From 6df6f642ea382169533a0ad106be270b6d4b7d58 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 30 Aug 2017 21:53:03 +0200 Subject: 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 --- src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp | 2 +- .../qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp | 2 +- src/qml/compiler/qv4codegen.cpp | 9 +++++++-- src/qml/compiler/qv4instr_moth.cpp | 3 +++ src/qml/compiler/qv4instr_moth_p.h | 2 ++ src/qml/jsapi/qjsengine.cpp | 2 +- src/qml/jsruntime/qv4function_p.h | 3 --- src/qml/jsruntime/qv4globalobject.cpp | 2 +- src/qml/jsruntime/qv4script.cpp | 4 ++-- src/qml/jsruntime/qv4script_p.h | 6 ++++-- src/qml/jsruntime/qv4vme_moth.cpp | 5 +++++ src/qml/types/qquickworkerscript.cpp | 4 ++-- 12 files changed, 29 insertions(+), 15 deletions(-) (limited to 'src') 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(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 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 @@ -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 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(stack[CallData::Context].m()); + stack[CallData::Context] = ExecutionContext::newCallContext(ctx, function, reinterpret_cast(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"))); -- cgit v1.2.3