aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4context.cpp
diff options
context:
space:
mode:
authorLars Knoll <[email protected]>2016-12-01 15:37:32 +0100
committerLars Knoll <[email protected]>2016-12-09 08:31:01 +0000
commitdeec039008c4df5ec2686459ee8c00801ee9d852 (patch)
tree0998823cc67809bbdf83424edd07d9175ea6c613 /src/qml/jsruntime/qv4context.cpp
parente54e4408bd03edc789370dd7670eb6da25e8a9bb (diff)
Refactor the calling code for (Simple)ScriptFunction
Factor the common code out into separate methods that can later on be reused by the QQmlJavaScriptExpression. Also ensure a CallContext is safe to use with a 0 FunctionObject. Change-Id: I1181a8e320b8c931d9df5b2c91bc143d8587fb60 Reviewed-by: Simon Hausmann <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4context.cpp')
-rw-r--r--src/qml/jsruntime/qv4context.cpp76
1 files changed, 63 insertions, 13 deletions
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 26f2f996a6..df0ecdd5d3 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -48,6 +48,8 @@
#include "qv4errorobject_p.h"
#include "qv4string_p.h"
#include "qv4qmlcontext_p.h"
+#include "qv4profiling_p.h"
+#include <private/qqmljavascriptexpression_p.h>
using namespace QV4;
@@ -57,28 +59,30 @@ DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
-Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData)
-{
- Q_ASSERT(function->function());
+/* Function *f, int argc */
+#define requiredMemoryForExecutionContect(f, argc) \
+ ((sizeof(CallContext::Data) + 7) & ~7) + \
+ sizeof(Value) * (f->compiledFunction->nLocals + qMax((uint)argc, f->nFormals)) + sizeof(CallData)
+Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData *callData)
+{
Heap::CallContext *c = d()->engine->memoryManager->allocManaged<CallContext>(
requiredMemoryForExecutionContect(function, callData->argc));
c->init(d()->engine, Heap::ExecutionContext::Type_CallContext);
- c->function = function->d();
- c->v4Function = function->d()->function;
+ c->v4Function = function;
- c->strictMode = function->strictMode();
- c->outer = function->scope();
+ c->strictMode = function->isStrict();
+ c->outer = this->d();
c->activation = 0;
- c->compilationUnit = function->function()->compilationUnit;
+ c->compilationUnit = function->compilationUnit;
c->lookups = c->compilationUnit->runtimeLookups;
c->constantTable = c->compilationUnit->constants;
c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
- const CompiledData::Function *compiledFunction = function->function()->compiledFunction;
+ const CompiledData::Function *compiledFunction = function->compiledFunction;
int nLocals = compiledFunction->nLocals;
if (nLocals)
std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue());
@@ -278,7 +282,7 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
break;
case Heap::ExecutionContext::Type_CallContext: {
QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
- Q_ASSERT(c->v4Function && c->function);
+ Q_ASSERT(c->v4Function);
ctx->callData->thisObject.mark(engine);
for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->v4Function->nFormals); ++arg)
ctx->callData->args[arg].mark(engine);
@@ -286,7 +290,8 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
c->locals[local].mark(engine);
if (c->activation)
c->activation->mark(engine);
- c->function->mark(engine);
+ if (c->function)
+ c->function->mark(engine);
break;
}
case Heap::ExecutionContext::Type_QmlContext: {
@@ -297,6 +302,51 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
}
}
+// Do a standard call with this execution context as the outer scope
+void ExecutionContext::call(Scope &scope, CallData *callData, Function *function, const FunctionObject *f)
+{
+ ExecutionContextSaver ctxSaver(scope);
+
+ Scoped<CallContext> ctx(scope, newCallContext(function, callData));
+ if (f)
+ ctx->d()->function = f->d();
+ scope.engine->pushContext(ctx);
+
+ scope.result = Q_V4_PROFILE(scope.engine, function);
+
+ if (function->hasQmlDependencies)
+ QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope);
+}
+
+// Do a simple, fast call with this execution context as the outer scope
+void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Function *function)
+{
+ Q_ASSERT(function->canUseSimpleFunction());
+
+ ExecutionContextSaver ctxSaver(scope);
+
+ CallContext::Data ctx = CallContext::Data::createOnStack(scope.engine);
+
+ ctx.strictMode = function->isStrict();
+ ctx.callData = callData;
+ ctx.v4Function = function;
+ ctx.compilationUnit = function->compilationUnit;
+ ctx.lookups = function->compilationUnit->runtimeLookups;
+ ctx.constantTable = function->compilationUnit->constants;
+ ctx.outer = this->d();
+ ctx.locals = scope.alloc(function->compiledFunction->nLocals);
+ for (int i = callData->argc; i < (int)function->nFormals; ++i)
+ callData->args[i] = Encode::undefined();
+
+ scope.engine->pushContext(&ctx);
+ Q_ASSERT(scope.engine->current == &ctx);
+
+ scope.result = Q_V4_PROFILE(scope.engine, function);
+
+ if (function->compiledFunction->hasQmlDependencies())
+ QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope);
+}
+
void ExecutionContext::setProperty(String *name, const Value &value)
{
Scope scope(this);
@@ -425,7 +475,7 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty)
return v->asReturnedValue();
}
- if (c->v4Function && c->v4Function->isNamedExpression()
+ if (c->function && c->v4Function->isNamedExpression()
&& name->equals(ScopedString(scope, c->v4Function->name())))
return c->function->asReturnedValue();
break;
@@ -503,7 +553,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
if (hasProperty)
return v->asReturnedValue();
}
- if (c->v4Function && c->v4Function->isNamedExpression()
+ if (c->function && c->v4Function->isNamedExpression()
&& name->equals(ScopedString(scope, c->v4Function->name())))
return c->function->asReturnedValue();
break;