aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp10
-rw-r--r--src/qml/compiler/qv4isel_p.cpp16
-rw-r--r--src/qml/compiler/qv4ssa.cpp280
-rw-r--r--src/qml/compiler/qv4ssa_p.h2
-rw-r--r--src/qml/debugger/qv4debugservice.cpp14
-rw-r--r--src/qml/jit/qv4isel_masm.cpp6
-rw-r--r--src/qml/jit/qv4regalloc.cpp83
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp12
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp60
-rw-r--r--src/qml/qml/qqmlengine.cpp10
-rw-r--r--src/qml/qml/qqmlengine_p.h2
11 files changed, 240 insertions, 255 deletions
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 39977375c4..8f411bfbc6 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -188,15 +188,9 @@ public:
void forFunction(IR::Function *function)
{
- IR::Optimizer::showMeTheCode(function);
+ IR::Optimizer::showMeTheCode(function, "Before stack slot allocation");
_function = function;
toStackSlots(function);
-
-// QTextStream os(stdout, QIODevice::WriteOnly);
-// os << "Frame layout:" << endl;
-// foreach (int t, _stackSlotForTemp.keys()) {
-// os << "\t" << t << " -> " << _stackSlotForTemp[t] << endl;
-// }
}
protected:
@@ -364,7 +358,7 @@ void InstructionSelection::run(int functionIndex)
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
}
- opt.showMeTheCode(_function);
+ opt.showMeTheCode(_function, "After stack slot allocation");
} else {
ConvertTemps().toStackSlots(_function);
}
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index e419084238..167ea8337c 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -31,6 +31,8 @@
**
****************************************************************************/
+#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
@@ -41,11 +43,6 @@
#include <QString>
-namespace {
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-} // anonymous namespace
-
using namespace QV4;
using namespace QV4::IR;
@@ -218,8 +215,12 @@ void IRDecoder::visitMove(IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(s);
qout << endl;
+ qDebug("%s", buf.data().constData());
Q_ASSERT(!"TODO");
}
@@ -398,7 +399,10 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
}
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(call); qout << endl;
- Q_ASSERT(!"TODO!");
+ qDebug("%s", buf.data().constData());
Q_UNREACHABLE();
}
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index d2222a0458..77cfab8f6f 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -40,6 +40,7 @@
#include "qv4isel_util_p.h"
#include "qv4util_p.h"
+#include <QtCore/QBuffer>
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QSet>
@@ -51,9 +52,6 @@
#include <cassert>
#include <algorithm>
-#undef SHOW_SSA
-#undef DEBUG_MOVEMAPPING
-
QT_USE_NAMESPACE
using namespace QV4;
@@ -61,21 +59,25 @@ using namespace IR;
namespace {
+enum { DebugMoveMapping = 0 };
+
#ifdef QT_NO_DEBUG
enum { DoVerification = 0 };
#else
enum { DoVerification = 1 };
#endif
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-
-void showMeTheCode(IR::Function *function)
+static void showMeTheCode(IR::Function *function, const char *marker)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
- IRPrinter(&qout).print(function);
- qout << endl;
+ qDebug() << marker;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream stream(&buf);
+ IRPrinter(&stream).print(function);
+ stream << endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -402,11 +404,6 @@ class DominatorTree
todo = worklist.back();
worklist.pop_back();
}
-
-#if defined(SHOW_SSA)
- for (int i = 0; i < nodes.size(); ++i)
- qDebug("\tL%d: dfnum = %d, parent = %d", i, dfnum[i], parent[i]);
-#endif // SHOW_SSA
}
BasicBlockIndex ancestorWithLowestSemi(BasicBlockIndex v, std::vector<BasicBlockIndex> &worklist) {
@@ -592,6 +589,9 @@ public:
}
if (DebugDominatorFrontiers) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Dominator Frontiers:" << endl;
foreach (BasicBlock *n, function->basicBlocks()) {
if (n->isRemoved())
@@ -606,6 +606,7 @@ public:
}
qout << "}" << endl;
}
+ qDebug("%s", buf.data().constData());
}
if (DebugDominatorFrontiers && DebugCodeCanUseLotsOfCpu) {
@@ -624,7 +625,7 @@ public:
}
}
if (!hasDominatedSucc) {
- qout << fBlock << " in DF[" << n->index() << "] has no dominated predecessors" << endl;
+ qDebug("%d in DF[%d] has no dominated predecessors", fBlock->index(), n->index());
}
Q_ASSERT(hasDominatedSucc);
}
@@ -646,6 +647,9 @@ public:
void dumpImmediateDominators() const
{
if (DebugImmediateDominators) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Immediate dominators:" << endl;
foreach (BasicBlock *to, function->basicBlocks()) {
if (to->isRemoved())
@@ -659,6 +663,7 @@ public:
qout << "(none)";
qout << " -> " << to->index() << endl;
}
+ qDebug("%s", buf.data().constData());
}
}
@@ -953,10 +958,6 @@ public:
for (int i = 0, ei = A_orig.size(); i != ei; ++i)
A_orig[i].reserve(8);
-#if defined(SHOW_SSA)
- qout << "Variables collected:" << endl;
-#endif // SHOW_SSA
-
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
continue;
@@ -966,17 +967,6 @@ public:
foreach (Stmt *s, bb->statements())
s->accept(this);
}
-
-#if defined(SHOW_SSA)
- qout << "Non-locals:" << endl;
- foreach (const Temp &nonLocal, nonLocals) {
- qout << "\t";
- nonLocal.dump(qout);
- qout << endl;
- }
-
- qout << "end collected variables." << endl;
-#endif // SHOW_SSA
}
const std::vector<Temp> &allTemps() const
@@ -1038,12 +1028,6 @@ protected:
addTemp(t);
if (isCollectable(t)) {
-#if defined(SHOW_SSA)
- qout << '\t';
- t->dump(qout);
- qout << " -> L" << currentBB->index << endl;
-#endif // SHOW_SSA
-
_defsites[t->index].insert(currentBB);
addDefInCurrentBlock(t);
@@ -1274,6 +1258,9 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Defines and uses:" << endl;
foreach (const DefUse &du, _defUses) {
if (!du.isValid())
@@ -1294,16 +1281,11 @@ public:
qout << ' ' << t.index;
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
};
void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
-#if defined(SHOW_SSA)
- qout << "-> inserted phi node for variable ";
- a.dump(qout);
- qout << " in block " << y->index << endl;
-#endif
-
Phi *phiNode = f->NewStmt<Phi>();
phiNode->d = new Stmt::Data;
phiNode->targetTemp = f->New<Temp>();
@@ -1643,15 +1625,6 @@ protected:
// see [Appel]. For the changes needed for semi-pruned SSA form, and for its advantages, see [Briggs].
void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defUses)
{
-#if defined(SHOW_SSA)
- qout << "Converting function ";
- if (function->name)
- qout << *function->name;
- else
- qout << "<no name>";
- qout << " to SSA..." << endl;
-#endif // SHOW_SSA
-
// Collect all applicable variables:
VariableCollector variables(function);
@@ -2248,23 +2221,32 @@ public:
continue;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Typing stmt ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
if (!run(s)) {
*_worklist += s;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Pushing back stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
} else {
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Finished: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
}
@@ -2306,9 +2288,9 @@ private:
void setType(Expr *e, DiscoveredType ty) {
if (Temp *t = e->asTemp()) {
if (DebugTypeInference)
- qout << "Setting type for temp " << t->index
- << " to " << typeName(Type(ty.type)) << " (" << ty.type << ")"
- << endl;
+ qDebug() << "Setting type for temp" << t->index
+ << " to " << typeName(Type(ty.type)) << "(" << ty.type << ")"
+ << endl;
DiscoveredType &it = _tempTypes[t->index];
if (it != ty) {
@@ -2316,9 +2298,12 @@ private:
if (DebugTypeInference) {
foreach (Stmt *s, _defUses.uses(*t)) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Pushing back dependent stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -2704,15 +2689,6 @@ class TypePropagation: public StmtVisitor, public ExprVisitor {
if (requestedType != UnknownType) {
if (e->type != requestedType) {
if (requestedType & NumberType || requestedType == BoolType) {
-#ifdef SHOW_SSA
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "adding conversion from " << typeName(e->type)
- << " to " << typeName(requestedType) << " for expression ";
- e->dump(os);
- os << " in statement ";
- _currStmt->dump(os);
- os << endl;
-#endif
if (insertConversion)
addConversion(e, requestedType);
return true;
@@ -3409,15 +3385,9 @@ public:
QHash<BasicBlock *, BasicBlock *> go()
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before block scheduling");
schedule(function->basicBlock(0));
-#if defined(SHOW_SSA)
- qDebug() << "Block sequence:";
- foreach (BasicBlock *bb, sequence)
- qDebug("\tL%d", bb->index());
-#endif // SHOW_SSA
-
Q_ASSERT(function->liveBasicBlocksCount() == sequence.size());
function->setScheduledBlocks(sequence);
function->renumberBasicBlocks();
@@ -3431,8 +3401,8 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
if (bb && bb->out.size() > 1) {
foreach (BasicBlock *bb2, bb->out) {
if (bb2 && bb2->in.size() > 1) {
- qout << "found critical edge between block "
- << bb->index() << " and block " << bb2->index();
+ qDebug() << "found critical edge between block"
+ << bb->index() << "and block" << bb2->index();
Q_ASSERT(false);
}
}
@@ -3443,7 +3413,7 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
void cleanupBasicBlocks(IR::Function *function)
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before basic block cleanup");
// Algorithm: this is the iterative version of a depth-first search for all blocks that are
// reachable through outgoing edges, starting with the start block and all exception handler
@@ -3496,7 +3466,7 @@ void cleanupBasicBlocks(IR::Function *function)
function->removeBasicBlock(bb);
}
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block cleanup");
}
inline Const *isConstPhi(Phi *phi)
@@ -3829,8 +3799,14 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
if (!showCode)
return;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
struct Util {
- static void genLoop(LoopDetection::LoopInfo *loop)
+ QTextStream &qout;
+ Util(QTextStream &qout): qout(qout) {}
+ void genLoop(LoopDetection::LoopInfo *loop)
{
qout << " subgraph \"cluster" << quint64(loop) << "\" {\n";
qout << " L" << loop->loopHeader->index() << ";\n";
@@ -3849,7 +3825,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
foreach (LoopDetection::LoopInfo *l, loops) {
if (l->parentLoop == 0)
- Util::genLoop(l);
+ Util(qout).genLoop(l);
}
foreach (BasicBlock *bb, f->basicBlocks()) {
@@ -3867,7 +3843,8 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
qout << " L" << idx << " -> L" << out->index() << "\n";
}
- qout << "}\n" << flush;
+ qout << "}\n";
+ qDebug("%s", buf.data().constData());
}
} // anonymous namespace
@@ -4301,6 +4278,10 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
qout << "Life ranges:" << endl;
qout << "Intervals:" << endl;
foreach (const LifeTimeInterval *range, _sortedIntervals->intervals()) {
@@ -4321,6 +4302,7 @@ public:
}
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
private:
@@ -5068,12 +5050,7 @@ Optimizer::Optimizer(IR::Function *function)
void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool peelLoops)
{
-#if defined(SHOW_SSA)
- qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!")
- << " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
-#endif
-
-// showMeTheCode(function);
+ showMeTheCode(function, "Before running the optimizer");
cleanupBasicBlocks(function);
@@ -5087,7 +5064,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
ConvertArgLocals(function).toTemps();
- showMeTheCode(function);
+ showMeTheCode(function, "After converting arguments to locals");
// Calculate the dominator tree:
DominatorTree df(function);
@@ -5099,7 +5076,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopDetection loopDetection(df);
loopDetection.run(function);
- showMeTheCode(function);
+ showMeTheCode(function, "After loop detection");
// cfg2dot(function, loopDetection.allLoops());
if (peelLoops) {
@@ -5107,7 +5084,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopPeeling(df).run(innerLoops);
// cfg2dot(function, loopDetection.allLoops());
- showMeTheCode(function);
+ showMeTheCode(function, "After loop peeling");
if (!innerLoops.isEmpty())
verifyImmediateDominators(df, function);
}
@@ -5130,14 +5107,14 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Cleaning up phi nodes..." << endl;
cleanupPhis(defUses);
- showMeTheCode(function);
+ showMeTheCode(function, "After cleaning up phi-nodes");
StatementWorklist worklist(function);
if (doTypeInference) {
// qout << "Running type inference..." << endl;
TypeInference(qmlEngine, defUses).run(worklist);
- showMeTheCode(function);
+ showMeTheCode(function, "After type inference");
// qout << "Doing reverse inference..." << endl;
ReverseInference(defUses).run(function);
@@ -5154,7 +5131,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Running SSA optimization..." << endl;
worklist.reset();
optimizeSSA(worklist, defUses, df);
- showMeTheCode(function);
+ showMeTheCode(function, "After optimization");
verifyImmediateDominators(df, function);
verifyCFG(function);
@@ -5180,7 +5157,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Doing block scheduling..." << endl;
// df.dumpImmediateDominators();
startEndLoops = BlockScheduler(function, df).go();
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block scheduling");
// cfg2dot(function);
#ifndef QT_NO_DEBUG
@@ -5217,16 +5194,19 @@ void Optimizer::convertOutOfSSA() {
}
}
- #if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping for function ";
- if (function->name)
- os << *function->name;
- else
- os << (void *) function;
- os << " on basic-block L" << bb->index << ":" << endl;
- moves.dump();
- #endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ os << "Move mapping for function ";
+ if (function->name)
+ os << *function->name;
+ else
+ os << (void *) function;
+ os << " on basic-block L" << bb->index() << ":" << endl;
+ moves.dump();
+ qDebug("%s", buf.data().constData());
+ }
moves.order();
@@ -5282,22 +5262,12 @@ QSet<Jump *> Optimizer::calculateOptionalJumps()
reachableWithoutJump.insert(bb);
}
-#if 0
- QTextStream out(stdout, QIODevice::WriteOnly);
- out << "Jumps to ignore:" << endl;
- foreach (Jump *j, removed) {
- out << "\t" << j->id << ": ";
- j->dump(out, Stmt::MIR);
- out << endl;
- }
-#endif
-
return optional;
}
-void Optimizer::showMeTheCode(IR::Function *function)
+void Optimizer::showMeTheCode(IR::Function *function, const char *marker)
{
- ::showMeTheCode(function);
+ ::showMeTheCode(function, marker);
}
static inline bool overlappingStorage(const Temp &t1, const Temp &t2)
@@ -5339,14 +5309,17 @@ void MoveMapping::add(Expr *from, Temp *to) {
if (Temp *t = from->asTemp()) {
if (overlappingStorage(*t, *to)) {
// assignments like fp1 = fp1 or var{&1} = double{&1} can safely be skipped.
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stderr, QIODevice::WriteOnly);
- os << "Skipping ";
- to->dump(os);
- os << " <- ";
- from->dump(os);
- os << endl;
-#endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Skipping ";
+ printer.print(to);
+ os << " <- ";
+ printer.print(from);
+ qDebug("%s", buf.data().constData());
+ }
return;
}
}
@@ -5397,20 +5370,24 @@ QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *functio
void MoveMapping::dump() const
{
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping has " << _moves.size() << " moves..." << endl;
- foreach (const Move &m, _moves) {
- os << "\t";
- m.to->dump(os);
- if (m.needsSwap)
- os << " <-> ";
- else
- os << " <-- ";
- m.from->dump(os);
- os << endl;
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Move mapping has " << _moves.size() << " moves..." << endl;
+ foreach (const Move &m, _moves) {
+ os << "\t";
+ printer.print(m.to);
+ if (m.needsSwap)
+ os << " <-> ";
+ else
+ os << " <-- ";
+ printer.print(m.from);
+ os << endl;
+ }
+ qDebug("%s", buf.data().constData());
}
-#endif // DEBUG_MOVEMAPPING
}
MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed,
@@ -5421,19 +5398,24 @@ MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QLis
if (!output.contains(dependency)) {
if (delayed.contains(dependency)) {
// We have a cycle! Break it by swapping instead of assigning.
-#if defined(DEBUG_MOVEMAPPING)
- delayed+=m;
- QTextStream out(stderr, QIODevice::WriteOnly);
- out<<"we have a cycle! temps:" << endl;
- foreach (const Move &m, delayed) {
- out<<"\t";
- m.to->dump(out);
- out<<" <- ";
- m.from->dump(out);
- out<<endl;
+ if (DebugMoveMapping) {
+ delayed += m;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ IRPrinter printer(&out);
+ out<<"we have a cycle! temps:" << endl;
+ foreach (const Move &m, delayed) {
+ out<<"\t";
+ printer.print(m.to);
+ out<<" <- ";
+ printer.print(m.from);
+ out<<endl;
+ }
+ qDebug("%s", buf.data().constData());
+ delayed.removeOne(m);
}
- delayed.removeOne(m);
-#endif // DEBUG_MOVEMAPPING
+
return NeedsSwap;
} else {
delayed.append(m);
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 21a5b038b6..93bf62ad40 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -219,7 +219,7 @@ public:
QSet<IR::Jump *> calculateOptionalJumps();
- static void showMeTheCode(Function *function);
+ static void showMeTheCode(Function *function, const char *marker);
private:
Function *function;
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index 30d9557383..90f86cc29a 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -62,8 +62,8 @@ const char *V4_LINENUMBER = "linenumber";
#ifdef NO_PROTOCOL_TRACING
# define TRACE_PROTOCOL(x)
#else
+#include <QtCore/QDebug>
# define TRACE_PROTOCOL(x) x
-static QTextStream debug(stderr, QIODevice::WriteOnly);
#endif
QT_BEGIN_NAMESPACE
@@ -378,7 +378,7 @@ public:
QByteArray responseData = doc.toJson(QJsonDocument::Indented);
#endif
- TRACE_PROTOCOL(debug << "sending response for: " << responseData << endl);
+ TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData << endl);
q_func()->sendMessage(packMessage("v8message", responseData));
}
@@ -523,7 +523,7 @@ public:
void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
{
- TRACE_PROTOCOL(debug << "handling command " << command() << "..." << endl);
+ TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
req = request;
seq = req.value(QStringLiteral("seq"));
@@ -1137,13 +1137,13 @@ void QV4DebugService::messageReceived(const QByteArray &message)
QByteArray header;
ms >> header;
- TRACE_PROTOCOL(debug << "received message with header " << header << endl);
+ TRACE_PROTOCOL(qDebug() << "received message with header" << header);
if (header == "V8DEBUG") {
QByteArray type;
QByteArray payload;
ms >> type >> payload;
- TRACE_PROTOCOL(debug << "... type: "<<type << endl);
+ TRACE_PROTOCOL(qDebug() << "... type:" << type);
if (type == V4_CONNECT) {
sendMessage(d->packMessage(type));
@@ -1164,7 +1164,7 @@ void QV4DebugService::messageReceived(const QByteArray &message)
} else if (type == "v8request") {
handleV8Request(payload);
} else if (type == V4_DISCONNECT) {
- TRACE_PROTOCOL(debug << "... payload:"<<payload << endl);
+ TRACE_PROTOCOL(qDebug() << "... payload:" << payload);
handleV8Request(payload);
} else {
sendSomethingToSomebody(type, 0);
@@ -1249,7 +1249,7 @@ void QV4DebugService::handleV8Request(const QByteArray &payload)
{
Q_D(QV4DebugService);
- TRACE_PROTOCOL(debug << "v8request, payload: " << payload << endl);
+ TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload);
QJsonDocument request = QJsonDocument::fromJson(payload);
QJsonObject o = request.object();
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index f905e9c978..e7771f53d2 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -115,8 +115,8 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput, const Q
continue;
processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value());
}
- fprintf(stderr, "%s\n", processedOutput.constData());
- fflush(stderr);
+
+ qDebug("%s", processedOutput.constData());
}
JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
@@ -225,7 +225,7 @@ void InstructionSelection::run(int functionIndex)
// No register allocator available for this platform, or env. var was set, so:
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
- IR::Optimizer::showMeTheCode(_function);
+ IR::Optimizer::showMeTheCode(_function, "After stack slot allocation");
calculateRegistersToSave(Assembler::getRegisterInfo()); // FIXME: this saves all registers. We can probably do with a subset: those that are not used by the register allocator.
}
QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index e69522404d..16792d8a1e 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -31,6 +31,8 @@
**
****************************************************************************/
+#include <QtCore/QBuffer>
+#include <QtCore/QDebug>
#include "qv4regalloc_p.h"
#include <private/qv4value_inl_p.h>
@@ -223,7 +225,9 @@ public:
if (!DebugRegAlloc)
return;
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
qout << "RegAllocInfo:" << endl << "Defs/uses:" << endl;
@@ -264,6 +268,7 @@ public:
}
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
protected: // IRDecoder
@@ -823,8 +828,11 @@ public:
void run() {
renumber();
if (DebugRegAlloc) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions(&qout, _intervals).print(_function);
+ qDebug("%s", buf.data().constData());
}
resolve();
}
@@ -876,7 +884,9 @@ private:
_liveAtEnd[bb] = _intervalForTemp.values();
if (DebugRegAlloc) {
- QTextStream os(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
os << "Intervals live at the start of L" << bb->index() << ":" << endl;
if (_liveAtStart[bb].isEmpty())
os << "\t(none)" << endl;
@@ -893,6 +903,7 @@ private:
i->dump(os);
os << endl;
}
+ qDebug("%s", buf.data().constData());
}
bb->setStatements(newStatements);
@@ -967,11 +978,13 @@ private:
{
if (DebugRegAlloc) {
qDebug() << "Resolving edge" << predecessor->index() << "->" << successor->index();
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _intervals);
printer.print(predecessor);
printer.print(successor);
- qout.flush();
+ qDebug("%s", buf.data().constData());
}
MoveMapping mapping;
@@ -1088,11 +1101,13 @@ private:
if (DebugRegAlloc) {
qDebug() << ".. done, result:";
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _intervals);
printer.print(predecessor);
printer.print(successor);
- qout.flush();
+ qDebug("%s", buf.data().constData());
}
}
@@ -1260,7 +1275,9 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
_info->collect(function, _lifeTimeIntervals);
if (DebugRegAlloc) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Ranges:" << endl;
QVector<LifeTimeInterval *> intervals = _unhandled;
std::reverse(intervals.begin(), intervals.end());
@@ -1268,13 +1285,13 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
r->dump(qout);
qout << endl;
}
+ qDebug("%s", buf.data().constData());
_info->dump();
- }
- if (DebugRegAlloc) {
qDebug() << "*** Before register allocation:";
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ buf.setData(QByteArray());
IRPrinterWithPositions(&qout, _lifeTimeIntervals).print(function);
+ qDebug("%s", buf.data().constData());
}
prepareRanges();
@@ -1293,8 +1310,11 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithRegisters(&qout, _lifeTimeIntervals, _registerInformation).print(function);
+ qDebug("%s", buf.data().constData());
}
}
@@ -1675,10 +1695,12 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current)
// spill interval that currently block reg
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
out << "*** spilling intervals that block reg " <<reg<< " for interval ";
current.dump(out);
- out << endl;
+ qDebug("%s", buf.data().constData());
}
current.setReg(reg);
_lastAssignedRegister[current.temp().index] = reg;
@@ -1701,8 +1723,7 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current)
int ni = nextIntersection(current, *fixedRegRange);
if (ni != -1) {
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***-- current range intersects with a fixed reg use at " << ni << ", so splitting it." << endl;
+ qDebug("***-- current range intersects with a fixed reg use at %d, so splitting it.", ni);
}
// current does overlap with a fixed interval, so split current before that intersection.
split(current, ni, true);
@@ -1767,8 +1788,14 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
Q_ASSERT(!current.isFixedInterval());
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ out << "***** split request for range ";
+ current.dump(out);
+ out << " before position " << beforePosition
+ << " and skipOptionalRegisterUses = " << skipOptionalRegisterUses << endl;
+ qDebug("%s", buf.data().constData());
}
assignSpillSlot(current.temp(), current.start(), current.end());
@@ -1796,10 +1823,17 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
LifeTimeInterval newInterval = current.split(lastUse, nextUse);
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
- out << "***** new interval: "; newInterval.dump(out); out << endl;
- out << "***** preceding interval: "; current.dump(out); out << endl;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ out << "***** last use = " << lastUse << ", nextUse = " << nextUse << endl;
+ out << "***** new interval: ";
+ newInterval.dump(out);
+ out << endl;
+ out << "***** preceding interval: ";
+ current.dump(out);
+ out << endl;
+ qDebug("%s", buf.data().constData());
}
if (newInterval.isValid()) {
if (current.reg() != LifeTimeInterval::InvalidRegister)
@@ -1848,7 +1882,9 @@ void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
void RegisterAllocator::dump(IR::Function *function) const
{
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
qout << "Ranges:" << endl;
@@ -1865,6 +1901,7 @@ void RegisterAllocator::dump(IR::Function *function) const
qout << "\t%" << i << " -> " << _assignedSpillSlots[i] << endl;
printer.print(function);
+ qDebug("%s", buf.data().constData());
}
// References:
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index b5fbf89e3e..a4340a3fab 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -60,6 +60,11 @@
#include "../../3rdparty/double-conversion/double-conversion.h"
+#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
+# include <QtCore/QBuffer>
+# include <QtCore/QDebug>
+#endif // QV4_COUNT_RUNTIME_FUNCTIONS
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -144,7 +149,9 @@ struct RuntimeCounters::Data {
};
void dump() const {
- QTextStream outs(stderr, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream outs(&buf);
QList<Line> lines;
foreach (const char *func, counters.keys()) {
const Counters &fCount = counters[func];
@@ -159,7 +166,7 @@ struct RuntimeCounters::Data {
lines.append(line);
}
}
- qSort(lines.begin(), lines.end(), Line::less);
+ std::sort(lines.begin(), lines.end(), Line::less);
outs << lines.size() << " counters:" << endl;
foreach (const Line &line, lines)
outs << qSetFieldWidth(10) << line.count << qSetFieldWidth(0)
@@ -167,6 +174,7 @@ struct RuntimeCounters::Data {
<< " | " << pretty(line.tag1)
<< " | " << pretty(line.tag2)
<< endl;
+ qDebug("%s", buf.data().constData());
}
};
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 1e1c17ffef..8372aaa510 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -42,9 +42,11 @@
#include "qv4alloca_p.h"
+#undef DO_TRACE_INSTR // define to enable instruction tracing
+
#ifdef DO_TRACE_INSTR
-# define TRACE_INSTR(I) fprintf(stderr, "executing a %s\n", #I);
-# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); fprintf(stderr, " %s : %s\n", #n, buf); }
+# define TRACE_INSTR(I) qDebug("executing a %s\n", #I);
+# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); qDebug(" %s : %s", #n, buf); }
#else
# define TRACE_INSTR(I)
# define TRACE(n, str, ...)
@@ -79,59 +81,23 @@ using namespace QV4::Moth;
#endif
-#ifdef WITH_STATS
-namespace {
-struct VMStats {
- quint64 paramIsValue;
- quint64 paramIsArg;
- quint64 paramIsLocal;
- quint64 paramIsTemp;
- quint64 paramIsScopedLocal;
-
- VMStats()
- : paramIsValue(0)
- , paramIsArg(0)
- , paramIsLocal(0)
- , paramIsTemp(0)
- , paramIsScopedLocal(0)
- {}
-
- ~VMStats()
- { show(); }
-
- void show() {
- fprintf(stderr, "VM stats:\n");
- fprintf(stderr, " value: %lu\n", paramIsValue);
- fprintf(stderr, " arg: %lu\n", paramIsArg);
- fprintf(stderr, " local: %lu\n", paramIsLocal);
- fprintf(stderr, " temp: %lu\n", paramIsTemp);
- fprintf(stderr, " scoped local: %lu\n", paramIsScopedLocal);
- }
-};
-static VMStats vmStats;
-#define VMSTATS(what) ++vmStats.what
-}
-#else // !WITH_STATS
-#define VMSTATS(what) {}
-#endif // WITH_STATS
-
#ifdef DO_TRACE_INSTR
Param traceParam(const Param &param)
{
if (param.isConstant()) {
- fprintf(stderr, " constant\n");
+ qDebug(" constant\n");
} else if (param.isArgument()) {
- fprintf(stderr, " argument %d@%d\n", param.index, param.scope);
+ qDebug(" argument %d@%d\n", param.index, param.scope);
} else if (param.isLocal()) {
- fprintf(stderr, " local %d\n", param.index);
+ qDebug(" local %d\n", param.index);
} else if (param.isTemp()) {
- fprintf(stderr, " temp %d\n", param.index);
+ qDebug(" temp %d\n", param.index);
} else if (param.isScopedLocal()) {
- fprintf(stderr, " temp %d@%d\n", param.index, param.scope);
+ qDebug(" temp %d@%d\n", param.index, param.scope);
} else {
Q_ASSERT(!"INVALID");
}
- return Param
+ return param;
}
# define VALUE(param) (*VALUEPTR(param))
# define VALUEPTR(param) (scopes[traceParam(param).scope] + param.index)
@@ -256,7 +222,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(GetGlobalLookup)
- TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
QV4::Lookup *l = context->d()->lookups + instr.index;
STOREVALUE(instr.result, l->globalGetter(l, engine));
MOTH_END_INSTR(GetGlobalLookup)
@@ -364,7 +329,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
@@ -383,7 +347,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
- TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
@@ -393,7 +356,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallGlobalLookup)
- TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
@@ -519,7 +481,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(ConstructPropertyLookup)
MOTH_BEGIN_INSTR(CreateActivationProperty)
- TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
@@ -529,7 +490,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
- TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index debf740358..22cf73c51d 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -553,7 +553,7 @@ the same object as is returned from the Qt.include() call.
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0), isDebugging(false),
- profiler(0), outputWarningsToStdErr(true),
+ profiler(0), outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
@@ -1180,7 +1180,7 @@ void QQmlEngine::setBaseUrl(const QUrl &url)
bool QQmlEngine::outputWarningsToStandardError() const
{
Q_D(const QQmlEngine);
- return d->outputWarningsToStdErr;
+ return d->outputWarningsToMsgLog;
}
/*!
@@ -1196,7 +1196,7 @@ bool QQmlEngine::outputWarningsToStandardError() const
void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
{
Q_D(QQmlEngine);
- d->outputWarningsToStdErr = enabled;
+ d->outputWarningsToMsgLog = enabled;
}
/*!
@@ -1789,7 +1789,7 @@ void QQmlEnginePrivate::warning(const QQmlError &error)
{
Q_Q(QQmlEngine);
q->warnings(QList<QQmlError>() << error);
- if (outputWarningsToStdErr)
+ if (outputWarningsToMsgLog)
dumpwarning(error);
}
@@ -1797,7 +1797,7 @@ void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
{
Q_Q(QQmlEngine);
q->warnings(errors);
- if (outputWarningsToStdErr)
+ if (outputWarningsToMsgLog)
dumpwarning(errors);
}
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 3df249a667..a1935b854b 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -141,7 +141,7 @@ public:
QQmlProfiler *profiler;
void enableProfiler();
- bool outputWarningsToStdErr;
+ bool outputWarningsToMsgLog;
// Registered cleanup handlers
QQmlCleanup *cleanup;