Modify nanojit::live, expose ReverseLister, add some options to VerboseWriter (r=edwsmith,graydon,bug=538000)
Modify nanojit::live, expose ReverseLister, add some options to VerboseWriter (r=edwsmith,graydon,bug=538000)
--- a/js/src/nanojit/Assembler.h
+++ b/js/src/nanojit/Assembler.h
@@ -222,18 +222,16 @@ namespace nanojit
LabelStateMap(Allocator& alloc) : alloc(alloc), labels(alloc)
{}
void clear() { labels.clear(); }
void add(LIns *label, NIns *addr, RegAlloc ®s);
LabelState *get(LIns *);
};
- typedef SeqBuilder<char*> StringList;
-
/** map tracking the register allocation state at each bailout point
* (represented by SideExit*) in a trace fragment. */
typedef HashMap<SideExit*, RegAlloc*> RegAllocMap;
/**
* Information about the activation record for the method is built up
* as we generate machine code. As part of the prologue, we issue
* a stack adjustment instruction and then later patch the adjustment
--- a/js/src/nanojit/LIR.cpp
+++ b/js/src/nanojit/LIR.cpp
@@ -70,60 +70,36 @@ namespace nanojit
#undef OPDEF
NULL
};
#endif /* NANOJIT_VEBROSE */
// implementation
#ifdef NJ_VERBOSE
- /* A listing filter for LIR, going through backwards. It merely
- passes its input to its output, but notes it down too. When
- destructed, prints out what went through. Is intended to be
- used to print arbitrary intermediate transformation stages of
- LIR. */
- class ReverseLister : public LirFilter
+ void ReverseLister::finish()
{
- Allocator& _alloc;
- LirNameMap* _names;
- const char* _title;
- StringList _strs;
- LogControl* _logc;
- public:
- ReverseLister(LirFilter* in, Allocator& alloc,
- LirNameMap* names, LogControl* logc, const char* title)
- : LirFilter(in)
- , _alloc(alloc)
- , _names(names)
- , _title(title)
- , _strs(alloc)
- , _logc(logc)
- { }
+ _logc->printf("\n");
+ _logc->printf("=== BEGIN %s ===\n", _title);
+ int j = 0;
+ for (Seq<char*>* p = _strs.get(); p != NULL; p = p->tail)
+ _logc->printf(" %02d: %s\n", j++, p->head);
+ _logc->printf("=== END %s ===\n", _title);
+ _logc->printf("\n");
+ }
- void finish()
- {
- _logc->printf("\n");
- _logc->printf("=== BEGIN %s ===\n", _title);
- int j = 0;
- for (Seq<char*>* p = _strs.get(); p != NULL; p = p->tail)
- _logc->printf(" %02d: %s\n", j++, p->head);
- _logc->printf("=== END %s ===\n", _title);
- _logc->printf("\n");
- }
-
- LInsp read()
- {
- LInsp i = in->read();
- const char* str = _names->formatIns(i);
- char* cpy = new (_alloc) char[strlen(str)+1];
- VMPI_strcpy(cpy, str);
- _strs.insert(cpy);
- return i;
- }
- };
+ LInsp ReverseLister::read()
+ {
+ LInsp i = in->read();
+ const char* str = _names->formatIns(i);
+ char* cpy = new (_alloc) char[strlen(str)+1];
+ VMPI_strcpy(cpy, str);
+ _strs.insert(cpy);
+ return i;
+ }
#endif
#ifdef NJ_PROFILE
// @todo fixup move to nanojit.h
#undef counter_value
#define counter_value(x) x
#endif /* NJ_PROFILE */
@@ -1464,28 +1440,26 @@ namespace nanojit
/*
* traverse the LIR buffer and discover which instructions are live
* by starting from instructions with side effects (stores, calls, branches)
* and marking instructions used by them. Works bottom-up, in one pass.
* if showLiveRefs == true, also print the set of live expressions next to
* each instruction
*/
- void live(Allocator& alloc, Fragment *frag, LogControl *logc)
+ void live(LirFilter* in, Allocator& alloc, Fragment *frag, LogControl *logc)
{
// traverse backwards to find live exprs and a few other stats.
LiveTable live(alloc);
uint32_t exits = 0;
- LirReader br(frag->lastIns);
- StackFilter sf(&br, alloc, frag->lirbuf, frag->lirbuf->sp, frag->lirbuf->rp);
int total = 0;
if (frag->lirbuf->state)
- live.add(frag->lirbuf->state, sf.pos());
- for (LInsp ins = sf.read(); !ins->isop(LIR_start); ins = sf.read())
+ live.add(frag->lirbuf->state, in->pos());
+ for (LInsp ins = in->read(); !ins->isop(LIR_start); ins = in->read())
{
total++;
// first handle side-effect instructions
if (ins->isStmt())
{
live.add(ins, 0);
if (ins->isGuard())
@@ -2165,17 +2139,19 @@ namespace nanojit
logc->printf("===\n");
})
/* END decorative preamble */
verbose_only( if (liveVerb) {
logc->printf("\n");
logc->printf("=== Results of liveness analysis:\n");
logc->printf("===\n");
- live(alloc, frag, logc);
+ LirReader br(frag->lastIns);
+ StackFilter sf(&br, alloc, frag->lirbuf, frag->lirbuf->sp, frag->lirbuf->rp);
+ live(&sf, alloc, frag, logc);
})
/* Set up the generic text output cache for the assembler */
verbose_only( StringList asmOutput(alloc); )
verbose_only( assm->_outputCache = &asmOutput; )
assm->beginAssembly(frag);
if (assm->error())
--- a/js/src/nanojit/LIR.h
+++ b/js/src/nanojit/LIR.h
@@ -581,16 +581,17 @@ namespace nanojit
#else
return (void*)imm32();
#endif
}
};
typedef LIns* LInsp;
typedef SeqBuilder<LIns*> InsList;
+ typedef SeqBuilder<char*> StringList;
// 0-operand form. Used for LIR_start and LIR_label.
class LInsOp0
{
private:
friend class LIns;
@@ -1158,40 +1159,45 @@ namespace nanojit
};
class VerboseWriter : public LirWriter
{
InsList code;
LirNameMap* names;
LogControl* logc;
+ const char* const prefix;
+ bool const always_flush;
public:
VerboseWriter(Allocator& alloc, LirWriter *out,
- LirNameMap* names, LogControl* logc)
- : LirWriter(out), code(alloc), names(names), logc(logc)
+ LirNameMap* names, LogControl* logc, const char* prefix = "", bool always_flush = false)
+ : LirWriter(out), code(alloc), names(names), logc(logc), prefix(prefix), always_flush(always_flush)
{}
LInsp add(LInsp i) {
- if (i)
+ if (i) {
code.add(i);
+ if (always_flush)
+ flush();
+ }
return i;
}
LInsp add_flush(LInsp i) {
if ((i = add(i)) != 0)
flush();
return i;
}
void flush()
{
if (!code.isEmpty()) {
int32_t count = 0;
for (Seq<LIns*>* p = code.get(); p != NULL; p = p->tail) {
- logc->printf(" %s\n",names->formatIns(p->head));
+ logc->printf("%s %s\n",prefix,names->formatIns(p->head));
count++;
}
code.clear();
if (count > 1)
logc->printf("\n");
}
}
@@ -1473,17 +1479,17 @@ namespace nanojit
LInsp pos() {
return _i;
}
};
class Assembler;
void compile(Assembler *assm, Fragment *frag, Allocator& alloc verbose_only(, LabelMap*));
- verbose_only(void live(Allocator& alloc, Fragment* frag, LogControl*);)
+ verbose_only(void live(LirFilter* in, Allocator& alloc, Fragment* frag, LogControl*);)
class StackFilter: public LirFilter
{
LirBuffer *lirbuf;
LInsp sp;
LInsp rp;
BitSet spStk;
BitSet rpStk;
@@ -1535,10 +1541,40 @@ namespace nanojit
SanityFilter(LirWriter* out) : LirWriter(out)
{ }
public:
LIns* ins1(LOpcode v, LIns* s0);
LIns* ins2(LOpcode v, LIns* s0, LIns* s1);
LIns* ins3(LOpcode v, LIns* s0, LIns* s1, LIns* s2);
};
#endif
+
+#ifdef NJ_VERBOSE
+ /* A listing filter for LIR, going through backwards. It merely
+ passes its input to its output, but notes it down too. When
+ finish() is called, prints out what went through. Is intended to be
+ used to print arbitrary intermediate transformation stages of
+ LIR. */
+ class ReverseLister : public LirFilter
+ {
+ Allocator& _alloc;
+ LirNameMap* _names;
+ const char* _title;
+ StringList _strs;
+ LogControl* _logc;
+ public:
+ ReverseLister(LirFilter* in, Allocator& alloc,
+ LirNameMap* names, LogControl* logc, const char* title)
+ : LirFilter(in)
+ , _alloc(alloc)
+ , _names(names)
+ , _title(title)
+ , _strs(alloc)
+ , _logc(logc)
+ { }
+
+ void finish();
+ LInsp read();
+ };
+#endif
+
}
#endif // __nanojit_LIR__