Sync with TT-tip.
Sync with TT-tip.
--- a/js/src/Makefile.ref
+++ b/js/src/Makefile.ref
@@ -189,16 +189,17 @@ JS_HFILES = \
nanojit/Nativei386.h \
nanojit/avmplus.h \
nanojit/vm_fops.h \
nanojit/Fragmento.h \
nanojit/Native.h \
nanojit/NativeThumb.h \
nanojit/RegAlloc.h \
nanojit/nanojit.h \
+ nanojit/TraceTreeDrawer.h \
$(NULL)
API_HFILES = \
jsapi.h \
jsdbgapi.h \
$(NULL)
OTHER_HFILES = \
@@ -264,16 +265,17 @@ JS_CPPFILES = \
prmjtime.cpp \
nanojit/Assembler.cpp \
nanojit/Fragmento.cpp \
nanojit/LIR.cpp \
nanojit/Nativei386.cpp \
nanojit/RegAlloc.cpp \
nanojit/avmplus.cpp \
nanojit/Tests.cpp \
+ nanojit/TraceTreeDrawer.cpp \
$(NULL)
ifdef JS_LIVECONNECT
DIRS += liveconnect
endif
ifdef JS_HAS_FILE_OBJECT
JS_CPPFILES += jsfile.cpp
--- a/js/src/nanojit/Assembler.cpp
+++ b/js/src/nanojit/Assembler.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -533,16 +534,22 @@ namespace nanojit
void Assembler::evict(Register r)
{
registerAlloc(rmask(r));
_allocator.addFree(r);
}
void Assembler::asm_cmp(LIns *cond)
{
+ LOpcode condop = cond->opcode();
+
+ // LIR_ov and LIR_cs recycle the flags set by arithmetic ops
+ if ((condop == LIR_ov) || (condop == LIR_cs))
+ return;
+
LInsp lhs = cond->oprnd1();
LInsp rhs = cond->oprnd2();
NanoAssert(!lhs->isQuad() && !rhs->isQuad());
Reservation *rA, *rB;
// ready to issue the compare
if (rhs->isconst())
{
@@ -1027,16 +1034,18 @@ namespace nanojit
// this code assumes that neither LD nor MR nor MRcc set any of the condition flags.
// (This is true on Intel, is it true on all architectures?)
const Register iffalsereg = findRegFor(iffalse, GpRegs & ~rmask(rr));
switch (condval->opcode())
{
// note that these are all opposites...
case LIR_eq: MRNE(rr, iffalsereg); break;
+ case LIR_ov: MRNO(rr, iffalsereg); break;
+ case LIR_cs: MRNC(rr, iffalsereg); break;
case LIR_lt: MRGE(rr, iffalsereg); break;
case LIR_le: MRG(rr, iffalsereg); break;
case LIR_gt: MRLE(rr, iffalsereg); break;
case LIR_ge: MRL(rr, iffalsereg); break;
case LIR_ult: MRAE(rr, iffalsereg); break;
case LIR_ule: MRA(rr, iffalsereg); break;
case LIR_ugt: MRBE(rr, iffalsereg); break;
case LIR_uge: MRB(rr, iffalsereg); break;
@@ -1444,16 +1453,20 @@ namespace nanojit
break;
}
#endif
// produce the branch
if (op == LIR_xf)
{
if (condop == LIR_eq)
JNE(exit);
+ else if (condop == LIR_ov)
+ JNO(exit);
+ else if (condop == LIR_cs)
+ JNC(exit);
else if (condop == LIR_lt)
JNL(exit);
else if (condop == LIR_le)
JNLE(exit);
else if (condop == LIR_gt)
JNG(exit);
else if (condop == LIR_ge)
JNGE(exit);
@@ -1463,18 +1476,22 @@ namespace nanojit
JNBE(exit);
else if (condop == LIR_ugt)
JNA(exit);
else //if (condop == LIR_uge)
JNAE(exit);
}
else // op == LIR_xt
{
- if (condop == LIR_eq)
+ if (condop == LIR_eq)
JE(exit);
+ else if (condop == LIR_ov)
+ JO(exit);
+ else if (condop == LIR_cs)
+ JC(exit);
else if (condop == LIR_lt)
JL(exit);
else if (condop == LIR_le)
JLE(exit);
else if (condop == LIR_gt)
JG(exit);
else if (condop == LIR_ge)
JGE(exit);
@@ -1482,17 +1499,17 @@ namespace nanojit
JB(exit);
else if (condop == LIR_ule)
JBE(exit);
else if (condop == LIR_ugt)
JA(exit);
else //if (condop == LIR_uge)
JAE(exit);
}
- asm_cmp(cond);
+ asm_cmp(cond);
break;
}
case LIR_x:
{
verbose_only(verbose_output(""));
// generate the side exit branch on the main trace.
NIns *exit = asm_exit(ins);
JMP( exit );
@@ -1529,48 +1546,54 @@ namespace nanojit
// SETcc only sets low 8 bits, so extend
MOVZX8(r,r);
SETNP(r);
asm_fcmp(ins);
break;
}
#endif
case LIR_eq:
+ case LIR_ov:
+ case LIR_cs:
case LIR_le:
case LIR_lt:
case LIR_gt:
case LIR_ge:
case LIR_ult:
case LIR_ule:
case LIR_ugt:
case LIR_uge:
{
// only want certain regs
Register r = prepResultReg(ins, AllowableFlagRegs);
// SETcc only sets low 8 bits, so extend
MOVZX8(r,r);
if (op == LIR_eq)
SETE(r);
+ else if (op == LIR_ov)
+ SETO(r);
+ else if (op == LIR_cs)
+ SETC(r);
else if (op == LIR_lt)
SETL(r);
else if (op == LIR_le)
SETLE(r);
else if (op == LIR_gt)
SETG(r);
else if (op == LIR_ge)
SETGE(r);
else if (op == LIR_ult)
SETB(r);
else if (op == LIR_ule)
SETBE(r);
else if (op == LIR_ugt)
SETA(r);
else // if (op == LIR_uge)
SETAE(r);
- asm_cmp(ins);
+ asm_cmp(ins);
break;
}
case LIR_ref:
{
// ref arg - use lea
LIns *p = ins->oprnd1();
if (ins->resv())
{
--- a/js/src/nanojit/Assembler.h
+++ b/js/src/nanojit/Assembler.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
--- a/js/src/nanojit/Fragmento.cpp
+++ b/js/src/nanojit/Fragmento.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -265,22 +266,22 @@ namespace nanojit
if (f->eot_target) {
sprintf(cause,"%s %s", f->_token, labels->format(f->eot_target));
} else {
strcpy(cause, f->_token);
}
}
else
cause[0] = 0;
-
- FOpcodep ip = f->frid;
+
+ FOpcodep ip = f->frid;
_assm->outputf("%-*s %7d %6d %6d %6d %4d %9llu %9llu %-12s %s", namewidth, buf,
called, f->guardCount, main, f->_native, f->compileNbr, f->traceTicks/1000, f->interpTicks/1000,
cause, core()->interp.labels->format(ip));
-
+
size += main;
traceDur += f->traceTicks;
interpDur += f->interpTicks;
for (Fragment *x = f->branches; x != 0; x = x->nextbranch)
if (x->kind != MergeTrace)
dumpFragStats(x,level+1,size,traceDur,interpDur);
for (Fragment *x = f->branches; x != 0; x = x->nextbranch)
@@ -403,16 +404,22 @@ namespace nanojit
_assm->outputf("++ %s %d", core()->interp.labels->format(ip), c);
}
void Fragmento::countIL(uint32_t il, uint32_t abc)
{
_stats.ilsize += il;
_stats.abcsize += abc;
}
+
+#ifdef AVMPLUS_VERBOSE
+ void Fragmento::drawTrees(avmplus::AvmString fileName) {
+ drawTraceTrees(this, this->_frags, this->_core, fileName);
+ }
+#endif
#endif // NJ_VERBOSE
//
// Fragment
//
Fragment::Fragment(FragID id) : frid(id)
{
// Fragment is a gc object which is zero'd by the GC, no need to clear fields
@@ -643,11 +650,12 @@ namespace nanojit
if (target == x->nextbranch) {
x->nextbranch = x->nextbranch->nextbranch;
// @todo this doesn't seem righ : target->clear();
return;
}
}
}
}
-
#endif /* FEATURE_NANOJIT */
}
+
+
--- a/js/src/nanojit/Fragmento.h
+++ b/js/src/nanojit/Fragmento.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -34,17 +35,19 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nanojit_Fragmento__
#define __nanojit_Fragmento__
-
+#ifdef AVMPLUS_VERBOSE
+extern void drawTraceTrees(Fragmento *frago, FragmentMap * _frags, avmplus::AvmCore *core, avmplus::AvmString fileName);
+#endif
namespace nanojit
{
struct GuardRecord;
class Assembler;
struct PageHeader
{
@@ -100,28 +103,33 @@ namespace nanojit
verbose_only ( uint32_t pageCount(); )
verbose_only ( void dumpStats(); )
verbose_only ( void dumpRatio(const char*, BlockHist*);)
verbose_only ( void dumpFragStats(Fragment*, int level,
int& size, uint64_t &dur, uint64_t &interpDur); )
verbose_only ( void countBlock(BlockHist*, avmplus::FOpcodep pc); )
verbose_only ( void countIL(uint32_t il, uint32_t abc); )
verbose_only( void addLabel(Fragment* f, const char *prefix, int id); )
-
+
// stats
struct
{
uint32_t pages; // pages consumed
uint32_t flushes, ilsize, abcsize, compiles, totalCompiles, freePages;
}
_stats;
verbose_only( DWB(BlockHist*) enterCounts; )
verbose_only( DWB(BlockHist*) mergeCounts; )
verbose_only( DWB(LabelMap*) labels; )
+
+ #ifdef AVMPLUS_VERBOSE
+ void drawTrees(avmplus::AvmString fileName);
+ #endif
+
private:
void pagesGrow(int32_t count);
AvmCore* _core;
DWB(Assembler*) _assm;
DWB(FragmentMap*) _frags; /* map from ip -> Fragment ptr */
Page* _pageList;
--- a/js/src/nanojit/LIR.cpp
+++ b/js/src/nanojit/LIR.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -45,17 +46,17 @@ namespace nanojit
#ifdef FEATURE_NANOJIT
const uint8_t operandCount[] = {
/* 0 */ 2, 2, /*trace*/0, /*skip*/0, /*tramp*/0, 2, 2, 2, 2, /*arg*/1,
/* 10 */ /*param*/0, 2, 2, /*ref*/1, 2, 2, 2, 2, /*call*/0, /*loop*/0,
/* 20 */ /*x*/0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 30 */ 2, 2, /*short*/0, /*int*/0, 2, 2, /*neg*/1, 2, 2, 2,
/* 40 */ /*callh*/1, 2, 2, 2, /*not*/1, 2, 2, 2, /*xt*/1, /*xf*/1,
- /* 50 */ /*qlo*/1, /*qhi*/1, 2, 2, 2, 2, 2, 2, 2, 2,
+ /* 50 */ /*qlo*/1, /*qhi*/1, 2, 1, 1, 2, 2, 2, 2, 2,
/* 60 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 70 */ 2, 2, 2, /*farg*/1, 2, 2, 2, 2, 2, 2,
/* 80 */ 2, 2, /*fcall*/0, 2, 2, 2, 2, 2, 2, 2,
/* 90 */ 2, 2, 2, 2, 2, 2, 2, /*quad*/0, 2, 2,
/* 100 */ /*fneg*/1, 2, 2, 2, 2, 2, /*i2f*/1, /*u2f*/1, 2, 2,
/* 110 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 120 */ 2, 2, 2, 2, 2, 2, 2, 2,
};
@@ -64,17 +65,17 @@ namespace nanojit
#ifdef NJ_VERBOSE
const char* lirNames[] = {
/* 0-9 */ "0","1","trace","skip","tramp","5","6","7","8","arg",
/* 10-19 */ "param","st","ld","ref","sti","15","16","17","call","loop",
/* 20-29 */ "x","21","22","23","24","25","feq","flt","fgt","fle",
/* 30-39 */ "fge","cmov","short","int","ldc","","neg","add","sub","mul",
/* 40-49 */ "callh","and","or","xor","not","lsh","rsh","ush","xt","xf",
- /* 50-59 */ "qlo","qhi","ldcb","53","54","eq","lt","gt","le","ge",
+ /* 50-59 */ "qlo","qhi","ldcb","ov","cs","eq","lt","gt","le","ge",
/* 60-63 */ "ult","ugt","ule","uge",
/* 64-69 */ "LIR64","65","66","67","68","69",
/* 70-79 */ "70","71","72","farg","74","stq","ldq","77","stqi","79",
/* 80-89 */ "80","81","fcall","83","84","85","86","87","88","89",
/* 90-99 */ "90","91","92","93","94","95","96","quad","98","99",
/* 100-109 */ "fneg","fadd","fsub","fmul","fdiv","qjoin","i2f","u2f","108","109",
/* 110-119 */ "110","111","112","113","114","115","116","117","118","119",
/* 120-127 */ "120","121","122","123","124","125","126","127"
@@ -437,21 +438,29 @@ namespace nanojit
while (is_trace_skip_tramp(iop)||iop==LIR_2);
_i = i;
return cur;
}
bool FASTCALL isCmp(LOpcode c) {
return c >= LIR_eq && c <= LIR_uge || c >= LIR_feq && c <= LIR_fge;
}
-
+
+ bool FASTCALL isCond(LOpcode c) {
+ return (c == LIR_ov) || (c == LIR_cs) || isCmp(c);
+ }
+
bool LIns::isCmp() const {
return nanojit::isCmp(u.code);
}
+ bool LIns::isCond() const {
+ return nanojit::isCond(u.code);
+ }
+
bool LIns::isCall() const
{
return (u.code&~LIR64) == LIR_call;
}
bool LIns::isGuard() const
{
return u.code==LIR_x || u.code==LIR_xf || u.code==LIR_xt;
@@ -656,16 +665,20 @@ namespace nanojit
int c1 = oprnd1->constval();
int c2 = oprnd2->constval();
if (v == LIR_qjoin) {
uint64_t q = c1 | uint64_t(c2)<<32;
return insImmq(q);
}
if (v == LIR_eq)
return insImm(c1 == c2);
+ if (v == LIR_ov)
+ return insImm((c2 != 0) && ((c1 + c2) <= c1));
+ if (v == LIR_cs)
+ return insImm((c2 != 0) && ((uint32_t(c1) + uint32_t(c2)) <= uint32_t(c1)));
if (v == LIR_lt)
return insImm(c1 < c2);
if (v == LIR_gt)
return insImm(c1 > c2);
if (v == LIR_le)
return insImm(c1 <= c2);
if (v == LIR_ge)
return insImm(c1 >= c2);
@@ -834,16 +847,21 @@ namespace nanojit
return ins2i(LIR_eq, oprnd1, 0);
}
LIns* LirWriter::qjoin(LInsp lo, LInsp hi)
{
return ins2(LIR_qjoin, lo, hi);
}
+ LIns* LirWriter::insImmPtr(const void *ptr)
+ {
+ return sizeof(ptr) == 8 ? insImmq((uintptr_t)ptr) : insImm((intptr_t)ptr);
+ }
+
LIns* LirWriter::ins_choose(LIns* cond, LIns* iftrue, LIns* iffalse, bool hasConditionalMove)
{
// if not a conditional, make it implicitly an ==0 test (then flop results)
if (!cond->isCmp())
{
cond = ins_eq0(cond);
LInsp tmp = iftrue;
iftrue = iffalse;
@@ -1541,16 +1559,18 @@ namespace nanojit
case LIR_fneg:
case LIR_arg:
case LIR_farg:
case LIR_i2f:
case LIR_u2f:
case LIR_qlo:
case LIR_qhi:
case LIR_ref:
+ case LIR_ov:
+ case LIR_cs:
sprintf(s, "%s %s", lirNames[op], formatRef(i->oprnd1()));
break;
case LIR_xt:
case LIR_xf: {
SideExit *x = (SideExit*) i->oprnd2()->payload();
uint32_t ip = int32_t(x->from->frid) + x->ip_adj;
sprintf(s, "%s: %s %s -> %s sp%+d rp%+d f%+d",
--- a/js/src/nanojit/LIR.h
+++ b/js/src/nanojit/LIR.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -93,16 +94,18 @@ namespace nanojit
LIR_ush = 47, // >>>
// conditional guards, op^1 to complement
LIR_xt = 48, // exit if true 0x30 0011 0000
LIR_xf = 49, // exit if false 0x31 0011 0001
LIR_qlo = 50,
LIR_qhi = 51,
LIR_ldcb = 52, // non-volatile 8-bit load
+ LIR_ov = 53,
+ LIR_cs = 54,
LIR_eq = 55,
// relational operators. op^1 to swap left/right, op^3 to complement.
LIR_lt = 56, // 0x38 0011 1000
LIR_gt = 57, // 0x39 0011 1001
LIR_le = 58, // 0x3A 0011 1010
LIR_ge = 59, // 0x3B 0011 1011
LIR_ult = 60, // 0x3C 0011 1100
LIR_ugt = 61, // 0x3D 0011 1101
@@ -122,17 +125,17 @@ namespace nanojit
LIR_fneg = LIR_neg | LIR64,
LIR_fadd = LIR_add | LIR64,
LIR_fsub = LIR_sub | LIR64,
LIR_fmul = LIR_mul | LIR64,
LIR_fdiv = 40 | LIR64,
LIR_qjoin = 41 | LIR64,
LIR_i2f = 42 | LIR64,
- LIR_u2f = 43 | LIR64,
+ LIR_u2f = 43 | LIR64
};
struct SideExit;
struct Page;
struct CallInfo;
// Low-level Instruction 4B
// had to lay it our as a union with duplicate code fields since msvc couldn't figure out how to compact it otherwise.
@@ -274,16 +277,17 @@ namespace nanojit
return u.tmpf;
#endif
}
bool isCse(const CallInfo *functions) const;
bool isop(LOpcode o) const { return u.code == o; }
bool isQuad() const { return (u.code & LIR64) != 0; }
bool isArg() const { return (u.code & ~LIR64)==LIR_arg || u.code == LIR_ref; }
+ bool isCond() const;
bool isCmp() const;
bool isCall() const;
bool isStore() const;
bool isLoad() const;
bool isGuard() const;
bool isconst() const;
bool isconstval(int32_t val) const;
bool isconstq() const;
@@ -299,16 +303,17 @@ namespace nanojit
void setDisp(int8_t d);
SideExit *exit();
};
typedef LIns* LInsp;
bool FASTCALL isCse(LOpcode v);
bool FASTCALL isCmp(LOpcode v);
+ bool FASTCALL isCond(LOpcode v);
LIns* FASTCALL callArgN(LInsp i, uint32_t n);
extern const uint8_t operandCount[];
class Fragmento; // @todo remove this ; needed for minbuild for some reason?!? Should not be compiling this code at all
class LirFilter;
struct CallInfo;
class LirWriter
@@ -359,16 +364,17 @@ namespace nanojit
// convenience
LIns* insLoadi(LIns *base, int disp);
LIns* insLoad(LOpcode op, LIns *base, int disp);
LIns* ins_choose(LIns* cond, LIns* iftrue, LIns* iffalse, bool);
LIns* ins_eq0(LIns* oprnd1);
LIns* ins2i(LOpcode op, LIns *oprnd1, int32_t);
LIns* qjoin(LInsp lo, LInsp hi);
+ LIns* insImmPtr(const void *ptr);
};
#ifdef NJ_VERBOSE
extern const char* lirNames[];
/**
* map address ranges to meaningful names.
*/
@@ -415,33 +421,91 @@ namespace nanojit
Entry(avmplus::String *n) : name(n) {}
DRCWB(avmplus::String*) name;
};
avmplus::SortedMap<LInsp, Entry*, avmplus::LIST_GCObjects> names;
const CallInfo *_functions;
LabelMap *labels;
void formatImm(int32_t c, char *buf);
public:
- const uint16_t* codepool;
LirNameMap(GC *gc, const CallInfo *_functions, LabelMap *r)
: lircounts(gc),
funccounts(gc),
names(gc),
_functions(_functions),
labels(r)
{}
void addName(LInsp i, const char *s);
void addName(LInsp i, avmplus::String *s);
void copyName(LInsp i, const char *s, int suffix);
const char *formatRef(LIns *ref);
const char *formatIns(LInsp i);
};
+ class VerboseWriter : public LirWriter
+ {
+ avmplus::List<LInsp, avmplus::LIST_NonGCObjects> code;
+ LirNameMap *names;
+ public:
+ VerboseWriter(GC *gc, LirWriter *out, LirNameMap* names)
+ : LirWriter(out), code(gc), names(names)
+ {}
+
+ LInsp add(LInsp i) {
+ code.add(i);
+ return i;
+ }
+
+ void flush()
+ {
+ for (int j=0, n=code.size(); j < n; j++)
+ printf(" %s\n",names->formatIns(code[j]));
+ code.clear();
+ printf("\n");
+ }
+
+ LIns* insGuard(LOpcode op, LInsp cond, SideExit *x) {
+ LInsp i = add(out->insGuard(op,cond,x));
+ if (i)
+ flush();
+ return i;
+ }
+
+ LIns* ins0(LOpcode v) {
+ LInsp i = add(out->ins0(v));
+ if (i)
+ flush();
+ return i;
+ }
+
+ LIns* ins1(LOpcode v, LInsp a) {
+ return add(out->ins1(v, a));
+ }
+ LIns* ins2(LOpcode v, LInsp a, LInsp b) {
+ return v == LIR_2 ? out->ins2(v,a,b) : add(out->ins2(v, a, b));
+ }
+ LIns* insCall(int32_t fid, LInsp args[]) {
+ return add(out->insCall(fid, args));
+ }
+ LIns* insImm8(LOpcode v, int32_t a, int32_t b) {
+ return add(out->insImm8(v, a, b));
+ }
+ LIns* insLoad(LOpcode v, LInsp base, LInsp disp) {
+ return add(out->insLoad(v, base, disp));
+ }
+ LIns* insStore(LInsp v, LInsp b, LInsp d) {
+ return add(out->insStore(v, b, d));
+ }
+ LIns* insStorei(LInsp v, LInsp b, int32_t d) {
+ return add(out->insStorei(v, b, d));
+ }
+ };
+
#endif
class ExprFilter: public LirWriter
{
public:
ExprFilter(LirWriter *out) : LirWriter(out) {}
LIns* ins1(LOpcode v, LIns* a);
LIns* ins2(LOpcode v, LIns* a, LIns* b);
--- a/js/src/nanojit/Native.h
+++ b/js/src/nanojit/Native.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
--- a/js/src/nanojit/NativeARM.h
+++ b/js/src/nanojit/NativeARM.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
--- a/js/src/nanojit/NativeThumb.h
+++ b/js/src/nanojit/NativeThumb.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
--- a/js/src/nanojit/Nativei386.cpp
+++ b/js/src/nanojit/Nativei386.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -92,17 +93,23 @@ namespace nanojit
MR(FP, SP);
PUSHr(FP); // push ebp twice to align frame on 8bytes
PUSHr(FP);
for(Register i=FirstReg; i <= LastReg; i = nextreg(i))
if (needSaving&rmask(i))
PUSHr(i);
- #ifndef DARWIN
+ // As of late 2006, Linux GCC aligns the stack to a 16-byte
+ // boundary in 'main', and keeps it that way, so there's no
+ // need to align it explicitly:
+ // http://gcc.gnu.org/ml/gcc-patches/2006-09/msg00298.html
+ // The same is true on Darwin:
+ // http://gcc.gnu.org/ml/gcc-patches/2007-06/msg00505.html
+ #if ! defined(DARWIN) && ! defined(__GNUC__)
// dynamically align the stack
PUSHr(FP);//fake returnaddr.
ANDi(SP, -NJ_ALIGN_STACK);
MR(FP,SP);
PUSHr(FP);
#endif
return patchEntry;
--- a/js/src/nanojit/Nativei386.h
+++ b/js/src/nanojit/Nativei386.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -51,21 +52,20 @@ namespace nanojit
const int NJ_STACK_OFFSET = 0;
// WARNING: setting this allows the NJ to growth memory as needed without bounds
const bool NJ_UNLIMITED_GROWTH = true;
#define NJ_MAX_STACK_ENTRY 256
#define NJ_MAX_PARAMETERS 1
-#ifdef DARWIN
+ // Preserve a 16-byte stack alignment, to support the use of
+ // SSE instructions like MOVDQA (if not by Tamarin itself,
+ // then by the C functions it calls).
const int NJ_ALIGN_STACK = 16;
-#else
- const int NJ_ALIGN_STACK = 8;
-#endif
typedef uint8_t NIns;
// These are used as register numbers in various parts of the code
typedef enum
{
// general purpose 32bit regs
EAX = 0, // return value, scratch
@@ -318,17 +318,19 @@ namespace nanojit
#define MRNE(dr,sr) do { ALU2(0x0f45,dr,sr); asm_output2("cmovne %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRL(dr,sr) do { ALU2(0x0f4C,dr,sr); asm_output2("cmovl %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRLE(dr,sr) do { ALU2(0x0f4E,dr,sr); asm_output2("cmovle %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRG(dr,sr) do { ALU2(0x0f4F,dr,sr); asm_output2("cmovg %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRGE(dr,sr) do { ALU2(0x0f4D,dr,sr); asm_output2("cmovge %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRB(dr,sr) do { ALU2(0x0f42,dr,sr); asm_output2("cmovb %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRBE(dr,sr) do { ALU2(0x0f46,dr,sr); asm_output2("cmovbe %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRA(dr,sr) do { ALU2(0x0f47,dr,sr); asm_output2("cmova %s,%s", gpn(dr),gpn(sr)); } while(0)
+#define MRNC(dr,sr) do { ALU2(0x0f43,dr,sr); asm_output2("cmovnc %s,%s", gpn(dr),gpn(sr)); } while(0)
#define MRAE(dr,sr) do { ALU2(0x0f43,dr,sr); asm_output2("cmovae %s,%s", gpn(dr),gpn(sr)); } while(0)
+#define MRNO(dr,sr) do { ALU2(0x0f41,dr,sr); asm_output2("cmovno %s,%s", gpn(dr),gpn(sr)); } while(0)
// these aren't currently used but left in for reference
//#define LDEQ(r,d,b) do { ALU2m(0x0f44,r,d,b); asm_output3("cmove %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
//#define LDNEQ(r,d,b) do { ALU2m(0x0f45,r,d,b); asm_output3("cmovne %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
#define LD(reg,disp,base) do { \
ALUm(0x8b,reg,disp,base); \
asm_output3("mov %s,%d(%s)",gpn(reg),disp,gpn(base)); } while(0)
--- a/js/src/nanojit/RegAlloc.cpp
+++ b/js/src/nanojit/RegAlloc.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
--- a/js/src/nanojit/RegAlloc.h
+++ b/js/src/nanojit/RegAlloc.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
new file mode 100644
--- /dev/null
+++ b/js/src/nanojit/TraceTreeDrawer.cpp
@@ -0,0 +1,303 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2004-2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include "nanojit.h"
+
+#define verbose_draw_only(x)
+
+namespace nanojit {
+
+#ifdef AVMPLUS_VERBOSE
+ using namespace avmplus;
+
+ TraceTreeDrawer::TraceTreeDrawer(Fragmento *frago, AvmCore *core, AvmString fileName) {
+ this->_frago = frago;
+ this->_core = core;
+ this->_labels = frago->labels;
+ this->_fileName = fileName;
+ }
+
+ TraceTreeDrawer::~TraceTreeDrawer() {
+ }
+
+ void TraceTreeDrawer::addNode(Fragment *fragment, const char *color) {
+ avmplus::String *filep = fragment->file;
+ if (!filep)
+ filep = _core->k_str[avmplus::kstrconst_emptyString];
+ avmplus::StringNullTerminatedUTF8 file(_core->gc, filep);
+ const char *fileName = file.c_str();
+
+ fprintf(_fstream, "<node id=\"%d\">\n"
+ "<data key=\"nodeGraphicsID\">\n"
+ "<y:ShapeNode>\n"
+ "<y:Shape type=\"roundrectangle\"/>\n"
+ "<y:NodeLabel alignment=\"center\">%s"
+ " %s:%d" //filename:line number
+ "</y:NodeLabel>\n"
+ "<y:Fill color=\"#%s\" transparent=\"false\"/>\n"
+ "</y:ShapeNode>\n"
+ "</data>\n"
+ "</node>\n", (int)fragment, _labels->format(fragment), fileName, fragment->line, color);
+ }
+
+ void TraceTreeDrawer::addNode(Fragment *fragment) {
+ if (!fragment->isAnchor())
+ addNode(fragment, "FFCC99"); // standard color
+ else
+ addNode(fragment, "CCFFFF"); // Root node
+ }
+
+ void TraceTreeDrawer::addEdge(Fragment *from, Fragment *to) {
+ this->addNode(from);
+ this->addNode(to);
+
+ // Create the edge
+ fprintf(_fstream, "<edge directed=\"true\" source=\"%d\" target=\"%d\">\n", (int)from, (int)to);
+ drawDirectedEdge();
+ fprintf(_fstream, "</edge>\n");
+ }
+
+ void TraceTreeDrawer::recursiveDraw(Fragment *root) {
+ if (!isCompiled(root)) {
+ return;
+ }
+
+ addBackEdges(root);
+
+ Fragment *lastDrawnBranch = root;
+ for (Fragment *treeBranch = root->branches; treeBranch != 0; treeBranch = treeBranch->nextbranch) {
+ if (!isMergeFragment(treeBranch)) {
+ struct SideExit* exit = treeBranch->spawnedFrom->exit();
+ if (isValidSideExit(exit) && isCompiled(treeBranch)) {
+ verbose_draw_only(printf("Adding edge between %s and %s\n", _labels->format(lastDrawnBranch), _labels->format(treeBranch)));
+
+ this->addEdge(lastDrawnBranch, treeBranch);
+ lastDrawnBranch = treeBranch;
+ }
+
+ recursiveDraw(treeBranch);
+ }
+ else {
+ addMergeNode(treeBranch);
+ } // end ifelse
+ } // end for loop
+ }
+
+ void TraceTreeDrawer::addBackEdges(Fragment *root) {
+ // At the end of a tree, find out where it goes
+ if (isCrossFragment(root)) {
+ verbose_draw_only(printf("Found a cross fragment %s TO %s \n", _labels->format(root), _labels->format(root->eot_target)));
+ this->addEdge(root, root->eot_target);
+ }
+ else if (isBackEdgeSideExit(root)) {
+ verbose_draw_only(printf("Adding anchor branch edge from %s TO %s\n", _labels->format(root), _labels->format(root->anchor)));
+ this->addEdge(root, root->anchor);
+ }
+ else if (isSingleTrace(root)) {
+ verbose_draw_only(printf("Found a single trace %s\n", _labels->format(root)));
+ this->addEdge(root, root);
+ }
+ else if (isSpawnedTrace(root)) {
+ struct SideExit *exit = root->spawnedFrom->exit();
+ if (isValidSideExit(exit) && isCompiled(root)) {
+ verbose_draw_only(printf("Found a spawned side exit from %s that is a spawn and compiled %s\n", _labels->format(root), _labels->format(exit->from)));
+ this->addEdge(root, exit->from);
+ }
+ }
+ else if (hasEndOfTraceFrag(root)) {
+ verbose_draw_only(printf("%s has an EOT to %s\n", _labels->format(root), _labels->format(root->eot_target)));
+ addEdge(root, root->eot_target);
+ }
+ }
+
+ void TraceTreeDrawer::addMergeNode(Fragment *mergeRoot) {
+ verbose_draw_only(printf("Found a merge fragment %s and anchor %s\n", _labels->format(mergeRoot), _labels->format(mergeRoot->anchor)));
+
+ if (hasCompiledBranch(mergeRoot)) {
+ verbose_draw_only(printf("Found a branch to %s\n", _labels->format(mergeRoot->branches)));
+ addEdge(mergeRoot, mergeRoot->branches);
+ recursiveDraw(mergeRoot->branches);
+ }
+
+ if (hasEndOfTraceFrag(mergeRoot)) {
+ verbose_draw_only(printf("Merge with an EOT to %s\n", _labels->format(mergeRoot->eot_target)));
+ addEdge(mergeRoot, mergeRoot->eot_target);
+ }
+ else {
+ verbose_draw_only(printf("Merge to anchor %s\n", _labels->format(mergeRoot->anchor)));
+ addEdge(mergeRoot, mergeRoot->anchor);
+ }
+ }
+
+ void TraceTreeDrawer::draw(Fragment *root) {
+ this->recursiveDraw(root);
+
+ verbose_draw_only(printf("\nFinished drawing, printing status\n"));
+ verbose_draw_only(this->printTreeStatus(root));
+ }
+
+ void TraceTreeDrawer::createGraphHeader() {
+ Stringp graphMLExtension = _core->newString(".graphml");
+ Stringp outputFileName = _core->concatStrings(this->_fileName, graphMLExtension);
+
+ verbose_draw_only(printf("output file name is %s\n", (char *)(outputFileName->getData())));
+ this->_fstream = fopen((char *)outputFileName->getData(), "w");
+
+ fprintf(_fstream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+ "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:y=\"http://www.yworks.com/xml/graphml\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns/graphml http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd\">\n"
+ "<key for=\"node\" id=\"nodeGraphicsID\" yfiles.type=\"nodegraphics\"/>\n"
+ "<key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"nodeDescID\"/>\n"
+ "<key for=\"edge\" id=\"edgeGraphicsID\" yfiles.type=\"edgegraphics\"/>\n"
+ "<key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"edgeDescID\"/>\n"
+ "<graph edgedefault=\"directed\" id=\"rootGraph\">\n");
+
+ }
+
+ void TraceTreeDrawer::createGraphFooter() {
+ fprintf(_fstream, " </graph></graphml>");
+ fclose(this->_fstream);
+ }
+
+ bool TraceTreeDrawer::isValidSideExit(struct SideExit *exit) {
+ return exit != 0;
+ }
+
+ bool TraceTreeDrawer::isCompiled(Fragment *f) {
+ return f->compileNbr != 0;
+ }
+
+ bool TraceTreeDrawer::isLoopFragment(Fragment *f) {
+ return f->kind == LoopTrace;
+ }
+
+ bool TraceTreeDrawer::isCrossFragment(Fragment *f) {
+ return f->kind == BranchTrace;
+ }
+
+ bool TraceTreeDrawer::isMergeFragment(Fragment *f) {
+ return f->kind == MergeTrace;
+ }
+
+ bool TraceTreeDrawer::isSingleTrace(Fragment *f) {
+ return f->isAnchor() && !hasCompiledBranch(f);
+ }
+
+ bool TraceTreeDrawer::hasCompiledBranch(Fragment *f) {
+ for (Fragment *current = f->branches; current != 0; current = current->nextbranch) {
+ if (isCompiled(current)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool TraceTreeDrawer::isSpawnedTrace(Fragment *f) {
+ return f->spawnedFrom != 0;
+ }
+
+ bool TraceTreeDrawer::isBackEdgeSideExit(Fragment *f) {
+ return !f->branches && !f->isAnchor();
+ }
+
+ bool TraceTreeDrawer::hasEndOfTraceFrag(Fragment *f) {
+ return (f->eot_target) && (f != f->eot_target);
+ }
+
+ void TraceTreeDrawer::drawDirectedEdge() {
+ // Make it directed
+ fprintf(_fstream, "<data key=\"edgeGraphicsID\">\n"
+ "<y:PolyLineEdge>\n"
+ "<y:Arrows source=\"none\" target=\"standard\"/>\n"
+ "</y:PolyLineEdge>\n"
+ "</data>\n");
+ }
+
+ void TraceTreeDrawer::printTreeStatus(Fragment *root) {
+ if (!isCompiled(root)) {
+ return;
+ }
+
+ printf("\nRoot is %s\n", _labels->format(root));
+ if (root->spawnedFrom) {
+ struct SideExit *exit = root->spawnedFrom->exit();
+ if (exit && root->compileNbr) {
+ printf("Found a root that is a spawn and compiled %s\n", _labels->format(exit->from));
+ }
+ }
+
+ for (Fragment *x = root->branches; x != 0; x = x->nextbranch) {
+ if (x->kind != MergeTrace) {
+ struct SideExit* exit = x->spawnedFrom->exit();
+ if (exit && x->compileNbr) {
+ printf("Found one with an SID and compiled %s\n", _labels->format(x));
+ }
+
+ printTreeStatus(x);
+ }
+ }
+ printf("\n");
+ }
+#endif
+}
+
+
+void drawTraceTrees(nanojit::Fragmento *frago, nanojit::FragmentMap * _frags, avmplus::AvmCore *core, avmplus::AvmString fileName) {
+#ifdef AVMPLUS_VERBOSE
+ nanojit::TraceTreeDrawer *traceDrawer = new (core->gc) nanojit::TraceTreeDrawer(frago, core, fileName);
+ traceDrawer->createGraphHeader();
+
+ int32_t count = _frags->size();
+ for (int32_t i=0; i<count; i++)
+ {
+ Fragment *frag = _frags->at(i);
+ // Count only fragments which have something compiled. Needs the -Dverbose flag
+ if (frag->compileNbr) {
+ traceDrawer->draw(frag);
+ }
+ }
+
+ traceDrawer->createGraphFooter();
+#else
+ (void)frago;
+ (void)_frags;
+ (void)core;
+ (void)fileName;
+#endif
+}
+
new file mode 100644
--- /dev/null
+++ b/js/src/nanojit/TraceTreeDrawer.h
@@ -0,0 +1,88 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2004-2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nanojit_TraceTreeDrawer__
+#define __nanojit_TraceTreeDrawer__
+#include <stdio.h>
+
+namespace nanojit {
+#ifdef AVMPLUS_VERBOSE
+ using namespace avmplus;
+
+ class TraceTreeDrawer : public GCFinalizedObject {
+ public:
+ TraceTreeDrawer(Fragmento *frago, AvmCore *core, AvmString fileName);
+ ~TraceTreeDrawer();
+
+ void createGraphHeader();
+ void createGraphFooter();
+
+ void addEdge(Fragment *from, Fragment *to);
+ void addNode(Fragment *fragment);
+ void addNode(Fragment *fragment, const char *color);
+
+ void draw(Fragment *rootFragment);
+ void recursiveDraw(Fragment *root);
+
+ private:
+ FILE* _fstream;
+ DWB(AvmCore *) _core;
+ DWB(Fragmento *) _frago;
+ DWB(LabelMap *) _labels;
+ AvmString _fileName;
+
+ void addBackEdges(Fragment *f);
+ void addMergeNode(Fragment *f);
+
+ bool isValidSideExit(struct SideExit *exit);
+ bool isCompiled(Fragment *f);
+ bool isLoopFragment(Fragment *f);
+ bool isCrossFragment(Fragment *f);
+ bool isMergeFragment(Fragment *f);
+ bool isSingleTrace(Fragment *f);
+ bool isSpawnedTrace(Fragment *f);
+ bool isBackEdgeSideExit(Fragment *f);
+ bool hasEndOfTraceFrag(Fragment *f);
+ bool hasCompiledBranch(Fragment *f);
+
+ void printTreeStatus(Fragment *root);
+ void drawDirectedEdge();
+ };
+#endif
+}
+
+#endif /*TRACETREEDRAWER_H_*/
--- a/js/src/nanojit/avmplus.h
+++ b/js/src/nanojit/avmplus.h
@@ -145,16 +145,18 @@ namespace avmplus
void* rp;
void* f;
};
class String
{
};
+ typedef class String AvmString;
+
class StringNullTerminatedUTF8
{
const char* cstr;
public:
StringNullTerminatedUTF8(GC* gc, String* s)
{
cstr = strdup((const char*)s);
--- a/js/src/nanojit/nanojit.h
+++ b/js/src/nanojit/nanojit.h
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
@@ -42,16 +43,19 @@
#include "avmplus.h"
#ifdef AVMPLUS_IA32
#define NANOJIT_IA32
#elif AVMPLUS_ARM
#define NANOJIT_ARM
#elif AVMPLUS_PPC
#define NANOJIT_PPC
+#elif AVMPLUS_AMD64
+#define NANOJIT_AMD64
+#define NANOJIT_64BIT
#else
#error "unknown nanojit architecture"
#endif
namespace nanojit
{
/**
* -------------------------------------------
@@ -156,10 +160,11 @@ namespace nanojit
#define pageBottom(x) ( (int*)(alignTo(x,NJ_PAGE_SIZE)+NJ_PAGE_SIZE)-1 )
#define samepage(x,y) (pageTop(x) == pageTop(y))
#include "Native.h"
#include "LIR.h"
#include "RegAlloc.h"
#include "Fragmento.h"
#include "Assembler.h"
+#include "TraceTreeDrawer.h"
#endif // __nanojit_h_