aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp2
-rw-r--r--src/qml/jsruntime/qv4context.cpp76
-rw-r--r--src/qml/jsruntime/qv4context_p.h9
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp73
-rw-r--r--src/qml/jsruntime/qv4script.cpp34
6 files changed, 93 insertions, 106 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index b2db23d78c..aed2759383 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -60,7 +60,7 @@ QV4::CallContext *QV4DataCollector::findContext(int frame)
QV4::ExecutionContext *ctx = engine()->currentContext;
while (ctx) {
QV4::CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->function) {
+ if (cCtxt && cCtxt->d()->v4Function) {
if (frame < 1)
return cCtxt;
--frame;
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;
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 7bf58ab5c6..c985fdb24d 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -198,7 +198,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
- Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
+ Heap::CallContext *newCallContext(Function *f, CallData *callData);
Heap::WithContext *newWithContext(Heap::Object *with);
Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
@@ -230,6 +230,9 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ReturnedValue argument(int i) const {
return d()->callData->argument(i);
}
+
+ void call(Scope &scope, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0);
+ void simpleCall(Scope &scope, CallData *callData, QV4::Function *function);
};
struct Q_QML_EXPORT CallContext : public ExecutionContext
@@ -296,10 +299,6 @@ inline Heap::CallContext Heap::CallContext::createOnStack(ExecutionEngine *v4)
return ctxt;
}
-/* Function *f, int argc */
-#define requiredMemoryForExecutionContect(f, argc) \
- ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData)
-
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c438b99cf0..0520bfe216 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -866,9 +866,8 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
ExecutionContext *c = currentContext;
while (c) {
CallContext *callCtx = c->asCallContext();
- if (callCtx && callCtx->d()->function) {
- if (callCtx->d()->function->function)
- base.setUrl(callCtx->d()->function->function->sourceFile());
+ if (callCtx && callCtx->d()->v4Function) {
+ base.setUrl(callCtx->d()->v4Function->sourceFile());
break;
}
c = parentContext(c);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 21edf1d8d3..08d66bec6f 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -441,15 +441,13 @@ void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *call
InternalClass *ic = v4->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
ScopedObject obj(scope, v4->newObject(ic, proto));
-
callData->thisObject = obj.asReturnedValue();
- Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
- v4->pushContext(ctx);
- scope.result = Q_V4_PROFILE(v4, f->function());
+ QV4::Function *v4Function = f->function();
+ Q_ASSERT(v4Function);
- if (f->function()->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope);
+ ScopedContext c(scope, f->scope());
+ c->call(scope, callData, v4Function, f);
if (Q_UNLIKELY(v4->hasException)) {
scope.result = Encode::undefined();
@@ -467,16 +465,13 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData)
}
CHECK_STACK_LIMITS(v4, scope);
- ExecutionContextSaver ctxSaver(scope);
-
Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
- Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
- v4->pushContext(ctx);
- scope.result = Q_V4_PROFILE(v4, f->function());
+ QV4::Function *v4Function = f->function();
+ Q_ASSERT(v4Function);
- if (f->function()->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope);
+ ScopedContext c(scope, f->scope());
+ c->call(scope, callData, v4Function, f);
}
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
@@ -523,35 +518,17 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData
}
CHECK_STACK_LIMITS(v4, scope);
- ExecutionContextSaver ctxSaver(scope);
-
Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
callData->thisObject = v4->newObject(ic, proto);
- CallContext::Data ctx = CallContext::Data::createOnStack(v4);
- ctx.function = f->d();
- QV4::Function *ff = ctx.function->function;
- ctx.v4Function = ff;
- ctx.strictMode = ff->isStrict();
- ctx.callData = callData;
- ctx.compilationUnit = ff->compilationUnit;
- ctx.lookups = ctx.compilationUnit->runtimeLookups;
- ctx.constantTable = ctx.compilationUnit->constants;
- ctx.outer = ctx.function->scope;
- if (unsigned varCount = f->varCount())
- ctx.locals = scope.alloc(varCount);
- for (int i = callData->argc; i < static_cast<int>(ff->nFormals); ++i)
- callData->args[i] = Encode::undefined();
- v4->pushContext(&ctx);
- Q_ASSERT(v4->current == &ctx);
+ QV4::Function *v4Function = f->function();
+ Q_ASSERT(v4Function);
- scope.result = Q_V4_PROFILE(v4, ff);
-
- if (ff->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope);
+ ScopedContext c(scope, f->scope());
+ c->simpleCall(scope, callData, v4Function);
if (Q_UNLIKELY(v4->hasException)) {
scope.result = Encode::undefined();
@@ -569,31 +546,13 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal
}
CHECK_STACK_LIMITS(v4, scope);
- ExecutionContextSaver ctxSaver(scope);
-
Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
- CallContext::Data ctx = CallContext::Data::createOnStack(v4);
- ctx.function = f->d();
- QV4::Function *ff = ctx.function->function;
- ctx.v4Function = ff;
- ctx.strictMode = ff->isStrict();
- ctx.callData = callData;
- ctx.compilationUnit = ff->compilationUnit;
- ctx.lookups = ctx.compilationUnit->runtimeLookups;
- ctx.constantTable = ctx.compilationUnit->constants;
- ctx.outer = ctx.function->scope;
- if (unsigned varCount = f->varCount())
- ctx.locals = scope.alloc(varCount);
- for (int i = callData->argc; i < static_cast<int>(ff->nFormals); ++i)
- callData->args[i] = Encode::undefined();
- v4->pushContext(&ctx);
- Q_ASSERT(v4->current == &ctx);
-
- scope.result = Q_V4_PROFILE(v4, ff);
+ QV4::Function *v4Function = f->function();
+ Q_ASSERT(v4Function);
- if (ff->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope);
+ ScopedContext c(scope, f->scope());
+ c->simpleCall(scope, callData, v4Function);
}
Heap::Object *SimpleScriptFunction::protoForConstructor() const
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 8c27d36f50..25089855bb 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -72,7 +72,9 @@ struct QmlBindingWrapper : FunctionObject {
struct QmlBindingWrapper : FunctionObject {
V4_OBJECT2(QmlBindingWrapper, FunctionObject)
- static void call(const Managed *that, Scope &scope, CallData *callData);
+ static void call(const Managed *that, Scope &scope, CallData *callData) {
+ QV4::ScriptFunction::call(that, scope, callData);
+ }
};
}
@@ -94,30 +96,6 @@ void Heap::QmlBindingWrapper::init(QV4::QmlContext *scope, Function *f)
function->compilationUnit->addref();
}
-void QmlBindingWrapper::call(const Managed *that, Scope &scope, CallData *callData)
-{
- const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that);
- ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
- if (v4->hasException) {
- scope.result = Encode::undefined();
- return;
- }
- CHECK_STACK_LIMITS(v4, scope);
-
- ExecutionContextSaver ctxSaver(scope);
-
- QV4::Function *f = This->function();
- if (!f) {
- scope.result = QV4::Encode::undefined();
- return;
- }
-
- Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData));
- v4->pushContext(ctx);
-
- scope.result = Q_V4_PROFILE(v4, f);
-}
-
Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
, compilationUnit(compilationUnit), vmFunction(0), parseAsBinding(true)
@@ -228,10 +206,12 @@ ReturnedValue Script::run()
return Q_V4_PROFILE(engine, vmFunction);
} else {
Scoped<QmlContext> qml(valueScope, qmlContext.value());
- ScopedFunctionObject f(valueScope, engine->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
- f->call(valueScope, callData);
+ if (vmFunction->canUseSimpleFunction())
+ qml->simpleCall(valueScope, callData, vmFunction);
+ else
+ qml->call(valueScope, callData, vmFunction);
return valueScope.result.asReturnedValue();
}
}