aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-30 14:14:00 +0200
committerLars Knoll <lars.knoll@qt.io>2017-09-01 12:30:23 +0000
commitede52ec76ed0939ce41bb81843dc750241c6e78f (patch)
treecb39f94e9a5eb3a948d18bc1cb90e1c975c8636c /src
parent3bb642089b736b1ca1c0f722af2dc18bed3e068b (diff)
Add the current context and function object to CallData
Like this we can avoid creating Scope's when calling functions. Change-Id: I59b82c85eafd3a5437c233aba5f2e8330d5ce104 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4codegen.cpp9
-rw-r--r--src/qml/jsruntime/qv4context_p.h6
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp98
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp2
4 files changed, 57 insertions, 58 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index b881454f40..34cffc3faa 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1230,10 +1230,15 @@ Moth::StackSlot Codegen::pushArgs(ArgumentList *args)
int argc = 0;
for (ArgumentList *it = args; it; it = it->next)
++argc;
- int calldata = bytecodeGenerator->newRegisterArray(argc + 2); // 2 additional values for CallData
+ int calldata = bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + argc);
(void) Reference::fromConst(this, QV4::Encode(argc)).storeOnStack(calldata);
+#ifndef QT_NO_DEBUG
(void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + 1);
+ (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + 2);
+#endif
+ (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + 3);
+ Q_STATIC_ASSERT(sizeof(CallData) == 5 * sizeof(Value));
argc = 0;
for (ArgumentList *it = args; it; it = it->next) {
@@ -1241,7 +1246,7 @@ Moth::StackSlot Codegen::pushArgs(ArgumentList *args)
Reference e = expression(it->expression);
if (hasError)
break;
- (void) e.storeOnStack(calldata + 2 + argc);
+ (void) e.storeOnStack(calldata + sizeof(CallData)/sizeof(Value) - 1 + argc);
++argc;
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index f5ecc3ba1d..fdfcc7a345 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -88,6 +88,8 @@ struct CallData
return i < argc ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
}
+ Value function;
+ Value dummy_context;
Value thisObject;
Value args[1];
@@ -95,8 +97,8 @@ struct CallData
};
Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
-Q_STATIC_ASSERT(offsetof(CallData, thisObject) == 8);
-Q_STATIC_ASSERT(offsetof(CallData, args) == 16);
+Q_STATIC_ASSERT(offsetof(CallData, thisObject) == 3*sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, args) == 4*sizeof(Value));
namespace Heap {
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 6f82e0b98a..5790ddfe10 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -991,95 +991,88 @@ uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const
ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
- ScopedFunctionObject o(scope, l->globalGetter(l, engine));
- if (!o)
+ callData->function = l->globalGetter(l, engine);
+ if (!callData->function.isObject())
return engine->throwTypeError();
- return o->call(callData);
+ return static_cast<Object &>(callData->function).call(callData);
}
ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, CallData *callData)
{
Q_ASSERT(callData->thisObject.isUndefined());
- Scope scope(engine);
- ScopedObject base(scope);
ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context);
- ScopedValue func(scope, ctx.getPropertyAndBase(engine->id_eval(), base.getRef()));
- if (scope.engine->hasException)
+ callData->function = ctx.getPropertyAndBase(engine->id_eval(), &callData->thisObject);
+ if (engine->hasException)
return Encode::undefined();
- if (base)
- callData->thisObject = base;
-
- FunctionObject *o = func->as<FunctionObject>();
- if (!o) {
+ FunctionObject *f = callData->function.as<FunctionObject>();
+ if (!f) {
QString objectAsString = QStringLiteral("[null]");
- if (base)
- objectAsString = ScopedValue(scope, base.asReturnedValue())->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);
}
- if (o->d() == scope.engine->evalFunction()->d())
- return static_cast<EvalFunction *>(o)->evalCall(callData, true);
+ if (f->d() == engine->evalFunction()->d())
+ return static_cast<EvalFunction *>(f)->evalCall(callData, true);
- return o->call(callData);
+ return f->call(callData);
}
ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Q_ASSERT(callData->thisObject.isUndefined());
- Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex];
- ScopedObject base(scope);
ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context);
- ScopedValue func(scope, ctx.getPropertyAndBase(name, base.getRef()));
- if (scope.engine->hasException)
+ callData->function = ctx.getPropertyAndBase(static_cast<String *>(&callData->function), &callData->thisObject);
+ if (engine->hasException)
return Encode::undefined();
- if (base)
- callData->thisObject = base;
-
- FunctionObject *o = func->as<FunctionObject>();
- if (!o) {
+ FunctionObject *f = callData->function.as<FunctionObject>();
+ if (!f) {
QString objectAsString = QStringLiteral("[null]");
- if (base)
- objectAsString = ScopedValue(scope, base.asReturnedValue())->toQStringNoThrow();
- QString msg = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString()).arg(objectAsString);
+ if (!callData->thisObject.isUndefined())
+ objectAsString = callData->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);
}
- return o->call(callData);
+ return f->call(callData);
}
ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
- Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- ScopedObject baseObject(scope, callData->thisObject);
- if (!baseObject) {
+ if (!callData->thisObject.isObject()) {
Q_ASSERT(!callData->thisObject.isEmpty());
if (callData->thisObject.isNullOrUndefined()) {
- QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQStringNoThrow());
+ QString message = QStringLiteral("Cannot call method '%1' of %2")
+ .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
+ callData->thisObject.toQStringNoThrow());
return engine->throwTypeError(message);
}
- baseObject = RuntimeHelpers::convertToObject(scope.engine, callData->thisObject);
- if (!baseObject) // type error
+ callData->thisObject = RuntimeHelpers::convertToObject(engine, callData->thisObject);
+ if (engine->hasException) // type error
return Encode::undefined();
- callData->thisObject = baseObject.asReturnedValue();
}
- ScopedFunctionObject o(scope, baseObject->get(name));
- if (o) {
- return o->call(callData);
+ callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex];
+ callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function));
+ FunctionObject *f = callData->function.as<FunctionObject>();
+ if (f) {
+ return f->call(callData);
} else {
- QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow());
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function")
+ .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
+ callData->thisObject.toQStringNoThrow());
return engine->throwTypeError(error);
}
@@ -1099,23 +1092,21 @@ ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, uint i
ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, const Value &index, CallData *callData)
{
- Scope scope(engine);
- ScopedObject baseObject(scope, callData->thisObject.toObject(engine));
- ScopedString s(scope, index.toString(engine));
-
- if (scope.engine->hasException)
+ callData->thisObject = callData->thisObject.toObject(engine);
+ callData->function = index.toString(engine);
+ if (engine->hasException)
return Encode::undefined();
- callData->thisObject = baseObject;
- ScopedObject o(scope, baseObject->get(s));
- if (!o)
+ callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function));
+ if (!callData->function.isObject())
return engine->throwTypeError();
- return o->call(callData);
+ return static_cast<Object &>(callData->function).call(callData);
}
ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, CallData *callData)
{
+ callData->function = func;
if (Object *o = func.objectValue())
return o->call(callData);
@@ -1125,6 +1116,7 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu
ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &func, CallData *callData)
{
+ callData->function = func;
const Object *f = func.as<Object>();
if (!f)
return engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 9cca33bbb4..2a14aa28fa 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -499,7 +499,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat
Profiling::FunctionCallProfiler(engine, function);
Value *jsStackTop = engine->jsStackTop;
- engine->jsStackTop = reinterpret_cast<QV4::Value *>(callData) + 2 + (int)function->nFormals;
+ engine->jsStackTop = reinterpret_cast<QV4::Value *>(callData) + sizeof(CallData)/sizeof(Value) - 1 + (int)function->nFormals;
for (int i = callData->argc; i < (int)function->nFormals; ++i)
callData->args[i] = Encode::undefined();