diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-30 21:53:03 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-09-01 12:30:49 +0000 |
commit | 6df6f642ea382169533a0ad106be270b6d4b7d58 (patch) | |
tree | 143401796a060f2e9aef61f9e5bf9a5ffa34a73b | |
parent | cc7a858698063649f9770a89949354e2b58ae288 (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>
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 9 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4globalobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 5 | ||||
-rw-r--r-- | src/qml/types/qquickworkerscript.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 6 | ||||
-rw-r--r-- | tools/qmljs/qmljs.cpp | 2 |
14 files changed, 33 insertions, 19 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"))); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 22251111d5..447151a59e 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -2338,7 +2338,7 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::Value &o, const QLatin1String(source) + QLatin1String(" })"); QV4::Scope scope(QV8Engine::getV4(engine)); - QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), functionSource); + QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource); program.inheritContext = true; QV4::ScopedFunctionObject function(scope, program.run()); @@ -2364,7 +2364,7 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::Value &o, QLatin1String(source) + QLatin1String(" })"); QV4::Scope scope(QV8Engine::getV4(engine)); - QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), functionSource); + QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource); program.inheritContext = true; QV4::ScopedFunctionObject function(scope, program.run()); @@ -2395,7 +2395,7 @@ static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::Value &o QV4::Scope scope(QV8Engine::getV4(engine)); - QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), functionSource); + QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource); program.inheritContext = true; QV4::ScopedFunctionObject function(scope, program.run()); diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp index 2250a501e7..bc2fcd4633 100644 --- a/tools/qmljs/qmljs.cpp +++ b/tools/qmljs/qmljs.cpp @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) const QString code = QString::fromUtf8(file.readAll()); file.close(); - script.reset(new QV4::Script(ctx, code, fn)); + script.reset(new QV4::Script(ctx, QV4::Compiler::GlobalCode, code, fn)); script->parseAsBinding = runAsQml; script->parse(); } |