diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-10-20 17:19:25 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-11-07 09:00:48 +0000 |
commit | e72306a6f2aeb2bddbb462c205db8fad2fb5a1a4 (patch) | |
tree | 3b83e1cead58d97c2b055283487500472ca7d698 /src/qml/jsruntime/qv4runtime.cpp | |
parent | bc5ff76e5afe6356bebb344c9a5d8b304e852f3c (diff) |
Further cleanup JSCallData
Avoid allocations on the JS stack if possible
Change-Id: I344cd6dceb6264314f9d22c94db22b22d1d24d14
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 100 |
1 files changed, 38 insertions, 62 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 00882d699c..42981949c9 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -429,12 +429,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH ScopedValue result(scope); ScopedValue conv(scope, object->get(meth1)); - JSCallData jsCallData(scope, 0); - jsCallData->thisObject = *object; - if (FunctionObject *o = conv->as<FunctionObject>()) { - jsCallData->function = o; - result = o->call(jsCallData); + result = o->call(object, nullptr, 0); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -444,8 +440,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH conv = object->get(meth2); if (FunctionObject *o = conv->as<FunctionObject>()) { - jsCallData->function = o; - result = o->call(jsCallData); + result = o->call(object, nullptr, 0); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -983,135 +978,116 @@ ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Va { Scope scope(engine); JSCallData callData(scope, argc, argv); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context); - callData->function = ctx.getPropertyAndBase(engine->id_eval(), &callData->thisObject); + ScopedFunctionObject function(scope, ctx.getPropertyAndBase(engine->id_eval(), callData->thisObject)); if (engine->hasException) return Encode::undefined(); - if (!callData->function.isFunctionObject()) { + if (!function) { QString objectAsString = QStringLiteral("[null]"); - if (!callData->thisObject.isUndefined()) - objectAsString = callData->thisObject.toQStringNoThrow(); + if (!callData->thisObject->isUndefined()) + objectAsString = callData->thisObject->toQStringNoThrow(); QString msg = QStringLiteral("Property 'eval' of object %2 is not a function").arg(objectAsString); return engine->throwTypeError(msg); } - FunctionObject &f = static_cast<FunctionObject &>(callData->function); - - if (f.d() == engine->evalFunction()->d()) - return static_cast<EvalFunction &>(f).evalCall(callData.callData(&f), true); + if (function->d() == engine->evalFunction()->d()) + return static_cast<EvalFunction *>(function.getPointer())->evalCall(callData.callData(function), true); - return f.call(&callData->thisObject, callData->args, callData->argc()); + return function->call(callData); } ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, Value *argv, int argc) { Scope scope(engine); - JSCallData callData(scope, argc, argv); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); - - callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]; + ScopedValue thisObject(scope); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context); - callData->function = ctx.getPropertyAndBase(static_cast<String *>(&callData->function), &callData->thisObject); + ScopedFunctionObject f(scope, ctx.getPropertyAndBase(name, thisObject)); if (engine->hasException) return Encode::undefined(); - if (!callData->function.isFunctionObject()) { + if (!f) { QString objectAsString = QStringLiteral("[null]"); - if (!callData->thisObject.isUndefined()) - objectAsString = callData->thisObject.toQStringNoThrow(); + if (!thisObject->isUndefined()) + objectAsString = thisObject->toQStringNoThrow(); QString msg = QStringLiteral("Property '%1' of object %2 is not a function") .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(), objectAsString); return engine->throwTypeError(msg); } - FunctionObject &f = static_cast<FunctionObject &>(callData->function); - return f.call(&callData->thisObject, callData->args, callData->argc()); + return f->call(thisObject, argv, argc); } ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc) { Scope scope(engine); - JSCallData callData(scope, argc, argv, base); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); - if (!callData->thisObject.isObject()) { - Q_ASSERT(!callData->thisObject.isEmpty()); - if (callData->thisObject.isNullOrUndefined()) { + if (!base->isObject()) { + Q_ASSERT(!base->isEmpty()); + if (base->isNullOrUndefined()) { QString message = QStringLiteral("Cannot call method '%1' of %2") .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(), - callData->thisObject.toQStringNoThrow()); + base->toQStringNoThrow()); return engine->throwTypeError(message); } - callData->thisObject = RuntimeHelpers::convertToObject(engine, callData->thisObject); + ScopedValue thisObject(scope, RuntimeHelpers::convertToObject(engine, *base)); if (engine->hasException) // type error return Encode::undefined(); + base = thisObject; } - callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]; - callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function)); + ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(name)); - if (!callData->function.isFunctionObject()) { + if (!f) { QString error = QStringLiteral("Property '%1' of object %2 is not a function") .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(), - callData->thisObject.toQStringNoThrow()); + base->toQStringNoThrow()); return engine->throwTypeError(error); } - FunctionObject &f = static_cast<FunctionObject &>(callData->function); - return f.call(&callData->thisObject, callData->args, callData->argc()); + return f->call(base, argv, argc); } ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc) { - Scope scope(engine); - JSCallData callData(scope, argc, argv, base); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); - - Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc()); Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; - callData->function = l->getter(l, engine, callData->thisObject); + // ok to have the value on the stack here + Value f = Value::fromReturnedValue(l->getter(l, engine, *base)); - if (!callData->function.isFunctionObject()) + if (!f.isFunctionObject()) return engine->throwTypeError(); - FunctionObject &f = static_cast<FunctionObject &>(callData->function); - return f.call(&callData->thisObject, callData->args, callData->argc()); + return static_cast<FunctionObject &>(f).call(base, argv, argc); } ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc) { Scope scope(engine); - JSCallData callData(scope, argc, argv, base); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); + ScopedValue thisObject(scope, base->toObject(engine)); + base = thisObject; - callData->thisObject = callData->thisObject.toObject(engine); - callData->function = index.toString(engine); + ScopedString str(scope, index.toString(engine)); if (engine->hasException) return Encode::undefined(); - callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function)); - if (!callData->function.isFunctionObject()) + ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str)); + if (!f) return engine->throwTypeError(); - return static_cast<FunctionObject &>(callData->function).call(&callData->thisObject, callData->args, callData->argc()); + return f->call(base, argv, argc); } ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, Value *argv, int argc) { if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - - Scope scope(engine); - JSCallData callData(scope, argc, argv); - Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop); - - return static_cast<const FunctionObject &>(func).call(&callData->thisObject, callData->args, callData->argc()); + return static_cast<const FunctionObject &>(func).call(nullptr, argv, argc); } |