Permalink
Browse files

Add support for gathering trace stats.

This will allow us to compute trace completion rates and similar
information.
  • Loading branch information...
1 parent 5cb5da7 commit c5ae5407ec960f5c06a28906a4f4c39af614486b @nominolo committed Sep 20, 2012
Showing with 114 additions and 1 deletion.
  1. +24 −0 vm/assembler.cc
  2. +3 −0 vm/assembler.hh
  3. +2 −0 vm/config.hh
  4. +37 −1 vm/jit.cc
  5. +21 −0 vm/jit.hh
  6. +27 −0 vm/main.cc
View
24 vm/assembler.cc
@@ -835,6 +835,10 @@ void Assembler::assemble(IRBuffer *buf, MachineCode *mcode) {
prepareTail(buf, saveref);
+#ifdef LC_TRACE_STATS
+ incrementCounter(&jit()->stats_[0]);
+#endif
+
for (curins_--; curins_ >= stopins_; curins_--) {
IR *ins = ir(curins_);
if (ins->isGuard()) {
@@ -871,6 +875,11 @@ void Assembler::assemble(IRBuffer *buf, MachineCode *mcode) {
if (buf_->entry_relbase_ != 0) {
adjustBase(buf_->entry_relbase_);
}
+
+#ifdef LC_TRACE_STATS
+ // Bump the parent trace's exit counter.
+ incrementCounter(buf_->parent_->exitCounterAddress(jit()->parentExitNo_));
+#endif
}
@@ -895,6 +904,21 @@ void Assembler::assemble(IRBuffer *buf, MachineCode *mcode) {
RA_DBG_FLUSH();
}
+void
+Assembler::incrementCounter(uint64_t *counterAddr)
+{
+ // We emit a PC-relative INC. For example:
+ //
+ // incq 0x200b31(%rip) = 48 ff 05 [31 0b 20 00]
+ //
+ MCode *p = mcp;
+ *(int32_t *)(p - 4) = jmprel(p, (MCode *)(void *)counterAddr);
+ p[-5] = 0x05;
+ p[-6] = 0xff;
+ p[-7] = 0x48;
+ mcp = p - 7;
+}
+
void Assembler::emitSLOAD(IR *ins) {
int32_t ofs = 8 * (int16_t)ins->op1();
Reg base = RID_BASE;
View
3 vm/assembler.hh
@@ -536,6 +536,9 @@ public:
void patchGuard(Fragment *, ExitNo, MCode *target);
void adjustBase(int32_t relbase);
+ // Emits code to increment the value of the value at the target
+ // address.
+ void incrementCounter(uint64_t *counterAddr);
void assemble(IRBuffer *, MachineCode *);
void transfer(RegSpill dst, RegSpill src, ParAssign *assign);
View
2 vm/config.hh
@@ -28,6 +28,8 @@
#define LC_JIT 1
+// #define LC_TRACE_STATS
+
#define MAX_HEAP_ENTRIES 300
#define HOT_SIDE_EXIT_THRESHOLD 7
View
38 vm/jit.cc
@@ -77,6 +77,9 @@ void Jit::beginRecording(Capability *cap, BcIns *startPc, Word *base, bool isRet
callStack_.reset();
btb_.reset(startPc_, &callStack_);
lastResult_ = TRef();
+#ifdef LC_TRACE_STATS
+ stats_ = NULL;
+#endif
}
/*
@@ -174,7 +177,9 @@ void Jit::beginSideTrace(Capability *cap, Word *base, Fragment *parent, SnapNo s
buf_.slots_.debugPrint(cerr);
}
- // exit(1);
+#ifdef LC_TRACE_STATS
+ stats_ = NULL;
+#endif
}
static IRType littypeToIRType(uint8_t littype) {
@@ -731,6 +736,11 @@ inline void Jit::resetRecorderState() {
void Jit::finishRecording() {
Time compilestart = getProcessElapsedTime();
DBG(cerr << "Recorded: " << endl);
+#ifdef LC_TRACE_STATS
+ uint32_t nStatCounters = 1 + buffer()->snaps_.size();
+ stats_ = new uint64_t[nStatCounters];
+ memset(stats_, 0, sizeof(uint64_t) * nStatCounters);
+#endif
asm_.assemble(buffer(), mcode());
if (DEBUG_COMPONENTS & DEBUG_ASSEMBLER)
buf_.debugPrint(cerr, Jit::numFragments());
@@ -762,11 +772,18 @@ void Jit::finishRecording() {
Fragment::Fragment()
: flags_(0), traceId_(0), startPc_(NULL), targets_(NULL) {
+#ifdef LC_TRACE_STATS
+ stats_ = NULL;
+#endif
}
Fragment::~Fragment() {
if (targets_ != NULL)
delete[] targets_;
+#ifdef LC_TRACE_STATS
+ if (stats_ != NULL)
+ delete[] stats_;
+#endif
}
void Jit::genCode(IRBuffer *buf) {
@@ -812,6 +829,10 @@ Fragment *Jit::saveFragment() {
F->snapmap_.index_ = buf->snapmap_.data_.size();
F->mcode_ = as->mcp;
+#ifdef LC_TRACE_STATS
+ F->stats_ = stats_; // Transfers ownership.
+ stats_ = NULL;
+#endif
return F;
}
@@ -889,6 +910,9 @@ void Fragment::restoreSnapshot(ExitNo exitno, ExitState *ex) {
LC_ASSERT(0 <= exitno && exitno < nsnaps_);
DBG(cerr << "Restoring from snapshot " << (int)exitno
<< " of Trace " << traceId() << endl);
+#ifdef LC_TRACE_STATS
+ bumpExitCount(exitno);
+#endif
Snapshot &sn = snap(exitno);
IR *snapins = ir(sn.ref());
Word *base = (Word *)ex->gpr[RID_BASE];
@@ -1034,4 +1058,16 @@ printLoggedNYIs(FILE *out)
}
}
+#ifdef LC_TRACE_STATS
+uint64_t
+Fragment::traceExits() const
+{
+ uint64_t exits = 0;
+ for (uint32_t e = 0; e < nsnaps_; ++e) {
+ exits += traceExitsAt(e);
+ }
+ return exits;
+}
+#endif
+
_END_LAMBDACHINE_NAMESPACE
View
21 vm/jit.hh
@@ -214,6 +214,9 @@ private:
BranchTargetBuffer btb_;
MCode *exitStubGroup_[16];
bool shouldAbort_;
+#ifdef LC_TRACE_STATS
+ uint64_t *stats_;
+#endif
static FRAGMENT_MAP fragmentMap_;
static std::vector<Fragment*> fragments_;
@@ -265,6 +268,19 @@ public:
return snaps_[n];
}
+#ifdef LC_TRACE_STATS
+ inline uint64_t traceCompletions() const { return stats_[0]; }
+ inline uint64_t traceExitsAt(ExitNo n) const {
+ LC_ASSERT(n < nsnaps_);
+ return stats_[1 + n];
+ }
+ uint64_t traceExits() const;
+
+private:
+ void bumpExitCount(ExitNo n) { ++stats_[1 + n]; }
+ uint64_t *exitCounterAddress(ExitNo n) const { return &stats_[1 + n]; }
+#endif
+
private:
Fragment();
@@ -292,7 +308,12 @@ private:
MCode *mcode_;
// size_t sizemcode_;
+#ifdef LC_TRACE_STATS
+ uint64_t *stats_;
+#endif
+
friend class Jit;
+ friend class Assembler;
};
inline void Jit::registerFragment(BcIns *startPc, Fragment *F) {
View
27 vm/main.cc
@@ -15,6 +15,7 @@ using namespace lambdachine;
void formatTime(FILE *out, const char *label, Time time);
void formatWithThousands(char *str, uint64_t n);
void printGCStats(FILE *out, MemoryManager *mm, Time mut_time);
+void printTraceStats(FILE *out);
inline double percent(double num, double denom) {
return (num * 100) / denom;
@@ -90,6 +91,11 @@ int main(int argc, char *argv[]) {
printf("\n\n");
printGCStats(stdout, &mm, mut_time);
+#ifdef LC_TRACE_STATS
+ printf("\n\n");
+ printTraceStats(stdout);
+#endif
+
formatTime(stdout, " Startup ", start_time - startup_time);
formatTime(stdout, " LOAD ", loader_time);
formatTime(stdout, " Runtime ", run_time);
@@ -142,3 +148,24 @@ void printGCStats(FILE *out, MemoryManager *mm, Time mut_time) {
fprintf(out, " (%18s bytes per MUT second)\n", buf);
fprintf(out, " %18d collections\n\n", mm->numGCs());
}
+
+void
+printTraceStats(FILE *out)
+{
+#ifdef LC_TRACE_STATS
+ fprintf(out, "Trace Statistics:\n");
+ for (uint32_t traceId = 0; traceId < Jit::numFragments(); ++traceId) {
+ Fragment *F = Jit::traceById(traceId);
+ uint64_t completions = F->traceCompletions();
+ uint64_t exits = F->traceExits();
+ char completionsString[30];
+ char exitsString[30];
+ formatWithThousands(completionsString, completions);
+ formatWithThousands(exitsString, exits);
+ fprintf(out, " %04d: %20s %20s\n", traceId, completionsString, exitsString);
+ }
+ fprintf(out, "\n");
+#else
+ UNUSED(out);
+#endif
+}

0 comments on commit c5ae540

Please sign in to comment.