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 <erik.verbruggen@qt.io>
This commit is contained in:
parent
3c201dd0d9
commit
4e0174a88e
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <private/qv4bytecodegenerator_p.h>
|
||||
#include <private/qv4compilercontext_p.h>
|
||||
#include <private/qqmljsastfwd_p.h>
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
@ -46,12 +47,7 @@ using namespace Moth;
|
|||
|
||||
void BytecodeGenerator::setLocation(const QQmlJS::AST::SourceLocation &loc)
|
||||
{
|
||||
if (static_cast<int>(loc.startLine) == currentLine)
|
||||
return;
|
||||
currentLine = static_cast<int>(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<int> instructionOffsets;
|
||||
QVector<int> 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<const char *>(&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;
|
||||
}
|
||||
|
|
|
@ -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<int InstrT>
|
||||
Jump addJumpInstruction(const InstrData<InstrT> &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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
|
||||
const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
|
||||
const quint32_le *lineNumberTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + lineNumberOffset); }
|
||||
const quint32_le *qmlIdObjectDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingIdObjectsOffset); }
|
||||
const quint32_le *qmlContextPropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingContextPropertiesOffset); }
|
||||
const quint32_le *qmlScopePropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -133,6 +133,7 @@ struct Context {
|
|||
|
||||
ControlFlow *controlFlow = 0;
|
||||
QByteArray code;
|
||||
QVector<int> lineNumberMapping;
|
||||
|
||||
int maxNumberOfArguments = 0;
|
||||
bool hasDirectEval = false;
|
||||
|
|
|
@ -59,6 +59,12 @@ static QByteArray alignedNumber(int n) {
|
|||
return number;
|
||||
}
|
||||
|
||||
static QByteArray alignedLineNumber(int line) {
|
||||
if (line > 0)
|
||||
return alignedNumber(static_cast<int>(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<int(Instr::I)>::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<int> &lineNumberMapping)
|
||||
{
|
||||
int lastLine = -1;
|
||||
const char *start = code;
|
||||
const char *end = code + len;
|
||||
while (code < end) {
|
||||
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
|
||||
int line = startLine + ((code == start) ? 0 : lineNumberMapping.lastIndexOf(static_cast<uint>(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);
|
||||
|
|
|
@ -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<int> &lineNumberMapping = QVector<int>());
|
||||
inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, const QVector<int> &lineNumberMapping = QVector<int>()) {
|
||||
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;
|
||||
|
|
|
@ -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<uint>(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;
|
||||
|
|
|
@ -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<ExecutionContext *>(&jsFrame->context);
|
||||
}
|
||||
int lineNumber() const;
|
||||
|
||||
inline QV4::Heap::CallContext *callContext() const {
|
||||
Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::CallData *>(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<QV4::NoThrowEngine*>(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<QV4::CallData *>(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)
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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<QQmlProfilerService>();
|
||||
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<QQmlProfilerService>();
|
||||
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));
|
||||
|
||||
|
|
Loading…
Reference in New Issue