From 4e0174a88e66b9d9471c98eeb7d8be6209ba5c98 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Aug 2017 10:59:53 +0200 Subject: Move line number information into a side table Don't emit any Line instructions anymore, and instead store the info in a side table in the compiled data, where it can be looked up on demand. Change-Id: Idcaf3bf4ee4129fd62f9e717bf1277dc6a34fe19 Reviewed-by: Erik Verbruggen --- .../qmltooling/qmldbg_debugger/qv4debugger.cpp | 4 +-- .../qmldbg_debugger/qv4debuggeragent.cpp | 8 ++--- .../qqmlnativedebugservice.cpp | 6 ++-- src/qml/compiler/qv4bytecodegenerator.cpp | 20 +++++++---- src/qml/compiler/qv4bytecodegenerator_p.h | 10 ++++-- src/qml/compiler/qv4codegen.cpp | 7 ++-- src/qml/compiler/qv4compileddata_p.h | 9 +++-- src/qml/compiler/qv4compiler.cpp | 11 +++++- src/qml/compiler/qv4compilercontext_p.h | 1 + src/qml/compiler/qv4instr_moth.cpp | 24 ++++++++----- src/qml/compiler/qv4instr_moth_p.h | 13 ++----- src/qml/jsruntime/qv4engine.cpp | 17 +++++++-- src/qml/jsruntime/qv4engine_p.h | 4 +-- src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 +- src/qml/jsruntime/qv4script.cpp | 2 +- src/qml/jsruntime/qv4sequenceobject.cpp | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 41 ++++++++++++++++------ src/qml/qml/qqmlvaluetypewrapper.cpp | 2 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 16 ++++----- 19 files changed, 128 insertions(+), 71 deletions(-) diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp index c95d4ea99f..4ef377922b 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -158,7 +158,7 @@ QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const { ExecutionState state; state.fileName = getFunction()->sourceFile(); - state.lineNumber = engine()->currentStackFrame->line; + state.lineNumber = engine()->currentStackFrame->lineNumber(); return state; } @@ -203,7 +203,7 @@ void QV4Debugger::maybeBreakAtInstruction() pauseAndWait(PauseRequest); } else if (m_haveBreakPoints) { if (QV4::Function *f = getFunction()) { - const int lineNumber = engine()->currentStackFrame->line; + const int lineNumber = engine()->currentStackFrame->lineNumber(); if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber)) pauseAndWait(BreakPointHit); } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp index 316fd87dd4..2a46dc60a6 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp @@ -84,11 +84,11 @@ void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseR break; body.insert(QStringLiteral("invocationText"), frame->function()); - body.insert(QStringLiteral("sourceLine"), frame->line - 1); - if (frame->column > 0) - body.insert(QStringLiteral("sourceColumn"), frame->column); + body.insert(QStringLiteral("sourceLine"), frame->lineNumber() - 1); +// if (frame->column > 0) +// body.insert(QStringLiteral("sourceColumn"), frame->column); QJsonArray breakPoints; - foreach (int breakPointId, breakPointIds(frame->source(), frame->line)) + foreach (int breakPointId, breakPointIds(frame->source(), frame->lineNumber())) breakPoints.push_back(breakPointId); body.insert(QStringLiteral("breakpoints"), breakPoints); script.insert(QStringLiteral("name"), frame->source()); diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp index c879c77fcd..5015c39c8e 100644 --- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp @@ -344,7 +344,7 @@ void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &a frame.insert(QStringLiteral("function"), functionName->toQString()); frame.insert(QStringLiteral("file"), function->sourceFile()); - int line = f->line; + int line = f->lineNumber(); frame.insert(QStringLiteral("line"), (line < 0 ? -line : line)); frameArray.push_back(frame); @@ -607,7 +607,7 @@ void NativeDebugger::maybeBreakAtInstruction() if (m_service->m_breakHandler->m_haveBreakPoints) { if (QV4::Function *function = getFunction()) { - const int lineNumber = m_engine->currentStackFrame->line; + const int lineNumber = m_engine->currentStackFrame->lineNumber(); if (reallyHitTheBreakPoint(function, lineNumber)) pauseAndWait(); } @@ -668,7 +668,7 @@ void NativeDebugger::pauseAndWait() if (QV4::CppStackFrame *frame = m_engine->currentStackFrame) { QV4::Function *function = frame->v4Function; event.insert(QStringLiteral("file"), function->sourceFile()); - int line = frame->line; + int line = frame->lineNumber(); event.insert(QStringLiteral("line"), (line < 0 ? -line : line)); } diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index c9b7c4ae7e..cae984a253 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include +#include #include QT_USE_NAMESPACE @@ -46,12 +47,7 @@ using namespace Moth; void BytecodeGenerator::setLocation(const QQmlJS::AST::SourceLocation &loc) { - if (static_cast(loc.startLine) == currentLine) - return; currentLine = static_cast(loc.startLine); - Instruction::Line line; - line.lineNumber = currentLine; - addInstruction(line); //### put line numbers in a side-table, not in the instruction stream } int BytecodeGenerator::newRegister() @@ -71,14 +67,23 @@ int BytecodeGenerator::newRegisterArray(int n) return t; } -QByteArray BytecodeGenerator::finalize() +void BytecodeGenerator::finalize(Compiler::Context *context) { QByteArray code; // content QVector instructionOffsets; + QVector lineNumbers; + currentLine = startLine; instructionOffsets.reserve(instructions.size()); for (const auto &i : qAsConst(instructions)) { + if (i.line != currentLine) { + Q_ASSERT(i.line > currentLine); + while (currentLine < i.line) { + lineNumbers.append(code.size()); + ++currentLine; + } + } instructionOffsets.append(code.size()); code.append(reinterpret_cast(&i.instr), i.size); } @@ -97,5 +102,6 @@ QByteArray BytecodeGenerator::finalize() memcpy(c, &linkedInstructionOffset, sizeof(ptrdiff_t)); } - return code; + context->code = code; + context->lineNumberMapping = lineNumbers; } diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index f53a720d2c..5ab8c880f3 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -65,6 +65,8 @@ namespace Moth { class BytecodeGenerator { public: + BytecodeGenerator(int line) + : startLine(line) {} struct Label { enum LinkMode { @@ -221,7 +223,7 @@ public: int newRegisterArray(int n); int registerCount() const { return regCount; } - QByteArray finalize(); + void finalize(Compiler::Context *context); template Jump addJumpInstruction(const InstrData &data) @@ -239,7 +241,7 @@ private: int addInstructionHelper(uint size, const Instr &i) { int pos = instructions.size(); - instructions.append({size, i}); + instructions.append({size, currentLine, i}); return pos; } @@ -251,6 +253,7 @@ private: struct I { uint size; + int line; Instr instr; }; @@ -262,7 +265,8 @@ private: public: int currentReg = 0; private: - int currentLine = -1; + int startLine = 0; + int currentLine = 0; }; } diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 273856e541..7e8a823939 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1932,7 +1932,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, // ### still needed? _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount); - BytecodeGenerator bytecode; + BytecodeGenerator bytecode(_context->line); BytecodeGenerator *savedBytecodeGenerator; savedBytecodeGenerator = bytecodeGenerator; bytecodeGenerator = &bytecode; @@ -2025,13 +2025,14 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bytecodeGenerator->addInstruction(Instruction::Ret()); } - _context->code = bytecodeGenerator->finalize(); + bytecodeGenerator->finalize(_context); _context->registerCount = bytecodeGenerator->registerCount(); static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); if (showCode) { qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict << "register count" << _context->registerCount; - QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size()); + QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size(), + _context->line, _context->lineNumberMapping); qDebug(); } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 91ef2eac20..445c3c7091 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x12 +#define QV4_DATA_STRUCTURE_VERSION 0x13 class QIODevice; class QQmlPropertyCache; @@ -217,6 +217,8 @@ struct Function quint32_le formalsOffset; quint32_le nLocals; quint32_le localsOffset; + quint32_le nLineNumbers; + quint32_le lineNumberOffset; quint32_le nInnerFunctions; quint32_le nRegisters; Location location; @@ -240,6 +242,7 @@ struct Function const quint32_le *formalsTable() const { return reinterpret_cast(reinterpret_cast(this) + formalsOffset); } const quint32_le *localsTable() const { return reinterpret_cast(reinterpret_cast(this) + localsOffset); } + const quint32_le *lineNumberTable() const { return reinterpret_cast(reinterpret_cast(this) + lineNumberOffset); } const quint32_le *qmlIdObjectDependencyTable() const { return reinterpret_cast(reinterpret_cast(this) + dependingIdObjectsOffset); } const quint32_le *qmlContextPropertiesDependencyTable() const { return reinterpret_cast(reinterpret_cast(this) + dependingContextPropertiesOffset); } const quint32_le *qmlScopePropertiesDependencyTable() const { return reinterpret_cast(reinterpret_cast(this) + dependingScopePropertiesOffset); } @@ -251,8 +254,8 @@ struct Function inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; } - static int calculateSize(int nFormals, int nLocals, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies) { - int trailingData = nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + + static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies) { + int trailingData = nFormals + nLocals + nLines + nInnerfunctions + nIdObjectDependencies + 2 * nPropertyDependencies; return align(align(sizeof(Function)) + size_t(trailingData) * sizeof(quint32)); } diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 84deb076b3..acfd5c56e7 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -316,6 +316,10 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->localsOffset = currentOffset; currentOffset += function->nLocals * sizeof(quint32); + function->nLineNumbers = irFunction->lineNumberMapping.size(); + function->lineNumberOffset = currentOffset; + currentOffset += function->nLineNumbers * sizeof(quint32); + function->nInnerFunctions = irFunction->nestedContexts.size(); function->nRegisters = irFunction->registerCount; @@ -358,6 +362,11 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte for (int i = 0; i < irFunction->locals.size(); ++i) locals[i] = getStringId(irFunction->locals.at(i)); + // write line numbers + quint32 *lineNumbers = (quint32 *)(f + function->lineNumberOffset); + for (int i = 0; i < irFunction->lineNumberMapping.size(); ++i) + lineNumbers[i] = irFunction->lineNumberMapping.at(i); + // write QML dependencies quint32_le *writtenDeps = (quint32_le *)(f + function->dependingIdObjectsOffset); for (int id : irFunction->idObjectDependencies) { @@ -428,7 +437,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp const int qmlIdDepsCount = f->idObjectDependencies.count(); const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); - nextOffset += QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->nestedContexts.size(), qmlIdDepsCount, qmlPropertyDepsCount); + nextOffset += QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->lineNumberMapping.size(), f->nestedContexts.size(), qmlIdDepsCount, qmlPropertyDepsCount); } if (option == GenerateWithStringTable) { diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 0a204d8c24..796f313b5c 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -133,6 +133,7 @@ struct Context { ControlFlow *controlFlow = 0; QByteArray code; + QVector lineNumberMapping; int maxNumberOfArguments = 0; bool hasDirectEval = false; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 9101537236..523fe88c02 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -59,6 +59,12 @@ static QByteArray alignedNumber(int n) { return number; } +static QByteArray alignedLineNumber(int line) { + if (line > 0) + return alignedNumber(static_cast(line)); + return QByteArray(" "); +} + static QString toString(QV4::ReturnedValue v) { #ifdef V4_BOOTSTRAP @@ -91,7 +97,7 @@ size_t absoluteInstructionOffset(const char *codeStart, const T &instr) QDebug d = qDebug(); \ d.noquote(); \ d.nospace(); \ - d << alignedNumber(int(code - start)).constData() << ": " << #I << " "; \ + d << alignedLineNumber(line) << alignedNumber(int(code - start)).constData() << ": " << #I << " "; \ code += InstrMeta::Size; \ #define MOTH_END_INSTR(I) } break; @@ -109,12 +115,18 @@ void dumpConstantTable(const Value *constants, uint count) << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n"; } -void dumpBytecode(const char *code, int len, int nLocals, int nFormals) +void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int startLine, const QVector &lineNumberMapping) { + int lastLine = -1; const char *start = code; const char *end = code + len; while (code < end) { const Instr *genericInstr = reinterpret_cast(code); + int line = startLine + ((code == start) ? 0 : lineNumberMapping.lastIndexOf(static_cast(code - start)) + 1); + if (line > lastLine) + lastLine = line; + else + line = -1; switch (genericInstr->common.instructionType) { MOTH_BEGIN_INSTR(LoadReg) @@ -516,14 +528,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals) MOTH_BEGIN_INSTR(Ret) MOTH_END_INSTR(Ret) - #ifndef QT_NO_QML_DEBUGGER +#ifndef QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(Debug) MOTH_END_INSTR(Debug) - - MOTH_BEGIN_INSTR(Line) - d << instr.lineNumber; - MOTH_END_INSTR(Line) - #endif // QT_NO_QML_DEBUGGER +#endif // QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(LoadQmlContext) d << instr.result.dump(nFormals); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 2ce0ff7b22..588ee7c110 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -64,7 +64,6 @@ QT_BEGIN_NAMESPACE #define MOTH_DEBUG_INSTR(F) #else #define MOTH_DEBUG_INSTR(F) \ - F(Line, line) \ F(Debug, debug) #endif @@ -236,9 +235,9 @@ inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackS // When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h void dumpConstantTable(const Value *constants, uint count); -void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals); -inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals) { - dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals); +void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1, const QVector &lineNumberMapping = QVector()); +inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, const QVector &lineNumberMapping = QVector()) { + dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals, startLine, lineNumberMapping); } union Instr @@ -256,13 +255,8 @@ union Instr }; #ifndef QT_NO_QML_DEBUGGING - struct instr_line { - MOTH_INSTR_HEADER - qint32 lineNumber; - }; struct instr_debug { MOTH_INSTR_HEADER - qint32 lineNumber; }; #endif // QT_NO_QML_DEBUGGING @@ -714,7 +708,6 @@ union Instr instr_common common; instr_ret ret; - instr_line line; instr_debug debug; instr_loadConst loadConst; instr_loadZero loadZero; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f5effc8c3b..ce21e0f7e5 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -794,6 +794,19 @@ QString CppStackFrame::function() const return v4Function->name()->toQString(); } +int CppStackFrame::lineNumber() const +{ + const QV4::CompiledData::Function *cf = v4Function->compiledFunction; + uint offset = static_cast(instructionPointer - v4Function->codeData - 1); // -1 because the instructionPointer points to the next instruction + const quint32_le *lineNumbers = cf->lineNumberTable(); + int nLineNumbers = cf->nLineNumbers; + for (int i = 0; i < nLineNumbers; ++i) { + if (offset <= lineNumbers[i]) + return cf->location.line + i; + } + return cf->location.line + nLineNumbers; +} + ReturnedValue CppStackFrame::thisObject() const { return jsFrame->stack[-(int)v4Function->nFormals - 1].asReturnedValue(); } @@ -809,8 +822,8 @@ StackTrace ExecutionEngine::stackTrace(int frameLimit) const QV4::StackFrame frame; frame.source = f->source(); frame.function = f->function(); - frame.line = f->line; - frame.column = f->column; + frame.line = f->lineNumber(); + frame.column = -1; stack.append(frame); --frameLimit; f = f->parent; diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 3c3e6e048f..4cee69ed33 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -107,14 +107,14 @@ struct Q_QML_EXPORT CppStackFrame { CppStackFrame *parent; Function *v4Function; JSStackFrame *jsFrame; - int line = -1; - int column = -1; + const uchar *instructionPointer; QString source() const; QString function() const; inline QV4::ExecutionContext *context() const { return static_cast(&jsFrame->context); } + int lineNumber() const; inline QV4::Heap::CallContext *callContext() const { Heap::ExecutionContext *ctx = static_cast(jsFrame->context).d();\ diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 13cad8c081..2d791092dd 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -472,7 +472,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP qCInfo(lcBindingRemoval, "Overwriting binding on %s::%s at %s:%d that was initially bound at %s", object->metaObject()->className(), qPrintable(property->name(object)), - qPrintable(stackFrame->source()), stackFrame->line, + qPrintable(stackFrame->source()), stackFrame->lineNumber(), qPrintable(qmlBinding->expressionIdentifier())); } } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index d3d8c1c291..23dfd3fc89 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -60,7 +60,7 @@ using namespace QV4; Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit) - : line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false) + : line(1), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false) , compilationUnit(compilationUnit), vmFunction(0), parseAsBinding(true) { if (qml) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 10043be917..54a32e0747 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -68,7 +68,7 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description QV4::CppStackFrame *stackFrame = v4->currentStackFrame; - retn.setLine(stackFrame->line); + retn.setLine(stackFrame->lineNumber()); retn.setUrl(QUrl(stackFrame->source())); QQmlEnginePrivate::warning(engine, retn); } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 6aad96c0c8..c7beed7b22 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -242,7 +242,7 @@ Q_NEVER_INLINE static void qt_v4CheckForBreak(QV4::CppStackFrame *frame) if (!qt_v4IsStepping && !qt_v4Breakpoints.size()) return; - const int lineNumber = frame->line; + const int lineNumber = frame->lineNumber(); QV4::Function *function = frame->v4Function; QString engineName = function->sourceFile(); @@ -273,10 +273,8 @@ Q_NEVER_INLINE static void qt_v4CheckForBreak(QV4::CppStackFrame *frame) } } -Q_NEVER_INLINE static void debug_slowPath(const QV4::Moth::Instr::instr_debug &instr, - QV4::ExecutionEngine *engine) +Q_NEVER_INLINE static void debug_slowPath(QV4::ExecutionEngine *engine) { - engine->currentStackFrame->line = instr.lineNumber; QV4::Debugging::Debugger *debugger = engine->debugger(); if (debugger && debugger->pauseAtNextOpportunity()) debugger->maybeBreakAtInstruction(); @@ -515,6 +513,7 @@ static bool compareEqualInt(Value lhs, int rhs) } } +#define STORE_IP() frame.instructionPointer = code QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callData, Heap::ExecutionContext *context, QV4::Function *function) { @@ -539,6 +538,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat CppStackFrame frame; frame.parent = engine->currentStackFrame; frame.v4Function = function; + frame.instructionPointer = function->codeData; engine->currentStackFrame = &frame; QV4::Value *stack = nullptr; @@ -631,6 +631,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(LoadClosure) MOTH_BEGIN_INSTR(LoadName) + STORE_IP(); STORE_ACCUMULATOR(Runtime::method_loadName(engine, instr.name)); MOTH_END_INSTR(LoadName) @@ -640,54 +641,65 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(LoadGlobalLookup) MOTH_BEGIN_INSTR(StoreNameStrict) + STORE_IP(); Runtime::method_storeNameStrict(engine, instr.name, accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreNameSloppy) MOTH_BEGIN_INSTR(StoreNameSloppy) + STORE_IP(); Runtime::method_storeNameSloppy(engine, instr.name, accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreNameSloppy) MOTH_BEGIN_INSTR(LoadElement) + STORE_IP(); STORE_ACCUMULATOR(Runtime::method_loadElement(engine, STACK_VALUE(instr.base), STACK_VALUE(instr.index))); MOTH_END_INSTR(LoadElement) MOTH_BEGIN_INSTR(LoadElementA) + STORE_IP(); STORE_ACCUMULATOR(Runtime::method_loadElement(engine, STACK_VALUE(instr.base), accumulator)); MOTH_END_INSTR(LoadElementA) MOTH_BEGIN_INSTR(StoreElement) + STORE_IP(); if (!Runtime::method_storeElement(engine, STACK_VALUE(instr.base), STACK_VALUE(instr.index), accumulator) && function->isStrict()) engine->throwTypeError(); CHECK_EXCEPTION; MOTH_END_INSTR(StoreElement) MOTH_BEGIN_INSTR(LoadProperty) + STORE_IP(); STORE_ACCUMULATOR(Runtime::method_loadProperty(engine, STACK_VALUE(instr.base), instr.name)); MOTH_END_INSTR(LoadProperty) MOTH_BEGIN_INSTR(LoadPropertyA) + STORE_IP(); STORE_ACCUMULATOR(Runtime::method_loadProperty(engine, accumulator, instr.name)); MOTH_END_INSTR(LoadPropertyA) MOTH_BEGIN_INSTR(GetLookup) + STORE_IP(); QV4::Lookup *l = function->compilationUnit->runtimeLookups + instr.index; STORE_ACCUMULATOR(l->getter(l, engine, STACK_VALUE(instr.base))); MOTH_END_INSTR(GetLookup) MOTH_BEGIN_INSTR(GetLookupA) + STORE_IP(); QV4::Lookup *l = function->compilationUnit->runtimeLookups + instr.index; STORE_ACCUMULATOR(l->getter(l, engine, accumulator)); MOTH_END_INSTR(GetLookupA) MOTH_BEGIN_INSTR(StoreProperty) + STORE_IP(); if (!Runtime::method_storeProperty(engine, STACK_VALUE(instr.base), instr.name, accumulator) && function->isStrict()) engine->throwTypeError(); CHECK_EXCEPTION; MOTH_END_INSTR(StoreProperty) MOTH_BEGIN_INSTR(SetLookup) + STORE_IP(); QV4::Lookup *l = function->compilationUnit->runtimeLookups + instr.index; if (!l->setter(l, engine, STACK_VALUE(instr.base), accumulator) && function->isStrict()) engine->throwTypeError(); @@ -717,39 +729,46 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(LoadIdObject) MOTH_BEGIN_INSTR(CallValue) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_callValue(engine, accumulator, callData)); MOTH_END_INSTR(CallValue) MOTH_BEGIN_INSTR(CallProperty) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); callData->thisObject = STACK_VALUE(instr.base); STORE_ACCUMULATOR(Runtime::method_callProperty(engine, instr.name, callData)); MOTH_END_INSTR(CallProperty) MOTH_BEGIN_INSTR(CallPropertyLookup) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); callData->thisObject = STACK_VALUE(instr.base); STORE_ACCUMULATOR(Runtime::method_callPropertyLookup(engine, instr.lookupIndex, callData)); MOTH_END_INSTR(CallPropertyLookup) MOTH_BEGIN_INSTR(CallElement) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); callData->thisObject = STACK_VALUE(instr.base); STORE_ACCUMULATOR(Runtime::method_callElement(engine, STACK_VALUE(instr.index), callData)); MOTH_END_INSTR(CallElement) MOTH_BEGIN_INSTR(CallName) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_callName(engine, instr.name, callData)); MOTH_END_INSTR(CallName) MOTH_BEGIN_INSTR(CallPossiblyDirectEval) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_callPossiblyDirectEval(engine, callData)); MOTH_END_INSTR(CallPossiblyDirectEval) MOTH_BEGIN_INSTR(CallGlobalLookup) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_callGlobalLookup(engine, instr.index, callData)); MOTH_END_INSTR(CallGlobalLookup) @@ -760,6 +779,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(SetExceptionHandler) MOTH_BEGIN_INSTR(ThrowException) + STORE_IP(); Runtime::method_throwException(engine, accumulator); goto catchException; MOTH_END_INSTR(ThrowException) @@ -783,6 +803,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(PushCatchContext) MOTH_BEGIN_INSTR(PushWithContext) + STORE_IP(); accumulator = accumulator.toObject(engine); CHECK_EXCEPTION; STACK_VALUE(instr.reg) = Runtime::method_pushWithContext(accumulator, static_cast(engine)); @@ -803,6 +824,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_BEGIN_INSTR(DeleteMember) if (!Runtime::method_deleteMember(engine, STACK_VALUE(instr.base), instr.member)) { if (function->isStrict()) { + STORE_IP(); engine->throwTypeError(); goto catchException; } @@ -815,6 +837,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_BEGIN_INSTR(DeleteSubscript) if (!Runtime::method_deleteElement(engine, STACK_VALUE(instr.base), STACK_VALUE(instr.index))) { if (function->isStrict()) { + STORE_IP(); engine->throwTypeError(); goto catchException; } @@ -827,6 +850,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_BEGIN_INSTR(DeleteName) if (!Runtime::method_deleteName(engine, instr.name)) { if (function->isStrict()) { + STORE_IP(); QString name = function->compilationUnit->runtimeStrings[instr.name]->toQString(); engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name)); goto catchException; @@ -880,6 +904,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(ConvertThisToObject) MOTH_BEGIN_INSTR(Construct) + STORE_IP(); QV4::CallData *callData = reinterpret_cast(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_construct(engine, STACK_VALUE(instr.func), callData)); MOTH_END_INSTR(Construct) @@ -1171,14 +1196,8 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat #ifndef QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(Debug) - debug_slowPath(instr, engine); + debug_slowPath(engine); MOTH_END_INSTR(Debug) - - MOTH_BEGIN_INSTR(Line) - frame.line = instr.lineNumber; - if (Q_UNLIKELY(qt_v4IsDebugging)) - qt_v4CheckForBreak(&frame); - MOTH_END_INSTR(Line) #endif // QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(LoadQmlContext) diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 532c4b1454..ebca199ee1 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -479,7 +479,7 @@ bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) referenceObject->metaObject()->className(), referenceObject->metaObject()->property(referencePropertyIndex).name(), qPrintable(qmlBinding->expressionIdentifier()), metaObject->property(pd->coreIndex()).name(), - qPrintable(stackFrame->source()), stackFrame->line); + qPrintable(stackFrame->source()), stackFrame->lineNumber()); } } QQmlPropertyPrivate::removeBinding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex())); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 96c898e6d4..dcbe2b2a5b 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1342,7 +1342,7 @@ void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *originalFunction QQmlSourceLocation QQmlBindingFunction::currentLocation() const { QV4::CppStackFrame *frame = engine()->currentStackFrame; - return QQmlSourceLocation(frame->source(), frame->line, 0); + return QQmlSourceLocation(frame->source(), frame->lineNumber(), 0); } DEFINE_OBJECT_VTABLE(QQmlBindingFunction); @@ -1552,7 +1552,7 @@ static ReturnedValue writeToConsole(const BuiltinFunction *b, CallData *callData QV4::CppStackFrame *frame = v4->currentStackFrame; const QByteArray baSource = frame->source().toUtf8(); const QByteArray baFunction = frame->function().toUtf8(); - QMessageLogger logger(baSource.constData(), frame->line, baFunction.constData(), loggingCategory->categoryName()); + QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData(), loggingCategory->categoryName()); switch (logType) { case Log: @@ -1606,7 +1606,7 @@ ReturnedValue ConsoleObject::method_profile(const BuiltinFunction *b, CallData * QV4::CppStackFrame *frame = v4->currentStackFrame; const QByteArray baSource = frame->source().toUtf8(); const QByteArray baFunction = frame->function().toUtf8(); - QMessageLogger logger(baSource.constData(), frame->line, baFunction.constData()); + QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData()); QQmlProfilerService *service = QQmlDebugConnector::service(); if (!service) { logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX."); @@ -1626,7 +1626,7 @@ ReturnedValue ConsoleObject::method_profileEnd(const BuiltinFunction *b, CallDat QV4::CppStackFrame *frame = v4->currentStackFrame; const QByteArray baSource = frame->source().toUtf8(); const QByteArray baFunction = frame->function().toUtf8(); - QMessageLogger logger(baSource.constData(), frame->line, baFunction.constData()); + QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData()); QQmlProfilerService *service = QQmlDebugConnector::service(); if (!service) { @@ -1684,10 +1684,10 @@ ReturnedValue ConsoleObject::method_count(const BuiltinFunction *b, CallData *ca QString scriptName = frame->source(); - int value = v8engine->consoleCountHelper(scriptName, frame->line, frame->column); + int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), -1); QString message = name + QLatin1String(": ") + QString::number(value); - QMessageLogger(qPrintable(scriptName), frame->line, + QMessageLogger(qPrintable(scriptName), frame->lineNumber(), qPrintable(frame->function())) .debug("%s", qPrintable(message)); @@ -1705,7 +1705,7 @@ ReturnedValue ConsoleObject::method_trace(const BuiltinFunction *b, CallData *ca QString stack = jsStack(v4); QV4::CppStackFrame *frame = v4->currentStackFrame; - QMessageLogger(frame->source().toUtf8().constData(), frame->line, + QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(), frame->function().toUtf8().constData()) .debug("%s", qPrintable(stack)); @@ -1737,7 +1737,7 @@ ReturnedValue ConsoleObject::method_assert(const BuiltinFunction *b, CallData *c QString stack = jsStack(v4); QV4::CppStackFrame *frame = v4->currentStackFrame; - QMessageLogger(frame->source().toUtf8().constData(), frame->line, + QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(), frame->function().toUtf8().constData()) .critical("%s\n%s",qPrintable(message), qPrintable(stack)); -- cgit v1.2.3