aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-10-24 14:57:53 +0200
committerLars Knoll <lars.knoll@qt.io>2017-11-13 08:56:11 +0000
commit831ddc54932d2681712ca9fa3e94484ae11d59f7 (patch)
tree0cf4ad8756d9cae65f3c57f1c77c946eaf1f5749
parentd9b0878595e7ee2698ddc8c724657574d5fe4d4c (diff)
Cut out one more C++ layer when doing JS function calls
Change-Id: I0e2ac30b7e6d77fe41deb84a97b0a7f220437c6a Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4function_p.h8
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp22
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4script.cpp11
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp74
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h14
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp10
7 files changed, 74 insertions, 80 deletions
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 03529407ab..6c62881998 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -54,6 +54,7 @@
#include <private/qqmlglobal_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4context_p.h>
+#include <private/qv4vme_moth_p.h>
QT_BEGIN_NAMESPACE
@@ -63,12 +64,11 @@ struct Q_QML_EXPORT Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- ReturnedValue call(CallData *callData) {
- return code(callData, this);
+ ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
+ return Moth::VME::exec(this, thisObject, argv, argc, context);
}
-
- typedef ReturnedValue (*Code)(CallData *, Function *);
+ typedef ReturnedValue (*Code)(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc);
Code code;
const uchar *codeData;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index bd8bb9c8fb..1f86672a62 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -367,35 +367,21 @@ ReturnedValue ScriptFunction::callAsConstructor(const FunctionObject *fo, const
const ScriptFunction *f = static_cast<const ScriptFunction *>(fo);
Scope scope(v4);
- JSCallData callData(scope, argc, argv);
- CallData *cData = callData.callData(f);
InternalClass *ic = f->classForConstructor();
- cData->context = f->scope();
- cData->thisObject = v4->memoryManager->allocObject<Object>(ic);
+ ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic));
- QV4::Function *v4Function = f->function();
- Q_ASSERT(v4Function);
-
- ReturnedValue result = v4Function->call(cData);
+ ReturnedValue result = Moth::VME::exec(fo, thisObject, argv, argc);
if (Q_UNLIKELY(v4->hasException))
return Encode::undefined();
else if (!Value::fromReturnedValue(result).isObject())
- return cData->thisObject.asReturnedValue();
+ return thisObject->asReturnedValue();
return result;
}
ReturnedValue ScriptFunction::call(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
{
- const ScriptFunction *f = static_cast<const ScriptFunction *>(fo);
- Scope scope(f->engine());
- JSCallData callData(scope, argc, argv, thisObject);
- CallData *cData = callData.callData(f);
- cData->context = f->scope();
-
- QV4::Function *v4Function = f->function();
- Q_ASSERT(v4Function);
- return v4Function->call(cData);
+ return Moth::VME::exec(fo, thisObject, argv, argc);
}
void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 9ba65b2ce1..1049c5d3fa 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -374,20 +374,13 @@ ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc,
if (function->isStrict() || isStrict) {
ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function));
- JSCallData jsCallData(scope, 0);
- if (directCall)
- *jsCallData->thisObject = scope.engine->currentStackFrame->thisObject();
- else
- *jsCallData->thisObject = scope.engine->globalObject;
- return e->call(jsCallData);
+ ScopedValue thisObject(scope, directCall ? scope.engine->currentStackFrame->thisObject() : scope.engine->globalObject->asReturnedValue());
+ return e->call(thisObject, 0, 0);
}
- JSCallData jsCallData(scope);
- *jsCallData->thisObject = scope.engine->currentStackFrame->thisObject();
- CallData *cData = jsCallData.callData();
- cData->context = *ctx;
+ ScopedValue thisObject(scope, scope.engine->currentStackFrame->thisObject());
- return function->call(cData);
+ return function->call(thisObject, 0, 0, ctx);
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 7ac46bf594..901f2574da 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -149,17 +149,10 @@ ReturnedValue Script::run()
if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- QV4::JSCallData jsCall(valueScope);
- jsCall->thisObject = engine->globalObject;
- QV4::CallData *cData = jsCall.callData();
- cData->context = *context;
- return vmFunction->call(cData);
+ return vmFunction->call(engine->globalObject, 0, 0, context);
} else {
Scoped<QmlContext> qml(valueScope, qmlContext.value());
- JSCallData jsCall(valueScope);
- QV4::CallData *cData = jsCall.callData();
- cData->context = *qml;
- return vmFunction->call(cData);
+ return vmFunction->call(0, 0, 0, qml);
}
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 5b01e5a26b..58b54cf86c 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -497,46 +497,66 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs)
} \
} while (false)
-QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
+QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
{
qt_v4ResolvePendingBreakpointsHook();
+ ExecutionEngine *engine;
+ Value *stack;
+ CppStackFrame frame;
+ Function *function;
- MOTH_JUMP_TABLE;
+ {
+ Heap::ExecutionContext *scope;
+
+ quintptr d = reinterpret_cast<quintptr>(fo);
+ if (d & 0x1) {
+ // we don't have a FunctionObject, but a ExecData
+ ExecData *data = reinterpret_cast<ExecData *>(d - 1);
+ function = data->function;
+ scope = data->scope->d();
+ fo = nullptr;
+ } else {
+ function = fo->function();
+ scope = fo->scope();
+ }
- ExecutionEngine *engine = function->internalClass->engine;
- CHECK_STACK_LIMITS(engine);
- Profiling::FunctionCallProfiler profiler(engine, function);
- Q_UNUSED(profiler)
-
- Value *jsStackTop = engine->jsStackTop;
-
- Q_ASSERT(engine->jsStackTop == callData->args + callData->argc());
- Value *stack = reinterpret_cast<Value *>(callData);
- int stackSpaceToAdd = int(function->compiledFunction->nRegisters) - callData->argc();
- if (stackSpaceToAdd > 0) {
- // clear out remaining arguments and local registers
- for (int i = 0; i < stackSpaceToAdd; ++i)
- engine->jsStackTop[i] = Encode::undefined();
- engine->jsStackTop += stackSpaceToAdd;
+ engine = function->internalClass->engine;
+
+ stack = engine->jsStackTop;
+ CallData *callData = reinterpret_cast<CallData *>(stack);
+ callData->function = fo ? fo->asReturnedValue() : Encode::undefined();
+ callData->context = scope;
+ callData->accumulator = Encode::undefined();
+ callData->thisObject = thisObject ? *thisObject : Primitive::undefinedValue();
+ callData->setArgc(argc);
+
+ int jsStackFrameSize = offsetof(CallData, args)/sizeof(Value) + function->compiledFunction->nRegisters;
+ engine->jsStackTop += jsStackFrameSize;
+ memcpy(callData->args, argv, argc*sizeof(Value)); // ### Fixme: only copy nFormals
+ for (Value *v = callData->args + argc; v < engine->jsStackTop; ++v)
+ *v = Encode::undefined();
+
+ frame.parent = engine->currentStackFrame;
+ frame.v4Function = function;
+ frame.instructionPointer = function->codeData;
+ frame.jsFrame = callData;
+ engine->currentStackFrame = &frame;
}
+ CHECK_STACK_LIMITS(engine);
- CppStackFrame frame;
- frame.parent = engine->currentStackFrame;
- frame.v4Function = function;
- frame.instructionPointer = function->codeData;
- frame.jsFrame = callData;
- engine->currentStackFrame = &frame;
+ Profiling::FunctionCallProfiler profiler(engine, function);
+ if (QV4::Debugging::Debugger *debugger = engine->debugger())
+ debugger->enteringFunction();
const uchar *exceptionHandler = 0;
QV4::Value &accumulator = frame.jsFrame->accumulator;
QV4::ReturnedValue acc = Encode::undefined();
- if (QV4::Debugging::Debugger *debugger = engine->debugger())
- debugger->enteringFunction();
-
const uchar *code = function->codeData;
+ MOTH_JUMP_TABLE;
+
for (;;) {
MOTH_DISPATCH()
Q_UNREACHABLE(); // only reached when the dispatch doesn't jump somewhere
@@ -1321,7 +1341,7 @@ functionExit:
if (QV4::Debugging::Debugger *debugger = engine->debugger())
debugger->leavingFunction(ACC.asReturnedValue());
engine->currentStackFrame = frame.parent;
- engine->jsStackTop = jsStackTop;
+ engine->jsStackTop = stack;
return acc;
}
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 3a1e7b6637..dbf9ed3550 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -52,8 +52,6 @@
//
#include <private/qv4global_p.h>
-#include <private/qv4runtime_p.h>
-#include <private/qv4instr_moth_p.h>
QT_REQUIRE_CONFIG(qml_interpreter);
@@ -65,7 +63,17 @@ namespace Moth {
class VME
{
public:
- static QV4::ReturnedValue exec(CallData *callData, QV4::Function *);
+ struct ExecData {
+ QV4::Function *function;
+ const QV4::ExecutionContext *scope;
+ };
+ static inline
+ QV4::ReturnedValue exec(Function *v4Function, const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
+ ExecData data{v4Function, context};
+ quintptr d = reinterpret_cast<quintptr>(&data) | 0x1;
+ return exec(reinterpret_cast<const FunctionObject *>(d), thisObject, argv, argc);
+ }
+ static QV4::ReturnedValue exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc);
};
} // namespace Moth
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 0208db2d48..006611e089 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -226,17 +226,11 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
}
Q_ASSERT(m_qmlScope.valueRef());
- callData->context = *m_qmlScope.valueRef();
- QV4::ReturnedValue res = v4Function->call(callData);
+ QV4::ReturnedValue res = v4Function->call(&callData->thisObject, callData->args, callData->argc(), static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef()));
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, res);
if (v4Function->hasQmlDependencies) {
- QV4::Heap::ExecutionContext *c = static_cast<QV4::Heap::ExecutionContext *>(callData->context.m());
- // CreateCallContext might have been executed, and that will push a CallContext on top of
- // the current one. So, search back to the original QMLContext.
- while (c->type != QV4::Heap::ExecutionContext::Type_QmlContext)
- c = c->outer;
- QV4::Heap::QmlContext *qc = static_cast<QV4::Heap::QmlContext *>(c);
+ QV4::Heap::QmlContext *qc = m_qmlScope.as<QV4::QmlContext>()->d();
QQmlPropertyCapture::registerQmlDependencies(qc, v4, v4Function->compiledFunction);
}