aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-30 21:53:03 +0200
committerLars Knoll <lars.knoll@qt.io>2017-09-01 12:30:49 +0000
commit6df6f642ea382169533a0ad106be270b6d4b7d58 (patch)
tree143401796a060f2e9aef61f9e5bf9a5ffa34a73b /src
parentcc7a858698063649f9770a89949354e2b58ae288 (diff)
Move CallContext construction into a interpreter instruction
This will allow us to further cut down on function call overhead. To make this work, introduce a proper distinction between EvalCode and GlobalCode and use the correct compilation mode in all places. Change-Id: I070621142159b7416026347c9239200c5ed7a56b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp2
-rw-r--r--src/qml/compiler/qv4codegen.cpp9
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp3
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jsapi/qjsengine.cpp2
-rw-r--r--src/qml/jsruntime/qv4function_p.h3
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4script.cpp4
-rw-r--r--src/qml/jsruntime/qv4script_p.h6
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp5
-rw-r--r--src/qml/types/qquickworkerscript.cpp4
12 files changed, 29 insertions, 15 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index 625095b340..b0607c574a 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -101,7 +101,7 @@ void JavaScriptJob::run()
}
}
- QV4::Script script(ctx, this->script);
+ QV4::Script script(ctx, QV4::Compiler::EvalCode, this->script);
script.strictMode = ctx->d()->v4Function->isStrict();
// In order for property lookups in QML to work, we need to disable fast v4 lookups. That
// is a side-effect of inheritContext.
diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
index 5015c39c8e..1eaa2819af 100644
--- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
@@ -251,7 +251,7 @@ QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression)
QV4::ExecutionContext *ctx = m_engine->currentContext();
- QV4::Script script(ctx, expression);
+ QV4::Script script(ctx, QV4::Compiler::EvalCode, expression);
script.strictMode = ctx->d()->v4Function->isStrict();
// In order for property lookups in QML to work, we need to disable fast v4 lookups.
// That is a side-effect of inheritContext.
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 52f88905c5..deda792cc6 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1949,7 +1949,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
_module->functions.append(_context);
_context->functionIndex = _module->functions.count() - 1;
- _context->hasDirectEval |= _context->compilationMode == EvalCode || _module->debugMode; // Conditional breakpoints are like eval in the function
+ _context->hasDirectEval |= (_context->compilationMode == EvalCode || _context->compilationMode == GlobalCode || _module->debugMode); // Conditional breakpoints are like eval in the function
// ### still needed?
_context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount);
@@ -1963,7 +1963,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + _context->arguments.size());
int returnAddress = -1;
- bool _requiresReturnValue = (_context->compilationMode == QmlBinding || _context->compilationMode == EvalCode);
+ bool _requiresReturnValue = (_context->compilationMode == QmlBinding || _context->compilationMode == EvalCode || _context->compilationMode == GlobalCode);
qSwap(requiresReturnValue, _requiresReturnValue);
if (requiresReturnValue)
returnAddress = bytecodeGenerator->newRegister();
@@ -1974,6 +1974,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
bool allVarsEscape = _context->hasWith || _context->hasTry || _context->hasDirectEval;
+ if (!_context->canUseSimpleCall() && _context->compilationMode != GlobalCode && (_context->compilationMode != EvalCode || _context->isStrict)) {
+ Instruction::CreateCallContext createContext;
+ bytecodeGenerator->addInstruction(createContext);
+ }
+
// variables in global code are properties of the global context object, not locals as with other functions.
if (_context->compilationMode == FunctionCode || _context->compilationMode == QmlBinding) {
for (Context::MemberMap::iterator it = _context->members.begin(), end = _context->members.end(); it != end; ++it) {
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 601cdc551c..ee787c97c0 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -377,6 +377,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(SetException)
MOTH_END_INSTR(SetExceptionFlag)
+ MOTH_BEGIN_INSTR(CreateCallContext)
+ MOTH_END_INSTR(CreateCallContext)
+
MOTH_BEGIN_INSTR(PushCatchContext)
d << dumpRegister(reg, nFormals) << ", " << name;
MOTH_END_INSTR(PushCatchContext)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 8922493163..44bd2c0db9 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -120,6 +120,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0)
#define INSTR_GetException(op) INSTRUCTION(op, GetException, 0)
#define INSTR_SetException(op) INSTRUCTION(op, SetException, 0)
+#define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0)
#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, name, reg)
#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 1, reg)
#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg)
@@ -233,6 +234,7 @@ QT_BEGIN_NAMESPACE
F(ThrowException) \
F(GetException) \
F(SetException) \
+ F(CreateCallContext) \
F(PushCatchContext) \
F(PushWithContext) \
F(PopContext) \
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 416c04b7ad..bca4057fbe 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -445,7 +445,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::Scope scope(v4);
QV4::ScopedValue result(scope);
- QV4::Script script(v4->rootContext(), program, fileName, lineNumber);
+ QV4::Script script(v4->rootContext(), QV4::Compiler::EvalCode, program, fileName, lineNumber);
script.strictMode = false;
if (v4->currentStackFrame)
script.strictMode = v4->currentStackFrame->v4Function->isStrict();
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index d845eec4d9..c3b21b1685 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -106,9 +106,6 @@ struct Q_QML_EXPORT Function {
private:
static ReturnedValue call(CallData *callData, Function *function)
{
- if (!function->canUseSimpleCall)
- callData->context = ExecutionContext::newCallContext(static_cast<Heap::ExecutionContext *>(callData->context.m()), function, callData);
-
return function->execute(callData);
}
};
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 08bae8fe02..44fc4d5a65 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -360,7 +360,7 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
const QString code = scode->toQString();
bool inheritContext = !ctx->d()->v4Function->isStrict();
- Script script(ctx, code, QStringLiteral("eval code"));
+ Script script(ctx, QV4::Compiler::EvalCode, code, QStringLiteral("eval code"));
script.strictMode = (directCall && isStrict);
script.inheritContext = inheritContext;
script.parse();
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index d5f08041f6..a0aa1b1f2d 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -120,7 +120,7 @@ void Script::parse()
RuntimeCodegen cg(v4, &jsGenerator, strictMode);
if (inheritContext)
cg.setUseFastLookups(false);
- cg.generateFromProgram(sourceFile, sourceCode, program, &module, EvalCode);
+ cg.generateFromProgram(sourceFile, sourceCode, program, &module, compilationMode);
if (v4->hasException)
return;
@@ -219,7 +219,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compi
Codegen cg(unitGenerator, /*strict mode*/false);
cg.setUseFastLookups(false);
- cg.generateFromProgram(url.toString(), source, program, module, EvalCode);
+ cg.generateFromProgram(url.toString(), source, program, module, GlobalCode);
errors = cg.qmlErrors();
if (!errors.isEmpty()) {
if (reportedErrors)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 96c3b4b32d..8d7500eb13 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -54,6 +54,7 @@
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
#include "qv4qmlcontext_p.h"
+#include "private/qv4compilercontext_p.h"
#include <QQmlError>
@@ -88,9 +89,9 @@ struct ContextStateSaver {
};
struct Q_QML_EXPORT Script {
- Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionContext *scope, QV4::Compiler::CompilationMode mode, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , scope(scope), strictMode(false), inheritContext(false), parsed(false)
+ , scope(scope), strictMode(false), inheritContext(false), parsed(false), compilationMode(mode)
, vmFunction(0), parseAsBinding(false) {}
Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
@@ -109,6 +110,7 @@ struct Q_QML_EXPORT Script {
bool strictMode;
bool inheritContext;
bool parsed;
+ QV4::Compiler::CompilationMode compilationMode = QV4::Compiler::EvalCode;
QV4::PersistentValue qmlContext;
QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit;
Function *vmFunction;
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index da0b06dac7..3f5d187770 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -807,6 +807,11 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, name);
MOTH_END_INSTR(PushCatchContext)
+ MOTH_BEGIN_INSTR(CreateCallContext)
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(stack[CallData::Context].m());
+ stack[CallData::Context] = ExecutionContext::newCallContext(ctx, function, reinterpret_cast<CallData *>(stack));
+ MOTH_END_INSTR(CreateCallContext)
+
MOTH_BEGIN_INSTR(PushWithContext)
STORE_IP();
STORE_ACC();
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index ce7635218e..3acc615541 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -239,9 +239,9 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QV4::Scope scope(m_v4Engine);
QV4::ExecutionContext *globalContext = scope.engine->rootContext();
- onmessage.set(scope.engine, QV4::Script(globalContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ onmessage.set(scope.engine, QV4::Script(globalContext, QV4::Compiler::GlobalCode, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
- QV4::Script createsendscript(globalContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ QV4::Script createsendscript(globalContext, QV4::Compiler::GlobalCode, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
QV4::ScopedFunctionObject createsendconstructor(scope, createsendscript.run());
Q_ASSERT(!scope.engine->hasException);
QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));