diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-09-05 13:22:23 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-11 13:01:50 +0200 |
commit | 6e8e5d16e16d6ee683a5c06a24f8f202ed5239ff (patch) | |
tree | fa8e710ad0ee4ff6cc9738fa717883c74d452b95 /src | |
parent | 736afb8e9b3694efb8ca1fa8f3a8eeeaef530da2 (diff) |
Move CallData onto the JS stack
Change-Id: I22e853acfd2da337344b581bb0412c5f9930c510
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
30 files changed, 381 insertions, 340 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 578c388b44..405acd0f7c 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -60,6 +60,7 @@ #include <private/qv4functionobject_p.h> #include <private/qv4objectproto_p.h> #include <private/qv4exception_p.h> +#include <private/qv4scopedvalue_p.h> using namespace QV4; @@ -340,11 +341,11 @@ static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx) ok = false; db.transaction(); - CALLDATA(1); - d.thisObject = engine->global(); - d.args[0] = Value::fromObject(w); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = engine->global(); + callData->args[0] = Value::fromObject(w); try { - f->call(d); + f->call(callData); } catch (Exception &) { db.rollback(); throw; @@ -394,11 +395,11 @@ static Value qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, bool read db.transaction(); if (callback) { - CALLDATA(1); - d.thisObject = engine->global(); - d.args[0] = Value::fromObject(w); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = engine->global(); + callData->args[0] = Value::fromObject(w); try { - callback->call(d); + callback->call(callData); } catch (Exception &) { w->inTransaction = false; db.rollback(); @@ -677,10 +678,10 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) db->version = version; if (created && dbcreationCallback) { - CALLDATA(1); - d.thisObject = engine->global(); - d.args[0] = Value::fromObject(db); - dbcreationCallback->call(d); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = engine->global(); + callData->args[0] = Value::fromObject(db); + dbcreationCallback->call(callData); } args->setReturnValue(Value::fromObject(db)); diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index b737ee0073..2640ea5d1c 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -55,6 +55,7 @@ #include "private/qv8engine_p.h" #include <private/qv4mm_p.h> #include <private/qv4exception_p.h> +#include <private/qv4scopedvalue_p.h> QV4::Value QJSValuePrivate::getValue(QV4::ExecutionEngine *e) { @@ -505,20 +506,20 @@ QJSValue QJSValue::call(const QJSValueList &args) ExecutionEngine *engine = d->engine; assert(engine); - CALLDATA(args.length()); - d.thisObject = Value::fromObject(engine->globalObject); + ScopedCallData callData(engine, args.length()); + callData->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(); } - d.args[i] = args.at(i).d->getValue(engine); + callData->args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->call(d); + result = f->call(callData); } catch (Exception &e) { e.accept(ctx); result = e.value(); @@ -561,20 +562,20 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList return QJSValue(); } - CALLDATA(args.size()); - d.thisObject = instance.d->getValue(engine); + ScopedCallData callData(engine, args.size()); + callData->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(); } - d.args[i] = args.at(i).d->getValue(engine); + callData->args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->call(d); + result = f->call(callData); } catch (Exception &e) { e.accept(ctx); result = e.value(); @@ -610,19 +611,19 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) ExecutionEngine *engine = d->engine; assert(engine); - CALLDATA(args.size()); + ScopedCallData callData(engine, 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(); } - d.args[i] = args.at(i).d->getValue(engine); + callData->args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->construct(d); + result = f->construct(callData); } catch (Exception &e) { e.accept(ctx); result = e.value(); diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 7ac74c1197..f25fe496f9 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <qv4argumentsobject_p.h> #include <qv4alloca_p.h> +#include <qv4scopedvalue_p.h> using namespace QV4; @@ -129,10 +130,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const if (isMapped && attrs.isData()) { if (!attrs.isGeneric()) { - CALLDATA(1); - d.thisObject = Value::fromObject(this); - d.args[0] = desc.value; - map.setter()->call(d); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = Value::fromObject(this); + callData->args[0] = desc.value; + map.setter()->call(callData); } if (attrs.isWritable()) { *pd = map; diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 6fc661565d..08578e0002 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -42,6 +42,7 @@ #include "qv4arrayobject_p.h" #include "qv4sparsearray_p.h" #include "qv4objectproto_p.h" +#include "qv4scopedvalue_p.h" using namespace QV4; @@ -137,8 +138,8 @@ Value ArrayPrototype::method_toString(SimpleCallContext *ctx) QV4::Object *o = ctx->thisObject.toObject(ctx); FunctionObject *f = o->get(ctx->engine->newString("join")).asFunctionObject(); if (f) { - CALLDATA(0); - d.thisObject = ctx->thisObject; + ScopedCallData d(ctx->engine, 0); + d->thisObject = ctx->thisObject; return f->call(d); } return ObjectPrototype::method_toString(ctx); @@ -636,12 +637,12 @@ Value ArrayPrototype::method_every(SimpleCallContext *ctx) if (!exists) continue; - 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); + ScopedCallData callData(ctx->engine, 3); + callData->args[0] = v; + callData->args[1] = Value::fromDouble(k); + callData->args[2] = Value::fromObject(instance); + callData->thisObject = thisArg; + Value r = callback->call(callData); ok = r.toBoolean(); } return Value::fromBoolean(ok); @@ -665,12 +666,12 @@ Value ArrayPrototype::method_some(SimpleCallContext *ctx) if (!exists) continue; - 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); + ScopedCallData callData(ctx->engine, 3); + callData->thisObject = thisArg; + callData->args[0] = v; + callData->args[1] = Value::fromDouble(k); + callData->args[2] = Value::fromObject(instance); + Value r = callback->call(callData); if (r.toBoolean()) return Value::fromBoolean(true); } @@ -695,12 +696,12 @@ Value ArrayPrototype::method_forEach(SimpleCallContext *ctx) if (!exists) continue; - CALLDATA(3); - d.args[0] = v; - d.args[1] = Value::fromDouble(k); - d.args[2] = Value::fromObject(instance); - d.thisObject = thisArg; - callback->call(d); + ScopedCallData callData(ctx->engine, 3); + callData->thisObject = thisArg; + callData->args[0] = v; + callData->args[1] = Value::fromDouble(k); + callData->args[2] = Value::fromObject(instance); + callback->call(callData); } return Value::undefinedValue(); } @@ -727,12 +728,12 @@ Value ArrayPrototype::method_map(SimpleCallContext *ctx) if (!exists) continue; - 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); + ScopedCallData callData(ctx->engine, 3); + callData->thisObject = thisArg; + callData->args[0] = v; + callData->args[1] = Value::fromDouble(k); + callData->args[2] = Value::fromObject(instance); + Value mapped = callback->call(callData); a->arraySet(k, mapped); } return Value::fromObject(a); @@ -760,12 +761,12 @@ Value ArrayPrototype::method_filter(SimpleCallContext *ctx) if (!exists) continue; - 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); + ScopedCallData callData(ctx->engine, 3); + callData->thisObject = thisArg; + callData->args[0] = v; + callData->args[1] = Value::fromDouble(k); + callData->args[2] = Value::fromObject(instance); + Value selected = callback->call(callData); if (selected.toBoolean()) { a->arraySet(to, v); ++to; @@ -804,13 +805,13 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx) bool kPresent; Value v = instance->getIndexed(k, &kPresent); if (kPresent) { - 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); + ScopedCallData callData(ctx->engine, 4); + callData->thisObject = Value::undefinedValue(); + callData->args[0] = acc; + callData->args[1] = v; + callData->args[2] = Value::fromDouble(k); + callData->args[3] = Value::fromObject(instance); + acc = callback->call(callData); } ++k; } @@ -853,13 +854,13 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) bool kPresent; Value v = instance->getIndexed(k - 1, &kPresent); if (kPresent) { - 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); + ScopedCallData callData(ctx->engine, 4); + callData->thisObject = Value::undefinedValue(); + callData->args[0] = acc; + callData->args[1] = v; + callData->args[2] = Value::fromDouble(k - 1); + callData->args[3] = Value::fromObject(instance); + acc = callback->call(callData); } --k; } diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 29fdc333f8..0ad245f8fc 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -63,7 +63,8 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject * c->initBaseContext(Type_CallContext, engine, this); c->function = function; - c->arguments = d.args; + // ### + c->arguments = const_cast<Value *>(d.args); c->realArgumentCount = d.argc; c->argumentCount = d.argc; c->thisObject = d.thisObject; @@ -109,9 +110,7 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Ca c->initBaseContext(Type_CallContext, engine, this); c->function = function; - c->arguments = d.args; c->realArgumentCount = d.argc; - c->argumentCount = d.argc; c->thisObject = d.thisObject; c->strictMode = function->strictMode; @@ -138,7 +137,7 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Ca c->argumentCount = qMax((uint)d.argc, function->formalParameterCount); c->arguments = c->locals + function->varCount; if (d.argc) - ::memcpy(c->arguments, d.args, c->realArgumentCount * sizeof(Value)); + ::memcpy(c->arguments, d.args, d.argc * sizeof(Value)); if (d.argc < function->formalParameterCount) std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue()); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 9f25b8dc40..c76fbed3bf 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -42,7 +42,7 @@ #include "qv4dateobject_p.h" #include "qv4objectproto_p.h" -#include "qv4mm_p.h" +#include "qv4scopedvalue_p.h" #include <QtCore/qnumeric.h> #include <QtCore/qmath.h> #include <QtCore/QDateTime> @@ -55,11 +55,6 @@ #include <time.h> #include <private/qqmljsengine_p.h> -#include <private/qqmljslexer_p.h> -#include <private/qqmljsparser_p.h> -#include <private/qqmljsast_p.h> -#include <qv4jsir_p.h> -#include <qv4codegen_p.h> #include <wtf/MathExtras.h> @@ -1306,9 +1301,9 @@ Value DatePrototype::method_toJSON(SimpleCallContext *ctx) if (!toIso) ctx->throwTypeError(); - CALLDATA(0); - d.thisObject = ctx->thisObject; - return toIso->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = ctx->thisObject; + return toIso->call(callData); } void DatePrototype::timezoneUpdated() diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index bb01adf599..9fbefef586 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -48,6 +48,7 @@ #include "qv4mm_p.h" #include "qv4exception_p.h" #include "qv4arrayobject_p.h" +#include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -122,8 +123,8 @@ FunctionObject::~FunctionObject() Value FunctionObject::newInstance() { - CALLDATA(0); - return construct(d); + ScopedCallData callData(engine(), 0); + return construct(callData); } bool FunctionObject::hasInstance(Managed *that, const Value &value) @@ -306,23 +307,23 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx) len = ArrayPrototype::getLength(ctx, arr); } - CALLDATA(len); + ScopedCallData callData(ctx->engine, len); if (len) { if (arr->protoHasArray() || arr->hasAccessorProperty) { for (quint32 i = 0; i < len; ++i) - d.args[i] = arr->getIndexed(i); + callData->args[i] = arr->getIndexed(i); } else { int alen = qMin(len, arr->arrayDataLen); for (quint32 i = 0; i < alen; ++i) - d.args[i] = arr->arrayData[i].value; + callData->args[i] = arr->arrayData[i].value; for (quint32 i = alen; i < len; ++i) - d.args[i] = Value::undefinedValue(); + callData->args[i] = Value::undefinedValue(); } } - d.thisObject = thisArg; - return o->call(d); + callData->thisObject = thisArg; + return o->call(callData); } Value FunctionPrototype::method_call(SimpleCallContext *ctx) @@ -333,12 +334,12 @@ Value FunctionPrototype::method_call(SimpleCallContext *ctx) if (!o) ctx->throwTypeError(); - CALLDATA(ctx->argumentCount ? ctx->argumentCount - 1 : 0); + ScopedCallData callData(ctx->engine, 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); + ctx->arguments + ctx->argumentCount, callData->args); + callData->thisObject = thisArg; + return o->call(callData); } Value FunctionPrototype::method_bind(SimpleCallContext *ctx) @@ -402,6 +403,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) Value ScriptFunction::construct(Managed *that, const CallData &d) { ScriptFunction *f = static_cast<ScriptFunction *>(that); + SAVE_JS_STACK(f->scope); ExecutionEngine *v4 = f->engine(); InternalClass *ic = v4->objectClass; @@ -411,9 +413,8 @@ Value ScriptFunction::construct(Managed *that, const CallData &d) Object *obj = v4->newObject(ic); ExecutionContext *context = v4->current; - CallData dd = d; - dd.thisObject = Value::fromObject(obj); - ExecutionContext *ctx = context->newCallContext(f, dd); + const_cast<CallData &>(d).thisObject = Value::fromObject(obj); + ExecutionContext *ctx = context->newCallContext(f, d); Value result; try { @@ -424,6 +425,7 @@ Value ScriptFunction::construct(Managed *that, const CallData &d) } ctx->engine->popContext(); + CHECK_JS_STACK(f->scope); if (result.isObject()) return result; return Value::fromObject(obj); @@ -432,9 +434,10 @@ Value ScriptFunction::construct(Managed *that, const CallData &d) Value ScriptFunction::call(Managed *that, const CallData &d) { ScriptFunction *f = static_cast<ScriptFunction *>(that); + SAVE_JS_STACK(f->scope); void *stackSpace; ExecutionContext *context = f->engine()->current; - ExecutionContext *ctx = context->newCallContext(f, d); + CallContext *ctx = context->newCallContext(f, d); if (!f->strictMode && !d.thisObject.isObject()) { if (d.thisObject.isNullOrUndefined()) { @@ -452,6 +455,7 @@ Value ScriptFunction::call(Managed *that, const CallData &d) throw; } ctx->engine->popContext(); + CHECK_JS_STACK(f->scope); return result; } @@ -493,6 +497,7 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu Value SimpleScriptFunction::construct(Managed *that, const CallData &d) { SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that); + SAVE_JS_STACK(f->scope); ExecutionEngine *v4 = f->engine(); InternalClass *ic = v4->objectClass; @@ -503,9 +508,8 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d) ExecutionContext *context = v4->current; void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f)); - CallData dd = d; - dd.thisObject = Value::fromObject(obj); - ExecutionContext *ctx = context->newCallContext(stackSpace, f, dd); + const_cast<CallData &>(d).thisObject = Value::fromObject(obj); + ExecutionContext *ctx = context->newCallContext(stackSpace, f, d); Value result; try { @@ -516,6 +520,7 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d) } ctx->engine->popContext(); + CHECK_JS_STACK(f->scope); if (result.isObject()) return result; return Value::fromObject(obj); @@ -524,6 +529,7 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d) Value SimpleScriptFunction::call(Managed *that, const CallData &d) { SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that); + SAVE_JS_STACK(f->scope); void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f)); ExecutionContext *context = f->engine()->current; ExecutionContext *ctx = context->newCallContext(stackSpace, f, d); @@ -544,6 +550,7 @@ Value SimpleScriptFunction::call(Managed *that, const CallData &d) throw; } ctx->engine->popContext(); + CHECK_JS_STACK(f->scope); return result; } @@ -576,7 +583,8 @@ Value BuiltinFunctionOld::call(Managed *that, const CallData &d) ctx.initSimpleCallContext(f->scope->engine); ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? ctx.thisObject = d.thisObject; - ctx.arguments = d.args; + // ### const_cast + ctx.arguments = const_cast<Value *>(d.args); ctx.argumentCount = d.argc; v4->pushContext(&ctx); @@ -602,7 +610,8 @@ Value IndexedBuiltinFunction::call(Managed *that, const CallData &d) ctx.initSimpleCallContext(f->scope->engine); ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? ctx.thisObject = d.thisObject; - ctx.arguments = d.args; + // ### const_cast + ctx.arguments = const_cast<Value *>(d.args); ctx.argumentCount = d.argc; v4->pushContext(&ctx); @@ -650,20 +659,20 @@ Value BoundFunction::call(Managed *that, const CallData &dd) { BoundFunction *f = static_cast<BoundFunction *>(that); - 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); + ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd.argc); + callData->thisObject = f->boundThis; + memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); + memcpy(callData->args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value)); + return f->target->call(callData); } Value BoundFunction::construct(Managed *that, const CallData &dd) { BoundFunction *f = static_cast<BoundFunction *>(that); - 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); + ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd.argc); + memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); + memcpy(callData->args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value)); + return f->target->construct(callData); } bool BoundFunction::hasInstance(Managed *that, const Value &value) diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 3b06a6d884..d71643b3dc 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -47,6 +47,7 @@ #include "qv4debugging_p.h" #include "qv4script_p.h" #include "qv4exception_p.h" +#include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -390,9 +391,9 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d if (strictMode) { FunctionObject *e = FunctionObject::creatScriptFunction(ctx, function); - CALLDATA(0); - d.thisObject = ctx->thisObject; - return e->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = ctx->thisObject; + return e->call(callData); } ExecutionContext::EvalCode evalCode; @@ -441,7 +442,8 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d Value EvalFunction::call(Managed *that, const CallData &d) { // indirect call - return static_cast<EvalFunction *>(that)->evalCall(d.thisObject, d.args, d.argc, false); + // ### const_cast + return static_cast<EvalFunction *>(that)->evalCall(d.thisObject, const_cast<Value *>(d.args), d.argc, false); } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 9068d573f6..647cc7d2cb 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qv4include_p.h" +#include "qv4scopedvalue_p.h" #include <QtQml/qjsengine.h> #include <QtNetwork/qnetworkrequest.h> @@ -104,10 +105,10 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status) QV4::ExecutionContext *ctx = f->engine()->current; try { - CALLDATA(1); - d.thisObject = QV4::Value::fromObject(f->engine()->globalObject); - d.args[0] = status; - f->call(d); + QV4::ScopedCallData callData(ctx->engine, 1); + callData->thisObject = QV4::Value::fromObject(f->engine()->globalObject); + callData->args[0] = status; + f->call(callData); } catch (QV4::Exception &e) { e.accept(ctx); } diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 9c98d78743..82c7e8caed 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -44,6 +44,7 @@ #include <qv4stringobject_p.h> #include <qv4booleanobject_p.h> #include <qv4objectiterator_p.h> +#include <qv4scopedvalue_p.h> #include <qjsondocument.h> #include <qstack.h> #include <qstringlist.h> @@ -702,10 +703,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) { - CALLDATA(1); - d.thisObject = value; - d.args[0] = Value::fromString(ctx, key); - value = toJSON->call(d); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = value; + callData->args[0] = Value::fromString(ctx, key); + value = toJSON->call(callData); } } @@ -713,11 +714,11 @@ QString Stringify::Str(const QString &key, Value value) Object *holder = ctx->engine->newObject(); Value holderValue = Value::fromObject(holder); holder->put(ctx, QString(), value); - CALLDATA(2); - d.args[0] = Value::fromString(ctx, key); - d.args[1] = value; - d.thisObject = holderValue; - value = replacerFunction->call(d); + ScopedCallData callData(ctx->engine, 2); + callData->args[0] = Value::fromString(ctx, key); + callData->args[1] = value; + callData->thisObject = holderValue; + value = replacerFunction->call(callData); } if (Object *o = value.asObject()) { diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index e66055653e..5484f9772d 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qv4lookup_p.h" #include "qv4functionobject_p.h" +#include "qv4scopedvalue_p.h" QT_BEGIN_NAMESPACE @@ -202,9 +203,9 @@ void Lookup::getterAccessor0(Lookup *l, Value *result, const Value &object) if (!getter) { res = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = object; - res = getter->call(d); + ScopedCallData callData(o->engine(), 0); + callData->thisObject = object; + res = getter->call(callData); } if (result) *result = res; @@ -225,9 +226,9 @@ void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object) if (!getter) { res = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = object; - res = getter->call(d); + ScopedCallData callData(o->engine(), 0); + callData->thisObject = object; + res = getter->call(callData); } if (result) *result = res; @@ -251,9 +252,9 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object) if (!getter) { res = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = object; - res = getter->call(d); + ScopedCallData callData(o->engine(), 0); + callData->thisObject = object; + res = getter->call(callData); } if (result) *result = res; @@ -306,9 +307,9 @@ void Lookup::primitiveGetterAccessor0(Lookup *l, Value *result, const Value &obj if (!getter) { res = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = object; - res = getter->call(d); + ScopedCallData callData(o->engine(), 0); + callData->thisObject = object; + res = getter->call(callData); } if (result) *result = res; @@ -330,9 +331,9 @@ void Lookup::primitiveGetterAccessor1(Lookup *l, Value *result, const Value &obj if (!getter) { res = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = object; - res = getter->call(d); + ScopedCallData callData(o->engine(), 0); + callData->thisObject = object; + res = getter->call(callData); } if (result) *result = res; @@ -434,9 +435,9 @@ void Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *resu if (!getter) { *result = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = Value::undefinedValue(); - *result = getter->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = Value::undefinedValue(); + *result = getter->call(callData); } return; } @@ -453,9 +454,9 @@ void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *resu if (!getter) { *result = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = Value::undefinedValue(); - *result = getter->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = Value::undefinedValue(); + *result = getter->call(callData); } return; } @@ -475,9 +476,9 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu if (!getter) { *result = Value::undefinedValue(); } else { - CALLDATA(0); - d.thisObject = Value::undefinedValue(); - *result = getter->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = Value::undefinedValue(); + *result = getter->call(callData); } return; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index b77b1cd638..ddef198fe6 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -76,24 +76,19 @@ struct GCDeletable struct CallData { - Value thisObject; - Value *args; + // below is to be compatible with Value. Initialize tag to 0 +#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN + uint tag; +#endif 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() +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + uint tag; #endif + Value thisObject; + Value args[1]; +}; + struct ManagedVTable { Value (*call)(Managed *, const CallData &data); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index c3c444b7b9..c99b48191a 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -47,6 +47,7 @@ #include "qv4argumentsobject_p.h" #include "qv4mm_p.h" #include "qv4lookup_p.h" +#include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -134,19 +135,19 @@ Value Object::getValue(const Value &thisObject, const Property *p, PropertyAttri if (!getter) return Value::undefinedValue(); - CALLDATA(0); - d.thisObject = thisObject; - return getter->call(d); + ScopedCallData callData(getter->engine(), 0); + callData->thisObject = thisObject; + return getter->call(callData); } void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value) { if (attrs.isAccessor()) { if (pd->set) { - CALLDATA(1); - d.args[0] = value; - d.thisObject = Value::fromObject(this); - pd->set->call(d); + ScopedCallData callData(pd->set->engine(), 1); + callData->args[0] = value; + callData->thisObject = Value::fromObject(this); + pd->set->call(callData); return; } goto reject; @@ -773,10 +774,10 @@ void Object::internalPut(String *name, const Value &value) if (pd && attrs.isAccessor()) { assert(pd->setter() != 0); - CALLDATA(1); - d.args[0] = value; - d.thisObject = Value::fromObject(this); - pd->setter()->call(d); + ScopedCallData callData(engine(), 1); + callData->args[0] = value; + callData->thisObject = Value::fromObject(this); + pd->setter()->call(callData); return; } @@ -851,10 +852,10 @@ void Object::internalPutIndexed(uint index, const Value &value) if (pd && attrs.isAccessor()) { assert(pd->setter() != 0); - CALLDATA(1); - d.args[0] = value; - d.thisObject = Value::fromObject(this); - pd->setter()->call(d); + ScopedCallData callData(engine(), 1); + callData->args[0] = value; + callData->thisObject = Value::fromObject(this); + pd->setter()->call(callData); return; } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index fbf86645e2..23224fc1fe 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -42,6 +42,7 @@ #include "qv4objectproto_p.h" #include "qv4mm_p.h" +#include "qv4scopedvalue_p.h" #include <QtCore/qnumeric.h> #include <QtCore/qmath.h> #include <QtCore/QDateTime> @@ -385,9 +386,9 @@ Value ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx) FunctionObject *f = ts.asFunctionObject(); if (!f) ctx->throwTypeError(); - CALLDATA(0); - d.thisObject = Value::fromObject(o); - return f->call(d); + ScopedCallData callData(ctx->engine, 0); + callData->thisObject = Value::fromObject(o); + return f->call(callData); } Value ObjectPrototype::method_valueOf(SimpleCallContext *ctx) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 9e80c82165..fc26385cb7 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -62,6 +62,7 @@ #include <private/qv4objectproto_p.h> #include <private/qv4jsonobject_p.h> #include <private/qv4regexpobject_p.h> +#include <private/qv4scopedvalue_p.h> #include <QtQml/qjsvalue.h> #include <QtCore/qjsonarray.h> @@ -700,19 +701,19 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase QV4::ExecutionEngine *v4 = f->internalClass->engine; QV4::ExecutionContext *ctx = v4->current; - CALLDATA(argCount); - d.thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value(); + QV4::ScopedCallData callData(v4, argCount); + callData->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<QVariant>()) { - d.args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); + callData->args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); } else { - d.args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1])); + callData->args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1])); } } try { - f->call(d); + f->call(callData); } catch (QV4::Exception &e) { e.accept(ctx); QQmlError error; @@ -1009,13 +1010,13 @@ private: namespace { struct CallArgs { - CallArgs(int length, QV4::Value *args) : _length(length), _args(args) {} + CallArgs(int length, const QV4::Value *args) : _length(length), _args(args) {} int Length() const { return _length; } QV4::Value operator[](int idx) { return _args[idx]; } private: int _length; - QV4::Value *_args; + const QV4::Value *_args; }; } @@ -1667,7 +1668,7 @@ QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx) return QV4::Value::fromString(ctx, result); } -QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc) +QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) { if (!m_object) return QV4::Value::undefinedValue(); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 39af02f38b..7d8e778a5d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -135,7 +135,7 @@ private: QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal); QV4::Value method_toString(QV4::ExecutionContext *ctx); - QV4::Value method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc); + QV4::Value method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc); QPointer<QObject> m_object; int m_index; diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index c213c78aeb..ed4d3e3d17 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -45,6 +45,7 @@ #include "qv4objectproto_p.h" #include "qv4stringobject_p.h" #include "qv4mm_p.h" +#include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -358,10 +359,9 @@ Value RegExpPrototype::method_compile(SimpleCallContext *ctx) if (!r) ctx->throwTypeError(); - CallData d; - d.args = ctx->arguments; - d.argc = ctx->argumentCount; - RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>(); + ScopedCallData callData(ctx->engine, ctx->argumentCount); + memcpy(callData->args, ctx->arguments, ctx->argumentCount*sizeof(Value)); + RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>(); r->value = re->value; r->global = re->global; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 77b11a4fa8..649baaf441 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -449,18 +449,18 @@ Value __qmljs_object_default_value(Object *object, int typeHint) Value conv = object->get(meth1); if (FunctionObject *o = conv.asFunctionObject()) { - CALLDATA(0); - d.thisObject = Value::fromObject(object); - Value r = o->call(d); + ScopedCallData callData(engine, 0); + callData->thisObject = Value::fromObject(object); + Value r = o->call(callData); if (r.isPrimitive()) return r; } conv = object->get(meth2); if (FunctionObject *o = conv.asFunctionObject()) { - CALLDATA(0); - d.thisObject = Value::fromObject(object); - Value r = o->call(d); + ScopedCallData callData(engine, 0); + callData->thisObject = Value::fromObject(object); + Value r = o->call(callData); if (r.isPrimitive()) return r; } @@ -607,10 +607,10 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value return; } - CALLDATA(1); - d.args[0] = value; - d.thisObject = Value::fromObject(o); - setter->call(d); + ScopedCallData callData(ctx->engine, 1); + callData->thisObject = Value::fromObject(o); + callData->args[0] = value; + setter->call(callData); return; } } @@ -738,10 +738,9 @@ void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint i return; } - CallData d; - d.thisObject = thisObject; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject; + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -770,10 +769,9 @@ void __qmljs_call_activation_property(ExecutionContext *context, Value *result, return; } - CallData d; - d.thisObject = thisObject; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject; + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -800,10 +798,9 @@ void __qmljs_call_property(ExecutionContext *context, Value *result, const Value context->throwTypeError(error); } - CallData d; - d.thisObject = thisObject; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject; + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -820,10 +817,9 @@ void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, cons if (!o) context->throwTypeError(); - CallData d; - d.thisObject = thisObject; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject; + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -839,10 +835,9 @@ void __qmljs_call_element(ExecutionContext *context, Value *result, const Value if (!o) context->throwTypeError(); - CallData d; - d.thisObject = thisObject; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject; + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -853,10 +848,10 @@ void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *t Object *o = func.asObject(); if (!o) context->throwTypeError(); - CallData d; - d.thisObject = thisObject ? *thisObject : Value::undefinedValue(); - d.args = args; - d.argc = argc; + + ScopedCallData d(context->engine, argc); + d->thisObject = thisObject ? *thisObject : Value::undefinedValue(); + memcpy(d->args, args, argc*sizeof(Value)); Value res = o->call(d); if (result) *result = res; @@ -874,10 +869,9 @@ void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, u if (!f) context->throwTypeError(); - CallData d; - d.args = args; - d.argc = argc; - Value res = f->construct(d); + ScopedCallData callData(context->engine, argc); + memcpy(callData->args, args, argc*sizeof(Value)); + Value res = f->construct(callData); if (result) *result = res; } @@ -892,9 +886,8 @@ 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()) { - CallData d; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + memcpy(d->args, args, argc*sizeof(Value)); Value res = f->construct(d); if (result) *result = res; @@ -910,9 +903,8 @@ void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value func = thisObject->get(name); if (Object *f = func.asObject()) { - CallData d; - d.args = args; - d.argc = argc; + ScopedCallData d(context->engine, argc); + memcpy(d->args, args, argc*sizeof(Value)); Value res = f->construct(d); if (result) *result = res; diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 9d19025d83..4218065768 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -46,6 +46,9 @@ QT_BEGIN_NAMESPACE +#define SAVE_JS_STACK(ctx) Value *__jsStack = ctx->engine->jsStackTop +#define CHECK_JS_STACK(ctx) Q_ASSERT(__jsStack == ctx->engine->jsStackTop) + namespace QV4 { struct ScopedValueArray { @@ -100,17 +103,6 @@ struct ValueScope { struct ScopedValue { - ScopedValue(ExecutionEngine *engine) - { - ptr = engine->jsStackTop++; - } - - ScopedValue(ExecutionEngine *engine, const Value &v) - { - ptr = engine->jsStackTop++; - *ptr = v; - } - ScopedValue(const ValueScope &scope) { ptr = scope.engine->jsStackTop++; @@ -143,6 +135,45 @@ struct ScopedValue Value *ptr; }; +struct ScopedCallData { + ScopedCallData(ExecutionEngine *e, int argc) + : engine(e) + // ### this check currently won't work because of exceptions +#if 0 //ndef QT_NO_DEBUG + , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + 2) +#endif + { + Q_ASSERT(sizeof(CallData) == 3*sizeof(Value)); + ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + 2)); + ptr->tag = 0; + ptr->argc = argc; + } + + ~ScopedCallData() { +#if 0 //ndef QT_NO_DEBUG + engine->stackPop(size); + Q_ASSERT((void *)engine->jsStackTop == (void *)ptr); +#else + engine->jsStackTop = reinterpret_cast<Value *>(ptr); +#endif + } + + CallData *operator->() { + return ptr; + } + + operator const CallData &() const { + return *ptr; + } + + + ExecutionEngine *engine; +#if 0 //ndef QT_NO_DEBUG + int size; +#endif + CallData *ptr; +}; + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 17bd9b5eed..46e4d1485f 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -46,6 +46,7 @@ #include "qv4context_p.h" #include "qv4debugging_p.h" #include "qv4exception_p.h" +#include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -247,9 +248,9 @@ Value Script::run() } else { FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject()); - CALLDATA(0); - d.thisObject = Value::undefinedValue(); - return f->call(d); + ScopedCallData callData(scope->engine, 0); + callData->thisObject = Value::undefinedValue(); + return f->call(callData); } } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index b7f7317c76..29ca34910c 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -46,6 +46,7 @@ #include <private/qv4functionobject_p.h> #include <private/qv4arrayobject_p.h> #include <private/qqmlengine_p.h> +#include <private/qv4scopedvalue_p.h> QT_BEGIN_NAMESPACE @@ -351,11 +352,11 @@ public: bool operator()(typename Container::value_type lhs, typename Container::value_type rhs) { QV4::Managed *fun = this->m_compareFn.asManaged(); - 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); + ScopedCallData callData(fun->engine(), 2); + callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs); + callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs); + callData->thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject); + QV4::Value result = fun->call(callData); return result.toNumber() < 0; } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 52d98502a3..4ff261ca26 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -44,6 +44,7 @@ #include "qv4regexpobject_p.h" #include "qv4objectproto_p.h" #include "qv4mm_p.h" +#include "qv4scopedvalue_p.h" #include <QtCore/qnumeric.h> #include <QtCore/qmath.h> #include <QtCore/QDateTime> @@ -352,9 +353,9 @@ Value StringPrototype::method_match(SimpleCallContext *context) Value regexp = context->argumentCount ? context->arguments[0] : Value::undefinedValue(); RegExpObject *rx = regexp.as<RegExpObject>(); if (!rx) { - CALLDATA(1); - d.args[0] = regexp; - rx = context->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>(); + ScopedCallData callData(context->engine, 1); + callData->args[0] = regexp; + rx = context->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>(); } if (!rx) @@ -366,11 +367,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->regExpClass->prototype->get(context->engine->newString(QStringLiteral("exec")), 0).asFunctionObject(); - CALLDATA(1); - d.thisObject = Value::fromObject(rx); - d.args[0] = Value::fromString(s); + ScopedCallData callData(context->engine, 1); + callData->thisObject = Value::fromObject(rx); + callData->args[0] = Value::fromString(s); if (!global) - return exec->call(d); + return exec->call(callData); String *lastIndex = context->engine->newString(QStringLiteral("lastIndex")); rx->put(lastIndex, Value::fromInt32(0)); @@ -379,7 +380,7 @@ Value StringPrototype::method_match(SimpleCallContext *context) double previousLastIndex = 0; uint n = 0; while (1) { - Value result = exec->call(d); + Value result = exec->call(callData); if (result.isNull()) break; assert(result.isObject()); @@ -505,8 +506,8 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx) Value replaceValue = ctx->argument(1); if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) { result.reserve(string.length() + 10*numStringMatches); - CALLDATA(numCaptures + 2); - d.thisObject = Value::undefinedValue(); + ScopedCallData callData(ctx->engine, numCaptures + 2); + callData->thisObject = Value::undefinedValue(); int lastEnd = 0; for (int i = 0; i < numStringMatches; ++i) { for (int k = 0; k < numCaptures; ++k) { @@ -516,15 +517,15 @@ 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)); - d.args[k] = entry; + callData->args[k] = entry; } uint matchStart = matchOffsets[i * numCaptures * 2]; Q_ASSERT(matchStart >= lastEnd); uint matchEnd = matchOffsets[i * numCaptures * 2 + 1]; - d.args[numCaptures] = Value::fromUInt32(matchStart); - d.args[numCaptures + 1] = Value::fromString(ctx, string); + callData->args[numCaptures] = Value::fromUInt32(matchStart); + callData->args[numCaptures + 1] = Value::fromString(ctx, string); - Value replacement = searchCallback->call(d); + Value replacement = searchCallback->call(callData); result += string.midRef(lastEnd, matchStart - lastEnd); result += replacement.toString(ctx)->toQString(); lastEnd = matchEnd; @@ -566,9 +567,9 @@ Value StringPrototype::method_search(SimpleCallContext *ctx) Value regExpValue = ctx->argument(0); RegExpObject *regExp = regExpValue.as<RegExpObject>(); if (!regExp) { - CALLDATA(1); - d.args[0] = regExpValue; - regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(d); + ScopedCallData callData(ctx->engine, 1); + callData->args[0] = regExpValue; + regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData); regExp = regExpValue.as<RegExpObject>(); } uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint)); diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5f3a2e971c..a1399b4f43 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -62,6 +62,7 @@ #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> +#include <private/qv4scopedvalue_p.h> #include <QStack> #include <QStringList> @@ -1224,12 +1225,12 @@ 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()); - CALLDATA(2); - d.thisObject = QV4::Value::fromObject(v4engine->globalObject); - d.args[0] = object; - d.args[1] = valuemap; - f.asFunctionObject()->call(d); + QV4::Value f = QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject()); + QV4::ScopedCallData callData(v4engine, 2); + callData->thisObject = QV4::Value::fromObject(v4engine->globalObject); + callData->args[0] = object; + callData->args[1] = valuemap; + f.asFunctionObject()->call(callData); } d->completeCreate(); @@ -1372,11 +1373,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()); - CALLDATA(2); - d.thisObject = QV4::Value::fromObject(v4engine->globalObject); - d.args[0] = object; - d.args[1] = valuemap; - f.asFunctionObject()->call(d); + QV4::ScopedCallData callData(v4engine, 2); + callData->thisObject = QV4::Value::fromObject(v4engine->globalObject); + callData->args[0] = object; + callData->args[1] = valuemap; + f.asFunctionObject()->call(callData); } } @@ -1471,11 +1472,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()); - 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); + QV4::ScopedCallData callData(v4, 2); + callData->thisObject = QV4::Value::fromObject(v4->globalObject); + callData->args[0] = QV4::QObjectWrapper::wrap(v4, o); + callData->args[1] = valuemap; + f.asFunctionObject()->call(callData); } } @@ -1508,10 +1509,10 @@ void QmlIncubatorObject::statusChanged(Status s) if (QV4::FunctionObject *f = callback.asFunctionObject()) { QV4::ExecutionContext *ctx = f->engine()->current; try { - CALLDATA(1); - d.thisObject = QV4::Value::fromObject(this); - d.args[0] = QV4::Value::fromUInt32(s); - f->call(d); + QV4::ScopedCallData callData(ctx->engine, 1); + callData->thisObject = QV4::Value::fromObject(this); + callData->args[0] = QV4::Value::fromUInt32(s); + f->call(callData); } catch (QV4::Exception &e) { e.accept(ctx); QQmlError error; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 41be44a0a7..2974bbcfbe 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -47,6 +47,7 @@ #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> #include <private/qv4errorobject_p.h> +#include <private/qv4scopedvalue_p.h> QT_BEGIN_NAMESPACE @@ -125,8 +126,7 @@ QV4::Value QQmlJavaScriptExpression::evaluate(QQmlContextData *context, const QV4::Value &function, bool *isUndefined) { - QV4::Value args[QV4::Global::ReservedArgumentCount]; - return evaluate(context, function, 0, args, isUndefined); + return evaluate(context, function, 0, 0, isUndefined); } QV4::Value @@ -173,11 +173,10 @@ QQmlJavaScriptExpression::evaluate(QQmlContextData *context, This = value; } - QV4::CallData d; - d.thisObject = This; - d.args = args; - d.argc = argc; - result = function.asFunctionObject()->call(d); + QV4::ScopedCallData callData(v4, argc); + callData->thisObject = This; + memcpy(callData->args, args, argc*sizeof(QV4::Value)); + result = function.asFunctionObject()->call(callData); if (isUndefined) *isUndefined = result.isUndefined(); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 3d2d54ccfa..0079b9580f 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -55,6 +55,7 @@ #include <private/qv4object_p.h> #include <private/qv4variantobject_p.h> #include <private/qv4functionobject_p.h> +#include <private/qv4scopedvalue_p.h> QT_BEGIN_NAMESPACE @@ -926,16 +927,16 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) QQmlVMEMetaData::MethodData *data = metaData->methodData() + id; - CALLDATA(data->parameterCount); - d.thisObject = ep->v8engine()->global(); + QV4::ScopedCallData callData(function->engine(), data->parameterCount); + callData->thisObject = ep->v8engine()->global(); for (int ii = 0; ii < data->parameterCount; ++ii) - d.args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]); + callData->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(d); + result = function->call(callData); 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 211383ae58..8e7fa43667 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -53,6 +53,7 @@ #include <private/qv4engine_p.h> #include <private/qv4functionobject_p.h> #include <private/qqmlcontextwrapper_p.h> +#include <private/qv4scopedvalue_p.h> #include <QtCore/qobject.h> #include <QtQml/qjsvalue.h> @@ -1481,9 +1482,9 @@ void QQmlXMLHttpRequest::dispatchCallback(const Value &me) QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject); if (callingContext) { - CALLDATA(0); - d.thisObject = activationObject; - callback->call(d); + QV4::ScopedCallData callData(v4, 0); + callData->thisObject = activationObject; + callback->call(callData); } // if the callingContext object is no longer valid, then it has been diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 6737c14b17..5b43dd6192 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -57,6 +57,7 @@ #include <private/qqmlcontextwrapper_p.h> #include <private/qqmlvaluetypewrapper_p.h> #include <private/qqmllistwrapper_p.h> +#include <private/qv4scopedvalue_p.h> #include "qv4domerrors_p.h" #include "qv4sqlerrors_p.h" @@ -442,10 +443,10 @@ void QV8Engine::initializeGlobal() void QV8Engine::freezeObject(const QV4::Value &value) { - CALLDATA(1); - d.args[0] = value; - d.thisObject = QV4::Value::fromObject(m_v4Engine->globalObject); - m_freezeObject.value().asFunctionObject()->call(d); + QV4::ScopedCallData callData(m_v4Engine, 1); + callData->args[0] = value; + callData->thisObject = QV4::Value::fromObject(m_v4Engine->globalObject); + m_freezeObject.value().asFunctionObject()->call(callData); } void QV8Engine::gc() diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 9c486d9809..8f724fa2eb 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -136,13 +136,13 @@ private: QQmlV4Function(const QQmlV4Function &); QQmlV4Function &operator=(const QQmlV4Function &); - QQmlV4Function(int length, QV4::Value *args, + QQmlV4Function(int length, const QV4::Value *args, QV4::Value *rv, const QV4::Value &global, QQmlContextData *c, QV8Engine *e) : argc(length), args(args), retVal(rv), global(global), ctx(c), e(e) {} int argc; - QV4::Value *args; + const QV4::Value *args; QV4::Value *retVal; QV4::Value global; QQmlContextData *ctx; diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 8822eaecd0..26514ac6db 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -65,6 +65,7 @@ #include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> +#include <private/qv4scopedvalue_p.h> QT_BEGIN_NAMESPACE @@ -233,10 +234,10 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() QV4::Value function = QV4::Value::fromObject(m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, m_v4Engine->newString(QStringLiteral("sendMessage")), QQuickWorkerScriptEnginePrivate::sendMessage)); - CALLDATA(1); - d.args[0] = function; - d.thisObject = global(); - createsend = createsendconstructor->call(d); + QV4::ScopedCallData callData(m_v4Engine, 1); + callData->args[0] = function; + callData->thisObject = global(); + createsend = createsendconstructor->call(callData); } // Requires handle and context scope @@ -246,10 +247,10 @@ QV4::Value QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id) QV4::Value v = QV4::Value::undefinedValue(); QV4::ExecutionContext *ctx = f->internalClass->engine->current; try { - CALLDATA(1); - d.args[0] = QV4::Value::fromInt32(id); - d.thisObject = global(); - v = f->call(d); + QV4::ScopedCallData callData(m_v4Engine, 1); + callData->args[0] = QV4::Value::fromInt32(id); + callData->thisObject = global(); + v = f->call(callData); } catch (QV4::Exception &e) { e.accept(ctx); v = e.value(); @@ -351,11 +352,11 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d QV4::ExecutionContext *ctx = f->internalClass->engine->current; try { - CALLDATA(2); - d.thisObject = workerEngine->global(); - d.args[0] = script->object.value(); - d.args[1] = value; - f->call(d); + QV4::ScopedCallData callData(ctx->engine, 2); + callData->thisObject = workerEngine->global(); + callData->args[0] = script->object.value(); + callData->args[1] = value; + f->call(callData); } 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 2538cad211..52281a4fbc 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -54,6 +54,7 @@ #include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> +#include <private/qv4scopedvalue_p.h> QT_BEGIN_NAMESPACE @@ -663,10 +664,10 @@ void QQuickCanvasItem::updatePolish() QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(qmlEngine(this)); QV4::FunctionObject *f = animationCallbacks.value(key).value().asFunctionObject(); - CALLDATA(1); - d.thisObject = QV4::QObjectWrapper::wrap(v4, this); - d.args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t()); - f->call(d); + QV4::ScopedCallData callData(v4, 1); + callData->thisObject = QV4::QObjectWrapper::wrap(v4, this); + callData->args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t()); + f->call(callData); } } else { |