mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 494864 - Make nanojit debug output easier to follow, r=graydon.
This commit is contained in:
parent
ee292894fd
commit
b96eed42da
@ -2343,7 +2343,7 @@ class RegExpNativeCompiler {
|
|||||||
addName(LirBuffer* lirbuf, LIns* ins, const char* name)
|
addName(LirBuffer* lirbuf, LIns* ins, const char* name)
|
||||||
{
|
{
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
debug_only_v(lirbuf->names->addName(ins, name);)
|
debug_only_stmt(lirbuf->names->addName(ins, name);)
|
||||||
#endif
|
#endif
|
||||||
return ins;
|
return ins;
|
||||||
}
|
}
|
||||||
@ -2401,11 +2401,18 @@ class RegExpNativeCompiler {
|
|||||||
|
|
||||||
/* FIXME Use bug 463260 smart pointer when available. */
|
/* FIXME Use bug 463260 smart pointer when available. */
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
debug_only_v(fragment->lirbuf->names = new (&gc) LirNameMap(&gc, fragmento->labels);)
|
debug_only_stmt(
|
||||||
|
fragment->lirbuf->names = new (&gc) LirNameMap(&gc, fragmento->labels);
|
||||||
|
)
|
||||||
#endif
|
#endif
|
||||||
/* FIXME Use bug 463260 smart pointer when available. */
|
/* FIXME Use bug 463260 smart pointer when available. */
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
debug_only_v(lir = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);)
|
debug_only_stmt(
|
||||||
|
if (js_LogController.lcbits & LC_TMRegexp) {
|
||||||
|
lir = new (&gc) VerboseWriter(&gc, lir, lirbuf->names,
|
||||||
|
&js_LogController);
|
||||||
|
}
|
||||||
|
)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lir->ins0(LIR_start);
|
lir->ins0(LIR_start);
|
||||||
@ -2434,7 +2441,8 @@ class RegExpNativeCompiler {
|
|||||||
|
|
||||||
delete lirBufWriter;
|
delete lirBufWriter;
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
debug_only_v(delete lir;)
|
debug_only_stmt( if (js_LogController.lcbits & LC_TMRegexp)
|
||||||
|
delete lir; )
|
||||||
#endif
|
#endif
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
fail:
|
fail:
|
||||||
@ -2448,7 +2456,8 @@ class RegExpNativeCompiler {
|
|||||||
}
|
}
|
||||||
delete lirBufWriter;
|
delete lirBufWriter;
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
debug_only_v(delete lir;)
|
debug_only_stmt( if (js_LogController.lcbits & LC_TMRegexp)
|
||||||
|
delete lir; )
|
||||||
#endif
|
#endif
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
@ -3923,12 +3932,13 @@ MatchRegExp(REGlobalData *gData, REMatchState *x)
|
|||||||
gData->skipped = (ptrdiff_t) x->cp;
|
gData->skipped = (ptrdiff_t) x->cp;
|
||||||
|
|
||||||
#ifdef JS_JIT_SPEW
|
#ifdef JS_JIT_SPEW
|
||||||
debug_only_v({
|
debug_only_stmt({
|
||||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||||
JSStackFrame *caller = (JS_ON_TRACE(gData->cx))
|
JSStackFrame *caller = (JS_ON_TRACE(gData->cx))
|
||||||
? NULL
|
? NULL
|
||||||
: js_GetScriptedCaller(gData->cx, NULL);
|
: js_GetScriptedCaller(gData->cx, NULL);
|
||||||
printf("entering REGEXP trace at %s:%u@%u, code: %p\n",
|
debug_only_printf(LC_TMRegexp,
|
||||||
|
"entering REGEXP trace at %s:%u@%u, code: %p\n",
|
||||||
caller ? caller->script->filename : "<unknown>",
|
caller ? caller->script->filename : "<unknown>",
|
||||||
caller ? js_FramePCToLineNumber(gData->cx, caller) : 0,
|
caller ? js_FramePCToLineNumber(gData->cx, caller) : 0,
|
||||||
caller ? FramePCOffset(caller) : 0,
|
caller ? FramePCOffset(caller) : 0,
|
||||||
@ -3942,7 +3952,7 @@ MatchRegExp(REGlobalData *gData, REMatchState *x)
|
|||||||
result = native(x, gData);
|
result = native(x, gData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
debug_only_v(printf("leaving REGEXP trace\n"));
|
debug_only_print0(LC_TMRegexp, "leaving REGEXP trace\n");
|
||||||
|
|
||||||
gData->skipped = ((const jschar *) gData->skipped) - cp;
|
gData->skipped = ((const jschar *) gData->skipped) - cp;
|
||||||
return result;
|
return result;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -154,10 +154,39 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef JS_JIT_SPEW
|
#ifdef JS_JIT_SPEW
|
||||||
extern bool js_verboseDebug;
|
|
||||||
#define debug_only_v(x) if (js_verboseDebug) { x; fflush(stdout); }
|
enum LC_TMBits {
|
||||||
|
/* Output control bits for all non-Nanojit code. Only use bits 16
|
||||||
|
and above, since Nanojit uses 0 .. 15 itself. */
|
||||||
|
LC_TMMinimal = 1<<16,
|
||||||
|
LC_TMTracer = 1<<17,
|
||||||
|
LC_TMRecorder = 1<<18,
|
||||||
|
LC_TMPatcher = 1<<19,
|
||||||
|
LC_TMAbort = 1<<20,
|
||||||
|
LC_TMStats = 1<<21,
|
||||||
|
LC_TMRegexp = 1<<22
|
||||||
|
};
|
||||||
|
|
||||||
|
// Top level logging controller object.
|
||||||
|
extern nanojit::LogControl js_LogController;
|
||||||
|
|
||||||
|
#define debug_only_stmt(stmt) \
|
||||||
|
stmt
|
||||||
|
#define debug_only_printf(mask, fmt, ...) \
|
||||||
|
do { if ((js_LogController.lcbits & (mask)) > 0) { \
|
||||||
|
js_LogController.printf(fmt, __VA_ARGS__); fflush(stdout); \
|
||||||
|
}} while (0)
|
||||||
|
#define debug_only_print0(mask, str) \
|
||||||
|
do { if ((js_LogController.lcbits & (mask)) > 0) { \
|
||||||
|
js_LogController.printf(str); fflush(stdout); \
|
||||||
|
}} while (0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define debug_only_v(x)
|
|
||||||
|
#define debug_only_stmt(action) /* */
|
||||||
|
#define debug_only_printf(mask, fmt, ...) /* */
|
||||||
|
#define debug_only_print0(mask, str) /* */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -137,6 +137,59 @@ namespace nanojit
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
{
|
||||||
|
avmplus::GC* _gc;
|
||||||
|
LirNameMap* _names;
|
||||||
|
const char* _title;
|
||||||
|
StringList* _strs;
|
||||||
|
LogControl* _logc;
|
||||||
|
public:
|
||||||
|
ReverseLister(LirFilter* in, avmplus::GC* gc,
|
||||||
|
LirNameMap* names, LogControl* logc, const char* title)
|
||||||
|
: LirFilter(in)
|
||||||
|
{
|
||||||
|
_gc = gc;
|
||||||
|
_names = names;
|
||||||
|
_title = title;
|
||||||
|
_strs = new StringList(gc);
|
||||||
|
_logc = logc;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ReverseLister()
|
||||||
|
{
|
||||||
|
_logc->printf("\n");
|
||||||
|
_logc->printf("=== BEGIN %s ===\n", _title);
|
||||||
|
int i, j;
|
||||||
|
const char* prefix = " ";
|
||||||
|
for (j = 0, i = _strs->size()-1; i >= 0; i--, j++) {
|
||||||
|
char* str = _strs->get(i);
|
||||||
|
_logc->printf("%s%02d: %s\n", prefix, j, str);
|
||||||
|
_gc->Free(str);
|
||||||
|
}
|
||||||
|
delete _strs;
|
||||||
|
_logc->printf("=== END %s ===\n", _title);
|
||||||
|
_logc->printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
LInsp read()
|
||||||
|
{
|
||||||
|
LInsp i = in->read();
|
||||||
|
if (!i)
|
||||||
|
return i;
|
||||||
|
const char* str = _names->formatIns(i);
|
||||||
|
char* cpy = (char*)_gc->Alloc(strlen(str) + 1, 0/*AllocFlags*/);
|
||||||
|
strcpy(cpy, str);
|
||||||
|
_strs->add(cpy);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -144,7 +197,7 @@ namespace nanojit
|
|||||||
*
|
*
|
||||||
* - merging paths ( build a graph? ), possibly use external rep to drive codegen
|
* - merging paths ( build a graph? ), possibly use external rep to drive codegen
|
||||||
*/
|
*/
|
||||||
Assembler::Assembler(Fragmento* frago)
|
Assembler::Assembler(Fragmento* frago, LogControl* logc)
|
||||||
: hasLoop(0)
|
: hasLoop(0)
|
||||||
, _frago(frago)
|
, _frago(frago)
|
||||||
, _gc(frago->core()->gc)
|
, _gc(frago->core()->gc)
|
||||||
@ -155,9 +208,9 @@ namespace nanojit
|
|||||||
{
|
{
|
||||||
AvmCore *core = frago->core();
|
AvmCore *core = frago->core();
|
||||||
nInit(core);
|
nInit(core);
|
||||||
verbose_only( _verbose = !core->quiet_opt() && core->verbose() );
|
verbose_only( _logc = logc; )
|
||||||
verbose_only( _outputCache = 0);
|
verbose_only( _outputCache = 0; )
|
||||||
verbose_only( outlineEOL[0] = '\0');
|
verbose_only( outlineEOL[0] = '\0'; )
|
||||||
|
|
||||||
internalReset();
|
internalReset();
|
||||||
pageReset();
|
pageReset();
|
||||||
@ -578,7 +631,9 @@ namespace nanojit
|
|||||||
int d = disp(resv);
|
int d = disp(resv);
|
||||||
Register rr = resv->reg;
|
Register rr = resv->reg;
|
||||||
bool quad = i->opcode() == LIR_param || i->isQuad();
|
bool quad = i->opcode() == LIR_param || i->isQuad();
|
||||||
verbose_only( if (d && _verbose) { outputForEOL(" <= spill %s", _thisfrag->lirbuf->names->formatRef(i)); } )
|
verbose_only( if (d && (_logc->lcbits & LC_RegAlloc)) {
|
||||||
|
outputForEOL(" <= spill %s",
|
||||||
|
_thisfrag->lirbuf->names->formatRef(i)); } )
|
||||||
asm_spill(rr, d, pop, quad);
|
asm_spill(rr, d, pop, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,9 +708,9 @@ namespace nanojit
|
|||||||
RegAlloc* captured = _branchStateMap->get(exit);
|
RegAlloc* captured = _branchStateMap->get(exit);
|
||||||
intersectRegisterState(*captured);
|
intersectRegisterState(*captured);
|
||||||
verbose_only(
|
verbose_only(
|
||||||
verbose_outputf(" merging trunk with %s",
|
verbose_outputf("## merging trunk with %s",
|
||||||
_frago->labels->format(exit->target));
|
_frago->labels->format(exit->target));
|
||||||
verbose_outputf(" %p:",_nIns);
|
verbose_outputf("%010lx:", (unsigned long)_nIns);
|
||||||
)
|
)
|
||||||
at = exit->target->fragEntry;
|
at = exit->target->fragEntry;
|
||||||
NanoAssert(at != 0);
|
NanoAssert(at != 0);
|
||||||
@ -666,10 +721,8 @@ namespace nanojit
|
|||||||
|
|
||||||
NIns* Assembler::asm_leave_trace(LInsp guard)
|
NIns* Assembler::asm_leave_trace(LInsp guard)
|
||||||
{
|
{
|
||||||
verbose_only(bool priorVerbose = _verbose; )
|
|
||||||
verbose_only( _verbose = verbose_enabled() && _frago->core()->config.verbose_exits; )
|
|
||||||
verbose_only( int32_t nativeSave = _stats.native );
|
verbose_only( int32_t nativeSave = _stats.native );
|
||||||
verbose_only(verbose_outputf("--------------------------------------- end exit block %p", guard);)
|
verbose_only( verbose_outputf("----------------------------------- ## END exit block %p", guard);)
|
||||||
|
|
||||||
RegAlloc capture = _allocator;
|
RegAlloc capture = _allocator;
|
||||||
|
|
||||||
@ -704,15 +757,14 @@ namespace nanojit
|
|||||||
_inExit = false;
|
_inExit = false;
|
||||||
|
|
||||||
//verbose_only( verbose_outputf(" LIR_xt/xf swapptrs, _nIns is now %08X(%08X), _nExitIns is now %08X(%08X)",_nIns, *_nIns,_nExitIns,*_nExitIns) );
|
//verbose_only( verbose_outputf(" LIR_xt/xf swapptrs, _nIns is now %08X(%08X), _nExitIns is now %08X(%08X)",_nIns, *_nIns,_nExitIns,*_nExitIns) );
|
||||||
verbose_only( verbose_outputf(" %p:",jmpTarget);)
|
verbose_only( verbose_outputf("%010lx:", (unsigned long)jmpTarget);)
|
||||||
verbose_only( verbose_outputf("--------------------------------------- exit block (LIR_xt|LIR_xf)") );
|
verbose_only( verbose_outputf("----------------------------------- ## BEGIN exit block (LIR_xt|LIR_xf)") );
|
||||||
|
|
||||||
#ifdef NANOJIT_IA32
|
#ifdef NANOJIT_IA32
|
||||||
NanoAssertMsgf(_fpuStkDepth == _sv_fpuStkDepth, "LIR_xtf, _fpuStkDepth=%d, expect %d",_fpuStkDepth, _sv_fpuStkDepth);
|
NanoAssertMsgf(_fpuStkDepth == _sv_fpuStkDepth, "LIR_xtf, _fpuStkDepth=%d, expect %d",_fpuStkDepth, _sv_fpuStkDepth);
|
||||||
debug_only( _fpuStkDepth = _sv_fpuStkDepth; _sv_fpuStkDepth = 9999; )
|
debug_only( _fpuStkDepth = _sv_fpuStkDepth; _sv_fpuStkDepth = 9999; )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
verbose_only( _verbose = priorVerbose; )
|
|
||||||
verbose_only(_stats.exitnative += (_stats.native-nativeSave));
|
verbose_only(_stats.exitnative += (_stats.native-nativeSave));
|
||||||
|
|
||||||
return jmpTarget;
|
return jmpTarget;
|
||||||
@ -771,24 +823,73 @@ namespace nanojit
|
|||||||
AvmCore *core = _frago->core();
|
AvmCore *core = _frago->core();
|
||||||
_thisfrag = frag;
|
_thisfrag = frag;
|
||||||
|
|
||||||
// set up backwards pipeline: assembler -> StackFilter -> LirReader
|
// Used for debug printing, if needed
|
||||||
LirReader bufreader(frag->lastIns);
|
|
||||||
avmplus::GC *gc = core->gc;
|
|
||||||
StackFilter storefilter1(&bufreader, gc, frag->lirbuf, frag->lirbuf->sp);
|
|
||||||
StackFilter storefilter2(&storefilter1, gc, frag->lirbuf, frag->lirbuf->rp);
|
|
||||||
DeadCodeFilter deadfilter(&storefilter2);
|
|
||||||
LirFilter* rdr = &deadfilter;
|
|
||||||
verbose_only(
|
verbose_only(
|
||||||
VerboseBlockReader vbr(rdr, this, frag->lirbuf->names);
|
ReverseLister *pp_init = NULL,
|
||||||
if (verbose_enabled())
|
*pp_after_sf1 = NULL,
|
||||||
rdr = &vbr;
|
*pp_after_sf2 = NULL,
|
||||||
|
*pp_after_dead = NULL;
|
||||||
|
)
|
||||||
|
|
||||||
|
// set up backwards pipeline: assembler -> StackFilter -> LirReader
|
||||||
|
avmplus::GC *gc = core->gc;
|
||||||
|
LirReader bufreader(frag->lastIns);
|
||||||
|
|
||||||
|
// Used to construct the pipeline
|
||||||
|
LirFilter* prev = &bufreader;
|
||||||
|
|
||||||
|
// The LIR passes through these filters as listed in this
|
||||||
|
// function, viz, top to bottom.
|
||||||
|
|
||||||
|
// INITIAL PRINTING
|
||||||
|
verbose_only( if (_logc->lcbits & LC_ReadLIR) {
|
||||||
|
pp_init = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
|
||||||
|
"Initial LIR");
|
||||||
|
prev = pp_init;
|
||||||
|
})
|
||||||
|
|
||||||
|
// STOREFILTER for sp
|
||||||
|
StackFilter storefilter1(prev, gc, frag->lirbuf, frag->lirbuf->sp);
|
||||||
|
prev = &storefilter1;
|
||||||
|
|
||||||
|
verbose_only( if (_logc->lcbits & LC_AfterSF_SP) {
|
||||||
|
pp_after_sf1 = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
|
||||||
|
"After Storefilter(sp)");
|
||||||
|
prev = pp_after_sf1;
|
||||||
|
})
|
||||||
|
|
||||||
|
// STOREFILTER for rp
|
||||||
|
StackFilter storefilter2(prev, gc, frag->lirbuf, frag->lirbuf->rp);
|
||||||
|
prev = &storefilter2;
|
||||||
|
|
||||||
|
verbose_only( if (_logc->lcbits & LC_AfterSF_RP) {
|
||||||
|
pp_after_sf2 = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
|
||||||
|
"After StoreFilter(rp)");
|
||||||
|
prev = pp_after_sf2;
|
||||||
|
})
|
||||||
|
|
||||||
|
// DEAD CODE FILTER
|
||||||
|
DeadCodeFilter deadfilter(prev);
|
||||||
|
prev = &deadfilter;
|
||||||
|
|
||||||
|
verbose_only( if (_logc->lcbits & LC_AfterDeadF) {
|
||||||
|
pp_after_dead = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
|
||||||
|
"After DeadFilter == Final LIR");
|
||||||
|
prev = pp_after_dead;
|
||||||
|
})
|
||||||
|
|
||||||
|
// end of pipeline
|
||||||
|
verbose_only(
|
||||||
|
VerboseBlockReader vbr(prev, this, frag->lirbuf->names);
|
||||||
|
if (_logc->lcbits & LC_Assembly)
|
||||||
|
prev = &vbr;
|
||||||
)
|
)
|
||||||
|
|
||||||
verbose_only(_thisfrag->compileNbr++; )
|
verbose_only(_thisfrag->compileNbr++; )
|
||||||
verbose_only(_frago->_stats.compiles++; )
|
verbose_only(_frago->_stats.compiles++; )
|
||||||
verbose_only(_frago->_stats.totalCompiles++; )
|
verbose_only(_frago->_stats.totalCompiles++; )
|
||||||
_inExit = false;
|
_inExit = false;
|
||||||
gen(rdr, loopJumps);
|
gen(prev, loopJumps);
|
||||||
frag->loopEntry = _nIns;
|
frag->loopEntry = _nIns;
|
||||||
//frag->outbound = core->config.tree_opt? _latestGuard : 0;
|
//frag->outbound = core->config.tree_opt? _latestGuard : 0;
|
||||||
//nj_dprintf("assemble frag %X entry %X\n", (int)frag, (int)frag->fragEntry);
|
//nj_dprintf("assemble frag %X entry %X\n", (int)frag, (int)frag->fragEntry);
|
||||||
@ -814,6 +915,16 @@ namespace nanojit
|
|||||||
// In case of failure, reset _nIns ready for the next assembly run.
|
// In case of failure, reset _nIns ready for the next assembly run.
|
||||||
resetInstructionPointer();
|
resetInstructionPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we were accumulating debug info in the various ReverseListers,
|
||||||
|
// destruct them now. Their destructors cause them to emit whatever
|
||||||
|
// contents they have accumulated.
|
||||||
|
verbose_only(
|
||||||
|
if (pp_init) delete pp_init;
|
||||||
|
if (pp_after_sf1) delete pp_after_sf1;
|
||||||
|
if (pp_after_sf2) delete pp_after_sf2;
|
||||||
|
if (pp_after_dead) delete pp_after_dead;
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::endAssembly(Fragment* frag, NInsList& loopJumps)
|
void Assembler::endAssembly(Fragment* frag, NInsList& loopJumps)
|
||||||
@ -826,7 +937,7 @@ namespace nanojit
|
|||||||
NIns* SOT = 0;
|
NIns* SOT = 0;
|
||||||
if (frag->isRoot()) {
|
if (frag->isRoot()) {
|
||||||
SOT = frag->loopEntry;
|
SOT = frag->loopEntry;
|
||||||
verbose_only( verbose_outputf(" %p:",_nIns); )
|
verbose_only( verbose_outputf("%010lx:", (unsigned long)_nIns); )
|
||||||
} else {
|
} else {
|
||||||
SOT = frag->root->fragEntry;
|
SOT = frag->root->fragEntry;
|
||||||
}
|
}
|
||||||
@ -834,7 +945,8 @@ namespace nanojit
|
|||||||
while(!loopJumps.isEmpty())
|
while(!loopJumps.isEmpty())
|
||||||
{
|
{
|
||||||
NIns* loopJump = (NIns*)loopJumps.removeLast();
|
NIns* loopJump = (NIns*)loopJumps.removeLast();
|
||||||
verbose_only( verbose_outputf("patching %p to %p", loopJump, SOT); )
|
verbose_only( verbose_outputf("## patching branch at %010lx to %010lx",
|
||||||
|
loopJump, SOT); )
|
||||||
nPatchBranch(loopJump, SOT);
|
nPatchBranch(loopJump, SOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1312,7 +1424,7 @@ namespace nanojit
|
|||||||
intersectRegisterState(label->regs);
|
intersectRegisterState(label->regs);
|
||||||
label->addr = _nIns;
|
label->addr = _nIns;
|
||||||
}
|
}
|
||||||
verbose_only( if (_verbose) { outputAddr=true; asm_output("[%s]", _thisfrag->lirbuf->names->formatRef(ins)); } )
|
verbose_only( if (_logc->lcbits & LC_Assembly) { outputAddr=true; asm_output("[%s]", _thisfrag->lirbuf->names->formatRef(ins)); } )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LIR_xbarrier: {
|
case LIR_xbarrier: {
|
||||||
@ -1342,7 +1454,8 @@ namespace nanojit
|
|||||||
case LIR_x:
|
case LIR_x:
|
||||||
{
|
{
|
||||||
countlir_x();
|
countlir_x();
|
||||||
verbose_only(verbose_output(""));
|
verbose_only( if (_logc->lcbits & LC_Assembly)
|
||||||
|
asm_output("FIXME-whats-this?\n"); )
|
||||||
// generate the side exit branch on the main trace.
|
// generate the side exit branch on the main trace.
|
||||||
NIns *exit = asm_exit(ins);
|
NIns *exit = asm_exit(ins);
|
||||||
JMP( exit );
|
JMP( exit );
|
||||||
@ -1507,7 +1620,7 @@ namespace nanojit
|
|||||||
#ifdef NANOJIT_ARM
|
#ifdef NANOJIT_ARM
|
||||||
// @todo Why is there here?!? This routine should be indep. of platform
|
// @todo Why is there here?!? This routine should be indep. of platform
|
||||||
verbose_only(
|
verbose_only(
|
||||||
if (_verbose) {
|
if (_logc->lcbits & LC_Assembly) {
|
||||||
char* s = &outline[0];
|
char* s = &outline[0];
|
||||||
memset(s, ' ', 51); s[51] = '\0';
|
memset(s, ' ', 51); s[51] = '\0';
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
@ -1526,7 +1639,7 @@ namespace nanojit
|
|||||||
#else
|
#else
|
||||||
verbose_only(
|
verbose_only(
|
||||||
char* s = &outline[0];
|
char* s = &outline[0];
|
||||||
if (_verbose) {
|
if (_logc->lcbits & LC_Assembly) {
|
||||||
memset(s, ' ', 51); s[51] = '\0';
|
memset(s, ' ', 51); s[51] = '\0';
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " ebp ");
|
sprintf(s, " ebp ");
|
||||||
@ -1733,7 +1846,11 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assignSaved(saved, skip);
|
assignSaved(saved, skip);
|
||||||
verbose_only( if (shouldMention) verbose_outputf(" merging registers (intersect) with existing edge"); )
|
verbose_only(
|
||||||
|
if (shouldMention)
|
||||||
|
verbose_outputf("## merging registers (intersect) "
|
||||||
|
"with existing edge");
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1863,13 +1980,13 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nj_dprintf("%s\n", s);
|
_logc->printf("%s\n", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::output_asm(const char* s)
|
void Assembler::output_asm(const char* s)
|
||||||
{
|
{
|
||||||
if (!verbose_enabled())
|
if (!(_logc->lcbits & LC_Assembly))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Add the EOL string to the output, ensuring that we leave enough
|
// Add the EOL string to the output, ensuring that we leave enough
|
||||||
|
@ -159,13 +159,19 @@ namespace nanojit
|
|||||||
void FASTCALL outputf(const char* format, ...);
|
void FASTCALL outputf(const char* format, ...);
|
||||||
void FASTCALL output_asm(const char* s);
|
void FASTCALL output_asm(const char* s);
|
||||||
|
|
||||||
bool _verbose, outputAddr, vpad[2]; // if outputAddr=true then next asm instr. will include address in output
|
// if outputAddr=true then next asm instr. will include
|
||||||
|
// address in output
|
||||||
|
bool outputAddr, vpad[2];
|
||||||
void printActivationState();
|
void printActivationState();
|
||||||
|
|
||||||
StringList* _outputCache;
|
StringList* _outputCache;
|
||||||
|
|
||||||
|
// Log controller object. Contains what-stuff-should-we-print
|
||||||
|
// bits, and a sink function for debug printing
|
||||||
|
LogControl* _logc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Assembler(Fragmento* frago);
|
Assembler(Fragmento* frago, LogControl* logc);
|
||||||
~Assembler() {}
|
~Assembler() {}
|
||||||
|
|
||||||
void assemble(Fragment* frag, NInsList& loopJumps);
|
void assemble(Fragment* frag, NInsList& loopJumps);
|
||||||
|
@ -57,7 +57,7 @@ namespace nanojit
|
|||||||
/**
|
/**
|
||||||
* This is the main control center for creating and managing fragments.
|
* This is the main control center for creating and managing fragments.
|
||||||
*/
|
*/
|
||||||
Fragmento::Fragmento(AvmCore* core, uint32_t cacheSizeLog2)
|
Fragmento::Fragmento(AvmCore* core, LogControl* logc, uint32_t cacheSizeLog2)
|
||||||
:
|
:
|
||||||
#ifdef NJ_VERBOSE
|
#ifdef NJ_VERBOSE
|
||||||
enterCounts(NULL),
|
enterCounts(NULL),
|
||||||
@ -99,7 +99,7 @@ namespace nanojit
|
|||||||
NanoAssert(_max_pages > _pagesGrowth); // shrink growth if needed
|
NanoAssert(_max_pages > _pagesGrowth); // shrink growth if needed
|
||||||
_core = core;
|
_core = core;
|
||||||
GC *gc = core->GetGC();
|
GC *gc = core->GetGC();
|
||||||
_assm = NJ_NEW(gc, nanojit::Assembler)(this);
|
_assm = NJ_NEW(gc, nanojit::Assembler)(this, logc);
|
||||||
verbose_only( enterCounts = NJ_NEW(gc, BlockHist)(gc); )
|
verbose_only( enterCounts = NJ_NEW(gc, BlockHist)(gc); )
|
||||||
verbose_only( mergeCounts = NJ_NEW(gc, BlockHist)(gc); )
|
verbose_only( mergeCounts = NJ_NEW(gc, BlockHist)(gc); )
|
||||||
|
|
||||||
@ -384,9 +384,6 @@ namespace nanojit
|
|||||||
|
|
||||||
void Fragmento::dumpStats()
|
void Fragmento::dumpStats()
|
||||||
{
|
{
|
||||||
bool vsave = _assm->_verbose;
|
|
||||||
_assm->_verbose = true;
|
|
||||||
|
|
||||||
_assm->output("");
|
_assm->output("");
|
||||||
dumpRatio("inline", enterCounts);
|
dumpRatio("inline", enterCounts);
|
||||||
dumpRatio("merges", mergeCounts);
|
dumpRatio("merges", mergeCounts);
|
||||||
@ -403,7 +400,6 @@ namespace nanojit
|
|||||||
if (!count)
|
if (!count)
|
||||||
{
|
{
|
||||||
_assm->outputf("No fragments in cache, %d flushes", flushes);
|
_assm->outputf("No fragments in cache, %d flushes", flushes);
|
||||||
_assm->_verbose = vsave;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,14 +464,12 @@ namespace nanojit
|
|||||||
labels->format(d.frag->ip));
|
labels->format(d.frag->ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
_assm->_verbose = vsave;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fragmento::countBlock(BlockHist *hist, const void* ip)
|
void Fragmento::countBlock(BlockHist *hist, const void* ip)
|
||||||
{
|
{
|
||||||
int c = hist->count(ip);
|
int c = hist->count(ip);
|
||||||
if (_assm->_verbose)
|
if (_assm->_logc->lcbits & LC_Assembly)
|
||||||
_assm->outputf("++ %s %d", labels->format(ip), c);
|
_assm->outputf("++ %s %d", labels->format(ip), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ namespace nanojit
|
|||||||
class Fragmento : public avmplus::GCFinalizedObject
|
class Fragmento : public avmplus::GCFinalizedObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Fragmento(AvmCore* core, uint32_t cacheSizeLog2);
|
Fragmento(AvmCore* core, LogControl* logc, uint32_t cacheSizeLog2);
|
||||||
~Fragmento();
|
~Fragmento();
|
||||||
|
|
||||||
void addMemory(void* firstPage, uint32_t pageCount); // gives memory to the Assembler
|
void addMemory(void* firstPage, uint32_t pageCount); // gives memory to the Assembler
|
||||||
|
@ -45,18 +45,6 @@
|
|||||||
#endif /* PERFM */
|
#endif /* PERFM */
|
||||||
|
|
||||||
|
|
||||||
#if defined(NJ_VERBOSE)
|
|
||||||
void nj_dprintf( const char* format, ... )
|
|
||||||
{
|
|
||||||
va_list vargs;
|
|
||||||
va_start(vargs, format);
|
|
||||||
vfprintf(stdout, format, vargs);
|
|
||||||
va_end(vargs);
|
|
||||||
}
|
|
||||||
#endif /* NJ_VERBOSE */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace nanojit
|
namespace nanojit
|
||||||
{
|
{
|
||||||
using namespace avmplus;
|
using namespace avmplus;
|
||||||
@ -1486,7 +1474,7 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void live(GC *gc, Fragment *frag)
|
void live(GC *gc, Fragment *frag, LogControl *logc)
|
||||||
{
|
{
|
||||||
// traverse backwards to find live exprs and a few other stats.
|
// traverse backwards to find live exprs and a few other stats.
|
||||||
|
|
||||||
@ -1538,9 +1526,11 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nj_dprintf("live instruction count %d, total %u, max pressure %d\n",
|
logc->printf(" Live instruction count %d, total %u, max pressure %d\n",
|
||||||
live.retired.size(), total, live.maxlive);
|
live.retired.size(), total, live.maxlive);
|
||||||
nj_dprintf("side exits %u\n", exits);
|
logc->printf(" Side exits %u\n", exits);
|
||||||
|
logc->printf(" Showing LIR instructions with live-after variables\n");
|
||||||
|
logc->printf("\n");
|
||||||
|
|
||||||
// print live exprs, going forwards
|
// print live exprs, going forwards
|
||||||
LirNameMap *names = frag->lirbuf->names;
|
LirNameMap *names = frag->lirbuf->names;
|
||||||
@ -1551,7 +1541,7 @@ namespace nanojit
|
|||||||
char livebuf[4000], *s=livebuf;
|
char livebuf[4000], *s=livebuf;
|
||||||
*s = 0;
|
*s = 0;
|
||||||
if (!newblock && e->i->isop(LIR_label)) {
|
if (!newblock && e->i->isop(LIR_label)) {
|
||||||
nj_dprintf("\n");
|
logc->printf("\n");
|
||||||
}
|
}
|
||||||
newblock = false;
|
newblock = false;
|
||||||
for (int k=0,n=e->live.size(); k < n; k++) {
|
for (int k=0,n=e->live.size(); k < n; k++) {
|
||||||
@ -1560,9 +1550,18 @@ namespace nanojit
|
|||||||
*s++ = ' '; *s = 0;
|
*s++ = ' '; *s = 0;
|
||||||
NanoAssert(s < livebuf+sizeof(livebuf));
|
NanoAssert(s < livebuf+sizeof(livebuf));
|
||||||
}
|
}
|
||||||
nj_dprintf("%-60s %s\n", livebuf, names->formatIns(e->i));
|
/* If the LIR insn is pretty short, print it and its
|
||||||
|
live-after set on the same line. If not, put
|
||||||
|
live-after set on a new line, suitably indented. */
|
||||||
|
const char* insn_text = names->formatIns(e->i);
|
||||||
|
if (strlen(insn_text) >= 30-2) {
|
||||||
|
logc->printf(" %-30s\n %-30s %s\n", names->formatIns(e->i), "", livebuf);
|
||||||
|
} else {
|
||||||
|
logc->printf(" %-30s %s\n", names->formatIns(e->i), livebuf);
|
||||||
|
}
|
||||||
|
|
||||||
if (e->i->isGuard() || e->i->isBranch() || e->i->isRet()) {
|
if (e->i->isGuard() || e->i->isBranch() || e->i->isRet()) {
|
||||||
nj_dprintf("\n");
|
logc->printf("\n");
|
||||||
newblock = true;
|
newblock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1965,12 +1964,35 @@ namespace nanojit
|
|||||||
AvmCore *core = frago->core();
|
AvmCore *core = frago->core();
|
||||||
GC *gc = core->gc;
|
GC *gc = core->gc;
|
||||||
|
|
||||||
|
verbose_only(
|
||||||
|
LogControl *logc = assm->_logc;
|
||||||
|
bool anyVerb = (logc->lcbits & 0xFFFF) > 0;
|
||||||
|
bool asmVerb = (logc->lcbits & 0xFFFF & LC_Assembly) > 0;
|
||||||
|
bool liveVerb = (logc->lcbits & 0xFFFF & LC_Liveness) > 0;
|
||||||
|
)
|
||||||
|
|
||||||
|
/* BEGIN decorative preamble */
|
||||||
|
verbose_only(
|
||||||
|
if (anyVerb) {
|
||||||
|
logc->printf("========================================"
|
||||||
|
"========================================\n");
|
||||||
|
logc->printf("=== BEGIN LIR::compile(%p, %p)\n",
|
||||||
|
(void*)assm, (void*)triggerFrag);
|
||||||
|
logc->printf("===\n");
|
||||||
|
})
|
||||||
|
/* END decorative preamble */
|
||||||
|
|
||||||
|
verbose_only( if (liveVerb) {
|
||||||
|
logc->printf("\n");
|
||||||
|
logc->printf("=== Results of liveness analysis:\n");
|
||||||
|
logc->printf("===\n");
|
||||||
|
live(gc, triggerFrag, logc);
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Set up the generic text output cache for the assembler */
|
||||||
verbose_only( StringList asmOutput(gc); )
|
verbose_only( StringList asmOutput(gc); )
|
||||||
verbose_only( assm->_outputCache = &asmOutput; )
|
verbose_only( assm->_outputCache = &asmOutput; )
|
||||||
|
|
||||||
verbose_only(if (assm->_verbose && core->config.verbose_live)
|
|
||||||
live(gc, triggerFrag);)
|
|
||||||
|
|
||||||
bool treeCompile = core->config.tree_opt && (triggerFrag->kind == BranchTrace);
|
bool treeCompile = core->config.tree_opt && (triggerFrag->kind == BranchTrace);
|
||||||
RegAllocMap regMap(gc);
|
RegAllocMap regMap(gc);
|
||||||
NInsList loopJumps(gc);
|
NInsList loopJumps(gc);
|
||||||
@ -1981,26 +2003,42 @@ namespace nanojit
|
|||||||
if (assm->error())
|
if (assm->error())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//nj_dprintf("recompile trigger %X kind %d\n", (int)triggerFrag, triggerFrag->kind);
|
//logc->printf("recompile trigger %X kind %d\n", (int)triggerFrag, triggerFrag->kind);
|
||||||
|
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== Translating LIR fragments into assembly:\n");
|
||||||
|
})
|
||||||
|
|
||||||
Fragment* root = triggerFrag;
|
Fragment* root = triggerFrag;
|
||||||
if (treeCompile)
|
if (treeCompile)
|
||||||
{
|
{
|
||||||
// recompile the entire tree
|
// recompile the entire tree
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== -- Compile the entire tree: begin\n");
|
||||||
|
})
|
||||||
root = triggerFrag->root;
|
root = triggerFrag->root;
|
||||||
root->fragEntry = 0;
|
root->fragEntry = 0;
|
||||||
root->loopEntry = 0;
|
root->loopEntry = 0;
|
||||||
root->releaseCode(frago);
|
root->releaseCode(frago);
|
||||||
|
|
||||||
// do the tree branches
|
// do the tree branches
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== -- Do the tree branches\n");
|
||||||
|
})
|
||||||
Fragment* frag = root->treeBranches;
|
Fragment* frag = root->treeBranches;
|
||||||
while (frag)
|
while (frag)
|
||||||
{
|
{
|
||||||
// compile til no more frags
|
// compile til no more frags
|
||||||
if (frag->lastIns)
|
if (frag->lastIns)
|
||||||
{
|
{
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== -- Compiling branch %s ip %s\n",
|
||||||
|
frago->labels->format(frag),
|
||||||
|
frago->labels->format(frag->ip));
|
||||||
|
})
|
||||||
assm->assemble(frag, loopJumps);
|
assm->assemble(frag, loopJumps);
|
||||||
verbose_only(if (assm->_verbose)
|
verbose_only(if (asmVerb)
|
||||||
assm->outputf("compiling branch %s ip %s",
|
assm->outputf("## compiling branch %s ip %s",
|
||||||
frago->labels->format(frag),
|
frago->labels->format(frag),
|
||||||
frago->labels->format(frag->ip)); )
|
frago->labels->format(frag->ip)); )
|
||||||
|
|
||||||
@ -2013,14 +2051,29 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
frag = frag->treeBranches;
|
frag = frag->treeBranches;
|
||||||
}
|
}
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== -- Compile the entire tree: end\n");
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// now the the main trunk
|
// now the the main trunk
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("=== -- Compile trunk %s: begin\n",
|
||||||
|
frago->labels->format(root));
|
||||||
|
})
|
||||||
assm->assemble(root, loopJumps);
|
assm->assemble(root, loopJumps);
|
||||||
verbose_only(if (assm->_verbose)
|
verbose_only( if (anyVerb) {
|
||||||
assm->outputf("compiling trunk %s",
|
logc->printf("=== -- Compile trunk %s: end\n",
|
||||||
frago->labels->format(root));)
|
frago->labels->format(root));
|
||||||
NanoAssert(!frago->core()->config.tree_opt || root == root->anchor || root->kind == MergeTrace);
|
})
|
||||||
|
|
||||||
|
verbose_only(
|
||||||
|
if (asmVerb)
|
||||||
|
assm->outputf("## compiling trunk %s",
|
||||||
|
frago->labels->format(root));
|
||||||
|
)
|
||||||
|
NanoAssert(!frago->core()->config.tree_opt
|
||||||
|
|| root == root->anchor || root->kind == MergeTrace);
|
||||||
assm->endAssembly(root, loopJumps);
|
assm->endAssembly(root, loopJumps);
|
||||||
|
|
||||||
// reverse output so that assembly is displayed low-to-high
|
// reverse output so that assembly is displayed low-to-high
|
||||||
@ -2028,14 +2081,37 @@ namespace nanojit
|
|||||||
// has been accumulating output. Now we set it to NULL, traverse
|
// has been accumulating output. Now we set it to NULL, traverse
|
||||||
// the entire list of stored strings, and hand them a second time
|
// the entire list of stored strings, and hand them a second time
|
||||||
// to assm->output. Since _outputCache is now NULL, outputf just
|
// to assm->output. Since _outputCache is now NULL, outputf just
|
||||||
// hands these strings directly onwards to nj_dprintf.
|
// hands these strings directly onwards to logc->printf.
|
||||||
verbose_only( assm->_outputCache = 0; )
|
verbose_only( if (anyVerb) {
|
||||||
verbose_only(for(int i=asmOutput.size()-1; i>=0; --i) { assm->outputf("%s",asmOutput.get(i)); } );
|
logc->printf("\n");
|
||||||
|
logc->printf("=== Aggregated assembly output: BEGIN\n");
|
||||||
|
logc->printf("===\n");
|
||||||
|
assm->_outputCache = 0;
|
||||||
|
for (int i = asmOutput.size() - 1; i >= 0; --i) {
|
||||||
|
char* str = asmOutput.get(i);
|
||||||
|
assm->outputf(" %s", str);
|
||||||
|
gc->Free(str);
|
||||||
|
}
|
||||||
|
logc->printf("===\n");
|
||||||
|
logc->printf("=== Aggregated assembly output: END\n");
|
||||||
|
});
|
||||||
|
|
||||||
if (assm->error()) {
|
if (assm->error()) {
|
||||||
root->fragEntry = 0;
|
root->fragEntry = 0;
|
||||||
root->loopEntry = 0;
|
root->loopEntry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* BEGIN decorative postamble */
|
||||||
|
verbose_only( if (anyVerb) {
|
||||||
|
logc->printf("\n");
|
||||||
|
logc->printf("===\n");
|
||||||
|
logc->printf("=== END LIR::compile(%p, %p)\n",
|
||||||
|
(void*)assm, (void*)triggerFrag);
|
||||||
|
logc->printf("========================================"
|
||||||
|
"========================================\n");
|
||||||
|
logc->printf("\n");
|
||||||
|
});
|
||||||
|
/* END decorative postamble */
|
||||||
}
|
}
|
||||||
|
|
||||||
LInsp LoadFilter::insLoad(LOpcode v, LInsp base, LInsp disp)
|
LInsp LoadFilter::insLoad(LOpcode v, LInsp base, LInsp disp)
|
||||||
@ -2158,6 +2234,19 @@ namespace nanojit
|
|||||||
strcpy(s, b);
|
strcpy(s, b);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// START debug-logging definitions
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
void LogControl::printf( const char* format, ... )
|
||||||
|
{
|
||||||
|
va_list vargs;
|
||||||
|
va_start(vargs, format);
|
||||||
|
vfprintf(stdout, format, vargs);
|
||||||
|
va_end(vargs);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NJ_VERBOSE
|
#endif // NJ_VERBOSE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,9 +582,11 @@ namespace nanojit
|
|||||||
{
|
{
|
||||||
InsList code;
|
InsList code;
|
||||||
DWB(LirNameMap*) names;
|
DWB(LirNameMap*) names;
|
||||||
|
LogControl* logc;
|
||||||
public:
|
public:
|
||||||
VerboseWriter(avmplus::GC *gc, LirWriter *out, LirNameMap* names)
|
VerboseWriter(avmplus::GC *gc, LirWriter *out,
|
||||||
: LirWriter(out), code(gc), names(names)
|
LirNameMap* names, LogControl* logc)
|
||||||
|
: LirWriter(out), code(gc), names(names), logc(logc)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
LInsp add(LInsp i) {
|
LInsp add(LInsp i) {
|
||||||
@ -604,10 +606,10 @@ namespace nanojit
|
|||||||
int n = code.size();
|
int n = code.size();
|
||||||
if (n) {
|
if (n) {
|
||||||
for (int i=0; i < n; i++)
|
for (int i=0; i < n; i++)
|
||||||
nj_dprintf(" %s\n",names->formatIns(code[i]));
|
logc->printf(" %s\n",names->formatIns(code[i]));
|
||||||
code.clear();
|
code.clear();
|
||||||
if (n > 1)
|
if (n > 1)
|
||||||
nj_dprintf("\n");
|
logc->printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,15 +101,17 @@ namespace nanojit {
|
|||||||
#elif defined(NJ_VERBOSE)
|
#elif defined(NJ_VERBOSE)
|
||||||
#define asm_output(...) do { \
|
#define asm_output(...) do { \
|
||||||
counter_increment(native); \
|
counter_increment(native); \
|
||||||
if (verbose_enabled()) {\
|
if (_logc->lcbits & LC_Assembly) { \
|
||||||
outline[0]='\0'; \
|
outline[0]='\0'; \
|
||||||
if (outputAddr) sprintf(outline, " %10p ",_nIns);\
|
if (outputAddr) \
|
||||||
else sprintf(outline, " ");\
|
sprintf(outline, "%010lx ", (unsigned long)_nIns); \
|
||||||
sprintf(&outline[14], ##__VA_ARGS__);\
|
else \
|
||||||
Assembler::outputAlign(outline, 45);\
|
memset(outline, (int)' ', 10+3); \
|
||||||
|
sprintf(&outline[13], ##__VA_ARGS__); \
|
||||||
|
Assembler::outputAlign(outline, 35); \
|
||||||
RegAlloc::formatRegisters(_allocator, outline, _thisfrag); \
|
RegAlloc::formatRegisters(_allocator, outline, _thisfrag); \
|
||||||
Assembler::output_asm(outline); \
|
Assembler::output_asm(outline); \
|
||||||
outputAddr=false; /* set =true if you like to see addresses for each native instruction */ \
|
outputAddr=(_logc->lcbits & LC_NoCodeAddrs) ? false : true; \
|
||||||
} \
|
} \
|
||||||
} while (0) /* no semi */
|
} while (0) /* no semi */
|
||||||
#define gpn(r) regNames[(r)]
|
#define gpn(r) regNames[(r)]
|
||||||
|
@ -157,8 +157,8 @@ Assembler::genPrologue()
|
|||||||
if (amt)
|
if (amt)
|
||||||
SUBi(SP, SP, amt);
|
SUBi(SP, SP, amt);
|
||||||
|
|
||||||
verbose_only( verbose_outputf(" %p:",_nIns); )
|
verbose_only( asm_output("## %p:",(void*)_nIns); )
|
||||||
verbose_only( verbose_output(" patch entry"); )
|
verbose_only( asm_output("## patch entry"); )
|
||||||
NIns *patchEntry = _nIns;
|
NIns *patchEntry = _nIns;
|
||||||
|
|
||||||
MOV(FP, SP);
|
MOV(FP, SP);
|
||||||
@ -694,8 +694,7 @@ Assembler::asm_restore(LInsp i, Reservation *resv, Register r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
verbose_only(
|
verbose_only(
|
||||||
if (_verbose)
|
asm_output(" restore %s",_thisfrag->lirbuf->names->formatRef(i));
|
||||||
outputf(" restore %s",_thisfrag->lirbuf->names->formatRef(i));
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,7 +1075,7 @@ Assembler::JMP_far(NIns* addr)
|
|||||||
// B [PC+offs]
|
// B [PC+offs]
|
||||||
*(--_nIns) = (NIns)( COND_AL | (0xA<<24) | ((offs>>2) & 0xFFFFFF) );
|
*(--_nIns) = (NIns)( COND_AL | (0xA<<24) | ((offs>>2) & 0xFFFFFF) );
|
||||||
|
|
||||||
asm_output("b %p", addr);
|
asm_output("b %p", (void*)addr);
|
||||||
} else {
|
} else {
|
||||||
// Insert the target address as a constant in the instruction stream.
|
// Insert the target address as a constant in the instruction stream.
|
||||||
*(--_nIns) = (NIns)((addr));
|
*(--_nIns) = (NIns)((addr));
|
||||||
@ -1084,7 +1083,7 @@ Assembler::JMP_far(NIns* addr)
|
|||||||
// the next instruction)
|
// the next instruction)
|
||||||
*(--_nIns) = (NIns)( COND_AL | (0x51<<20) | (PC<<16) | (PC<<12) | (4));
|
*(--_nIns) = (NIns)( COND_AL | (0x51<<20) | (PC<<16) | (PC<<12) | (4));
|
||||||
|
|
||||||
asm_output("ldr pc, =%p", addr);
|
asm_output("ldr pc, =%p", (void*)addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,7 +1122,7 @@ Assembler::BranchWithLink(NIns* addr)
|
|||||||
// BL addr
|
// BL addr
|
||||||
NanoAssert( ((offs>>2) & ~0xffffff) == 0);
|
NanoAssert( ((offs>>2) & ~0xffffff) == 0);
|
||||||
*(--_nIns) = (NIns)( (COND_AL) | (0xB<<24) | (offs>>2) );
|
*(--_nIns) = (NIns)( (COND_AL) | (0xB<<24) | (offs>>2) );
|
||||||
asm_output("bl %p", addr);
|
asm_output("bl %p", (void*)addr);
|
||||||
} else {
|
} else {
|
||||||
// The target is Thumb, so emit a BLX.
|
// The target is Thumb, so emit a BLX.
|
||||||
|
|
||||||
@ -1133,12 +1132,12 @@ Assembler::BranchWithLink(NIns* addr)
|
|||||||
// BLX addr
|
// BLX addr
|
||||||
NanoAssert( ((offs>>2) & ~0xffffff) == 0);
|
NanoAssert( ((offs>>2) & ~0xffffff) == 0);
|
||||||
*(--_nIns) = (NIns)( (0xF << 28) | (0x5<<25) | (H) | (offs>>2) );
|
*(--_nIns) = (NIns)( (0xF << 28) | (0x5<<25) | (H) | (offs>>2) );
|
||||||
asm_output("blx %p", addr);
|
asm_output("blx %p", (void*)addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// BLX IP
|
// BLX IP
|
||||||
*(--_nIns) = (NIns)( (COND_AL) | (0x12<<20) | (0xFFF<<8) | (0x3<<4) | (IP) );
|
*(--_nIns) = (NIns)( (COND_AL) | (0x12<<20) | (0xFFF<<8) | (0x3<<4) | (IP) );
|
||||||
asm_output("blx ip (=%p)", addr);
|
asm_output("blx ip (=%p)", (void*)addr);
|
||||||
|
|
||||||
// LDR IP, =addr
|
// LDR IP, =addr
|
||||||
LD32_nochk(IP, (int32_t)addr);
|
LD32_nochk(IP, (int32_t)addr);
|
||||||
@ -1193,7 +1192,7 @@ Assembler::LD32_nochk(Register r, int32_t imm)
|
|||||||
|
|
||||||
// Write the literal.
|
// Write the literal.
|
||||||
*(++_nSlot) = imm;
|
*(++_nSlot) = imm;
|
||||||
asm_output(" (%d(PC) = 0x%x)", offset, imm);
|
asm_output("## imm= 0x%x", imm);
|
||||||
|
|
||||||
// Load the literal.
|
// Load the literal.
|
||||||
LDR_nochk(r,PC,offset);
|
LDR_nochk(r,PC,offset);
|
||||||
|
@ -414,7 +414,9 @@ namespace nanojit
|
|||||||
void Assembler::asm_restore(LInsp i, Reservation *resv, Register r)
|
void Assembler::asm_restore(LInsp i, Reservation *resv, Register r)
|
||||||
{
|
{
|
||||||
if (i->isop(LIR_alloc)) {
|
if (i->isop(LIR_alloc)) {
|
||||||
verbose_only( if (_verbose) { outputForEOL(" <= remat %s size %d", _thisfrag->lirbuf->names->formatRef(i), i->size()); } )
|
verbose_only( if (_logc->lcbits & LC_RegAlloc) {
|
||||||
|
outputForEOL(" <= remat %s size %d",
|
||||||
|
_thisfrag->lirbuf->names->formatRef(i), i->size()); } )
|
||||||
LEA(r, disp(resv), FP);
|
LEA(r, disp(resv), FP);
|
||||||
}
|
}
|
||||||
else if (i->isconst()) {
|
else if (i->isconst()) {
|
||||||
@ -425,7 +427,9 @@ namespace nanojit
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int d = findMemFor(i);
|
int d = findMemFor(i);
|
||||||
verbose_only( if (_verbose) { outputForEOL(" <= restore %s", _thisfrag->lirbuf->names->formatRef(i)); } )
|
verbose_only( if (_logc->lcbits & LC_RegAlloc) {
|
||||||
|
outputForEOL(" <= restore %s",
|
||||||
|
_thisfrag->lirbuf->names->formatRef(i)); } )
|
||||||
asm_load(d,r);
|
asm_load(d,r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,14 +540,14 @@ namespace nanojit
|
|||||||
_nIns -= 2; \
|
_nIns -= 2; \
|
||||||
_nIns[0] = (uint8_t) ( 0x70 | (o) ); \
|
_nIns[0] = (uint8_t) ( 0x70 | (o) ); \
|
||||||
_nIns[1] = (uint8_t) (tt); \
|
_nIns[1] = (uint8_t) (tt); \
|
||||||
asm_output("%s %p",(n),(next+tt)); \
|
asm_output("%-5s %p",(n),(next+tt)); \
|
||||||
} else { \
|
} else { \
|
||||||
verbose_only( NIns* next = _nIns; ) \
|
verbose_only( NIns* next = _nIns; ) \
|
||||||
IMM32(tt); \
|
IMM32(tt); \
|
||||||
_nIns -= 2; \
|
_nIns -= 2; \
|
||||||
_nIns[0] = JCC32; \
|
_nIns[0] = JCC32; \
|
||||||
_nIns[1] = (uint8_t) ( 0x80 | (o) ); \
|
_nIns[1] = (uint8_t) ( 0x80 | (o) ); \
|
||||||
asm_output("%s %p",(n),(next+tt)); \
|
asm_output("%-5s %p",(n),(next+tt)); \
|
||||||
} } while(0)
|
} } while(0)
|
||||||
|
|
||||||
#define JMP_long(t) do { \
|
#define JMP_long(t) do { \
|
||||||
@ -555,7 +555,7 @@ namespace nanojit
|
|||||||
underrunProtect(5); \
|
underrunProtect(5); \
|
||||||
intptr_t tt = (intptr_t)t - (intptr_t)_nIns; \
|
intptr_t tt = (intptr_t)t - (intptr_t)_nIns; \
|
||||||
JMP_long_nochk_offset(tt); \
|
JMP_long_nochk_offset(tt); \
|
||||||
verbose_only( verbose_outputf(" %p:",_nIns); ) \
|
verbose_only( verbose_outputf("%010lx:", (unsigned long)_nIns); ) \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define JMP(t) do { \
|
#define JMP(t) do { \
|
||||||
|
@ -323,7 +323,7 @@ namespace avmplus {
|
|||||||
Config() {
|
Config() {
|
||||||
memset(this, 0, sizeof(Config));
|
memset(this, 0, sizeof(Config));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
verbose = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "verbose");
|
verbose = false;
|
||||||
verbose_addrs = 1;
|
verbose_addrs = 1;
|
||||||
verbose_exits = 1;
|
verbose_exits = 1;
|
||||||
verbose_live = 1;
|
verbose_live = 1;
|
||||||
|
@ -181,20 +181,16 @@ namespace nanojit
|
|||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
#if defined(_MSC_VER) && _MSC_VER < 1400
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define verbose_output if (verbose_enabled()) Assembler::output
|
#define verbose_outputf if (_logc->lcbits & LC_Assembly) \
|
||||||
#define verbose_outputf if (verbose_enabled()) Assembler::outputf
|
Assembler::outputf
|
||||||
#define verbose_enabled() (_verbose)
|
|
||||||
#define verbose_only(x) x
|
#define verbose_only(x) x
|
||||||
#elif defined(NJ_VERBOSE)
|
#elif defined(NJ_VERBOSE)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define verbose_output if (verbose_enabled()) Assembler::output
|
#define verbose_outputf if (_logc->lcbits & LC_Assembly) \
|
||||||
#define verbose_outputf if (verbose_enabled()) Assembler::outputf
|
Assembler::outputf
|
||||||
#define verbose_enabled() (_verbose)
|
|
||||||
#define verbose_only(...) __VA_ARGS__
|
#define verbose_only(...) __VA_ARGS__
|
||||||
#else
|
#else
|
||||||
#define verbose_output
|
|
||||||
#define verbose_outputf
|
#define verbose_outputf
|
||||||
#define verbose_enabled()
|
|
||||||
#define verbose_only(...)
|
#define verbose_only(...)
|
||||||
#endif /*NJ_VERBOSE*/
|
#endif /*NJ_VERBOSE*/
|
||||||
|
|
||||||
@ -243,11 +239,18 @@ namespace nanojit
|
|||||||
#define samepage(x,y) ( pageTop(x) == pageTop(y) )
|
#define samepage(x,y) ( pageTop(x) == pageTop(y) )
|
||||||
|
|
||||||
|
|
||||||
/* Debug printing stuff. All Nanojit debug printing should be routed
|
// -------------------------------------------------------------------
|
||||||
through this function. Don't use ad-hoc calls to printf,
|
// START debug-logging definitions
|
||||||
fprintf(stderr, ...) etc. */
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(NJ_VERBOSE)
|
/* Debug printing stuff. All Nanojit and jstracer debug printing
|
||||||
|
should be routed through LogControl::printf. Don't use
|
||||||
|
ad-hoc calls to printf, fprintf(stderr, ...) etc.
|
||||||
|
|
||||||
|
Similarly, don't use ad-hoc getenvs etc to decide whether or not to
|
||||||
|
print debug output. Instead consult the relevant control bit in
|
||||||
|
LogControl::lcbits in the LogControl object you are supplied with.
|
||||||
|
*/
|
||||||
|
|
||||||
# if defined(__GNUC__)
|
# if defined(__GNUC__)
|
||||||
# define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y)))
|
# define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y)))
|
||||||
@ -255,10 +258,41 @@ namespace nanojit
|
|||||||
# define PRINTF_CHECK(x, y)
|
# define PRINTF_CHECK(x, y)
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* is in LIR.cpp */
|
namespace nanojit {
|
||||||
void nj_dprintf( const char* format, ... ) PRINTF_CHECK(1,2);
|
|
||||||
|
|
||||||
#endif /* NJ_VERBOSE */
|
// LogControl, a class for controlling and routing debug output
|
||||||
|
|
||||||
|
enum LC_Bits {
|
||||||
|
/* Output control bits for Nanojit code. Only use bits 15
|
||||||
|
and below, so that callers can use bits 16 and above for
|
||||||
|
themselves. */
|
||||||
|
// TODO: add entries for the writer pipeline
|
||||||
|
LC_Liveness = 1<<7, // (show LIR liveness analysis)
|
||||||
|
LC_ReadLIR = 1<<6, // As read from LirBuffer
|
||||||
|
LC_AfterSF_SP = 1<<5, // After StackFilter(sp)
|
||||||
|
LC_AfterSF_RP = 1<<4, // After StackFilter(rp)
|
||||||
|
LC_AfterDeadF = 1<<3, // After DeadFilter
|
||||||
|
LC_RegAlloc = 1<<2, // stuff to do with reg alloc
|
||||||
|
LC_Assembly = 1<<1, // final assembly
|
||||||
|
LC_NoCodeAddrs = 1<<0 // (don't show code addresses on asm output)
|
||||||
|
};
|
||||||
|
|
||||||
|
class LogControl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// All Nanojit and jstracer printing should be routed through
|
||||||
|
// this function.
|
||||||
|
void printf( const char* format, ... ) PRINTF_CHECK(2,3);
|
||||||
|
|
||||||
|
// An OR of LC_Bits values, indicating what should be output
|
||||||
|
uint32_t lcbits;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// END debug-logging definitions
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user