Sync with TT-tip.
authorAndreas Gal <gal@uci.edu>
Mon, 30 Jun 2008 15:33:41 -0700
changeset 17368 4261e41eccc8010be4afc1d1cba2aa6be0d9ba31
parent 17367 a53a1fc6054cead81ab777e60e28b7eb8d5e8711
child 17369 3dcda8cce1d7913534236f9496e44bf38179a013
push id1452
push usershaver@mozilla.com
push dateFri, 22 Aug 2008 00:08:22 +0000
treeherdermozilla-central@d13bb0868596 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a1pre
Sync with TT-tip.
js/src/Makefile.ref
js/src/nanojit/Assembler.cpp
js/src/nanojit/Assembler.h
js/src/nanojit/Fragmento.cpp
js/src/nanojit/Fragmento.h
js/src/nanojit/LIR.cpp
js/src/nanojit/LIR.h
js/src/nanojit/Native.h
js/src/nanojit/NativeARM.h
js/src/nanojit/NativeThumb.h
js/src/nanojit/Nativei386.cpp
js/src/nanojit/Nativei386.h
js/src/nanojit/RegAlloc.cpp
js/src/nanojit/RegAlloc.h
js/src/nanojit/TraceTreeDrawer.cpp
js/src/nanojit/TraceTreeDrawer.h
js/src/nanojit/avmplus.h
js/src/nanojit/nanojit.h
--- 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_