Added RegAlloc.h and Fragmento.h from TT.
authorAndreas Gal <gal@uci.edu>
Wed, 18 Jun 2008 21:23:53 -0700
changeset 17273 703852bb249938b172156a13c9950670881b5c87
parent 17272 822efff560ea9b6c84a035030547edb0c4e7c56b
child 17274 af2c8cea077ab73bdb895a5f302001e9fd7262d9
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
Added RegAlloc.h and Fragmento.h from TT.
js/src/nanojit/Fragmento.h
js/src/nanojit/RegAlloc.h
js/src/nanojit/avmplus.h
js/src/nanojit/nanojit.h
new file mode 100644
--- /dev/null
+++ b/js/src/nanojit/Fragmento.h
@@ -0,0 +1,238 @@
+/* ***** 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_Fragmento__
+#define __nanojit_Fragmento__
+
+
+
+namespace nanojit
+{
+	struct GuardRecord;
+	class Assembler;
+	
+    struct PageHeader
+    {
+        struct Page *next;
+        verbose_only (int seq;) // sequence # of page
+    };
+    struct Page: public PageHeader
+    {
+        union {
+            LIns lir[(NJ_PAGE_SIZE-sizeof(PageHeader))/sizeof(LIns)];
+            NIns code[(NJ_PAGE_SIZE-sizeof(PageHeader))/sizeof(NIns)];
+        };
+    };
+	typedef avmplus::List<Page*,avmplus::LIST_NonGCObjects>	AllocList;
+
+	typedef avmplus::SortedMap<const void*, uint32_t, avmplus::LIST_NonGCObjects> BlockSortedMap;
+	class BlockHist: public BlockSortedMap
+	{
+	public:
+		BlockHist(GC*gc): BlockSortedMap(gc)
+		{
+		}
+		uint32_t count(const void *p) {
+			uint32_t c = 1+get(p);
+			put(p, c);
+			return c;
+		}
+	};
+
+	/*
+	 *
+	 * This is the main control center for creating and managing fragments.
+	 */
+	class Fragmento : public GCFinalizedObject
+	{
+		public:
+			Fragmento(AvmCore* core);
+			~Fragmento();
+
+			void		addMemory(void* firstPage, uint32_t pageCount);  // gives memory to the Assembler
+			Assembler*	assm();
+			AvmCore*	core();
+			Page*		pageAlloc();
+			void		pageFree(Page* page);
+			
+            Fragment*	getLoop(const avmplus::InterpState &is);
+			void		clearFrags();	// clear all fragments from the cache
+            Fragment*	getMerge(GuardRecord *lr, const avmplus::InterpState &is);
+            Fragment*   createBranch(GuardRecord *lr, const avmplus::InterpState &is);
+            Fragment*   newFrag(const avmplus::InterpState &is);
+            Fragment*   newBranch(Fragment *from, const avmplus::InterpState &is);
+
+            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	ilsize, abcsize, compiles, freePages;
+			}
+			_stats;
+
+			verbose_only( DWB(BlockHist*)		enterCounts; )
+			verbose_only( DWB(BlockHist*)		mergeCounts; )
+			verbose_only( DWB(LabelMap*)        labels; )
+
+		private:
+			void		pagesGrow(int32_t count);
+
+			AvmCore*			_core;
+			DWB(Assembler*)		_assm;
+			DWB(FragmentMap*)	_frags;		/* map from ip -> Fragment ptr  */
+			Page*			_pageList;
+
+			/* unmanaged mem */
+			AllocList			_allocList;
+			GCHeap*		_gcHeap;
+			
+			verbose_only( uint32_t _flushes; )
+	};
+
+    struct SideExit
+    {
+		int32_t f_adj;
+        int32_t ip_adj;
+		int32_t sp_adj;
+		int32_t rp_adj;
+		Fragment *from;
+        Fragment *target;
+		int32_t calldepth;
+		LInsp	ins;
+		verbose_only( uint32_t sid; )
+    };
+
+	enum TraceKind {
+		LoopTrace,
+		BranchTrace,
+		MergeTrace
+	};
+	
+	/**
+	 * Fragments are linear sequences of native code that have a single entry 
+	 * point at the start of the fragment and may have one or more exit points 
+	 * 
+	 * It may turn out that that this arrangement causes too much traffic
+	 * between d and i-caches and that we need to carve up the structure differently.
+	 */
+	class Fragment
+	{
+		public:
+			Fragment(FragID);
+
+			NIns*			code()							{ return _code; }
+			void			setCode(NIns* codee)			{ _code = codee; }
+			GuardRecord*	links()							{ return _links; }
+			int32_t&		hits()							{ return _hits; }
+            void            blacklist();
+			bool			isBlacklisted()		{ return _hits < 0; }
+			void			resetLinks();
+			void			addLink(GuardRecord* lnk);
+			void			removeLink(GuardRecord* lnk);
+			void			link(Assembler* assm);
+			void			linkBranches(Assembler* assm);
+			void			unlink(Assembler* assm);
+			void			unlinkBranches(Assembler* assm);
+			bool			hasOnlyTreeLinks();
+			void			removeIntraLinks();
+            void            removeExit(Fragment *target);
+            void            clear();
+			bool			isAnchor() { return anchor == this; }
+			
+			verbose_only( uint32_t		_called; )
+			verbose_only( uint32_t		_native; )
+            verbose_only( uint32_t      _exitNative; )
+			verbose_only( uint32_t		_lir; )
+			verbose_only( const char*	_token; )
+            verbose_only( uint64_t      traceTicks; )
+            verbose_only( uint64_t      interpTicks; )
+            verbose_only( int32_t line; )
+            verbose_only( DRCWB(avmplus::String *)file; )
+			verbose_only( DWB(Fragment*) eot_target; )
+			verbose_only( uint32_t mergeid;)
+			verbose_only( uint32_t		sid;)
+			verbose_only( uint32_t		compileNbr;)
+
+            DWB(Fragment*) treeBranches;
+            DWB(Fragment*) branches;
+            DWB(Fragment*) nextbranch;
+            DWB(Fragment*) anchor;
+			DWB(BlockHist*) mergeCounts;
+            DWB(LirBuffer*) lirbuf;
+			LIns*			lastIns;
+			SideExit*		spawnedFrom;
+			GuardRecord*	outbound;
+			
+			TraceKind kind;
+			const FragID frid;
+			uint32_t guardCount;
+            uint32_t xjumpCount;
+            int32_t blacklistLevel;
+            NIns* fragEntry;
+            LInsp param0,param1,sp,rp;
+			int32_t calldepth;
+			
+		private:
+			NIns*			_code;		// ptr to start of code
+			GuardRecord*	_links;		// code which is linked (or pending to be) to this fragment
+			int32_t			_hits;
+	};
+	
+#ifdef NJ_VERBOSE
+	inline int nbr(LInsp x) 
+	{
+        Page *p = x->page();
+        return (p->seq * NJ_PAGE_SIZE + (intptr_t(x)-intptr_t(p))) / sizeof(LIns);
+	}
+#else
+    inline int nbr(LInsp x)
+    {
+        return int(x) & (NJ_PAGE_SIZE-1);
+    }
+#endif
+}
+#endif // __nanojit_Fragmento__
new file mode 100644
--- /dev/null
+++ b/js/src/nanojit/RegAlloc.h
@@ -0,0 +1,79 @@
+/* ***** 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_RegAlloc__
+#define __nanojit_RegAlloc__
+
+
+namespace nanojit
+{
+	inline RegisterMask rmask(Register r)
+	{
+		return 1 << r;
+	}
+
+	class RegAlloc
+	{
+		public:
+			RegAlloc() {}
+			void	clear();
+			bool	isFree(Register r); 
+			void	addFree(Register r);
+			void	removeFree(Register r);
+			void	addActive(Register r, LIns* ins);
+			void	removeActive(Register r);
+			LIns*	getActive(Register r); 
+			void	retire(Register r);
+
+			debug_only( uint32_t	countFree(); )
+			debug_only( uint32_t	countActive(); )
+			debug_only( void		checkCount(); )
+			debug_only( bool		isConsistent(Register r, LIns* v); )
+			debug_only( uint32_t	count; )
+			debug_only( RegisterMask managed; )    // bitfield of 0..NJ_MAX_REGISTERS denoting which are under our management                     
+
+			LIns*	active[NJ_MAX_REGISTERS];  // active[r] = OP that defines r
+			RegisterMask	free;
+			RegisterMask	used;
+
+			verbose_only( static void formatRegisters(RegAlloc& regs, char* s, LirNameMap*); )
+
+			DECLARE_PLATFORM_REGALLOC()
+	};
+}
+#endif // __nanojit_RegAlloc__
--- a/js/src/nanojit/avmplus.h
+++ b/js/src/nanojit/avmplus.h
@@ -51,28 +51,36 @@ typedef JSUint8 uint8_t;
 typedef JSUint16 uint16_t;
 typedef JSUint32 uint32_t;
 typedef JSUint64 uint64_t;
 
 class GC 
 {
 };
 
+class GCHeap
+{
+};
+
 class GCObject 
 {
 };
 
 class GCFinalizedObject
 {
 };
 
 #define DWB(x) x
 
 namespace avmplus
 {
+    class InterpState
+    {
+    };
+
     class AvmCore 
     {
     };
     
     class OSDep
     {
     };
     
@@ -116,52 +124,47 @@ namespace avmplus
         inline void destroy()
         {
             if (data)
                 delete data;
         }
         
         uint32_t FASTCALL add(T value)
         {
-            if (len >= capacity()) {
+            if (len >= capacity) {
                 grow();
             }
             wb(len++, value);
             return len-1;
         }
         
         inline bool isEmpty() const
         {
             return len == 0;
         }
         
         inline uint32_t size() const
         {
             return len;
         }
         
-        inline uint32_t capacity() const
-        {
-            return data ? lot_size(data) / sizeof(T) : 0;
-        }
-        
         inline T get(uint32_t index) const
         {
             AvmAssert(index < len);
-            return *(T*)lot_get(data, factor(index));
+            return *(T*)(data + index);
         }
         
         void FASTCALL set(uint32_t index, T value)
         {
-            AvmAssert(index < capacity());
+            AvmAssert(index < capacity);
             if (index >= len)
             {
                 len = index+1;
             }
-            AvmAssert(len <= capacity());
+            AvmAssert(len <= capacity);
             wb(index, value);
         }
         
         inline void clear()
         {
             zero_range(0, len);
             len = 0;
         }
@@ -194,30 +197,31 @@ namespace avmplus
             T t = get(len-1);
             set(len-1, undef_list_val());
             len--;
             return t;
         }
     
         inline T operator[](uint32_t index) const
         {
-            AvmAssert(index < capacity());
+            AvmAssert(index < capacity);
             return get(index);
         }
         
         void FASTCALL ensureCapacity(uint32_t cap)
         {           
-            if (cap > capacity()) {
+            if (cap > capacity) {
                 if (data == NULL) {
                     data = new T[cap];
                     zero_range(0, cap);
                 } else {
                     data = (T*)realloc(data, factor(cap));
-                    zero_range(capacity(), cap - capacity());
+                    zero_range(capacity, cap - capacity);
                 }
+                capacity = cap;
             }
         }
         
         void FASTCALL insert(uint32_t index, T value, uint32_t count = 1)
         {
             AvmAssert(index <= len);
             AvmAssert(count > 0);
             ensureCapacity(len+count);
@@ -236,17 +240,17 @@ namespace avmplus
             return old;
         }
     
     private:
         void FASTCALL grow()
         {
             // growth is fast at first, then slows at larger list sizes.
             uint32_t newMax = 0;
-            const uint32_t curMax = capacity();
+            const uint32_t curMax = capacity;
             if (curMax == 0)
                 newMax = kInitialCapacity;
             else if(curMax > 15)
                 newMax = curMax * 3/2;
             else
                 newMax = curMax * 2;
         
             ensureCapacity(newMax);
@@ -254,24 +258,24 @@ namespace avmplus
         
         inline void do_wb_nongc(void* /*container*/, T* slot, T value)
         {   
             *slot = value;
         }
 
         inline void do_wb_gc(void* container, GCObject** slot, const GCObject** value)
         {   
-            *slot = *value;
+            *slot = (GCObject*)*value;
         }
 
         void FASTCALL wb(uint32_t index, T value)
         {   
-            AvmAssert(index < capacity());
+            AvmAssert(index < capacity);
             AvmAssert(data != NULL);
-            T* slot = data[index];
+            T* slot = &data[index];
             switch(kElementType)
             {
                 case LIST_NonGCObjects:
                     do_wb_nongc(0, slot, value);
                     break;
                 case LIST_GCObjects:
                     do_wb_gc(0, (GCObject**)slot, (const GCObject**)&value);
                     break;
@@ -279,18 +283,18 @@ namespace avmplus
         }
 
         // multiple wb call with the same value, and assumption that existing value is all zero bits,
         // like
         //  for (uint32_t u = index; u < index_end; ++u)
         //      wb(u, value);
         void FASTCALL wbzm(uint32_t index, uint32_t index_end, T value)
         {   
-            AvmAssert(index < capacity());
-            AvmAssert(index_end <= capacity());
+            AvmAssert(index < capacity);
+            AvmAssert(index_end <= capacity);
             AvmAssert(index < index_end);
             AvmAssert(data != NULL);
             void *container;
             T* slot = data + index;
             switch(kElementType)
             {
                 case LIST_NonGCObjects:
                     for (  ; index < index_end; ++index, ++slot)
@@ -319,16 +323,17 @@ namespace avmplus
     private:
         List(const List& toCopy);           // unimplemented
         void operator=(const List& that);   // unimplemented
 
     // ------------------------ DATA SECTION BEGIN
     private:
         T* data;
         uint32_t len;
+        uint32_t capacity;
     // ------------------------ DATA SECTION END
 
     };
 
     // stuff that needs specialization based on the type
     template<typename T, ListElementType kElementType> 
     /* static */ inline T List<T, kElementType>::undef_list_val() { return T(0); }
 
--- a/js/src/nanojit/nanojit.h
+++ b/js/src/nanojit/nanojit.h
@@ -154,13 +154,13 @@ namespace nanojit
 #define alignUp(x,s)		((((uint32_t)(x))+((s)-1))&~((s)-1))
 
 #define pageTop(x)			( (int*)alignTo(x,NJ_PAGE_SIZE) )
 #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 "RegAlloc.h"
 #include "Fragmento.h"
-#include "Assembler.h"*/
+/*#include "Assembler.h"*/
 
 #endif // __nanojit_h_