From debb2cc333a8f8f0c0af360a28033794711a08ec Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Wed, 18 Jun 2008 21:23:53 -0700 Subject: [PATCH] Added RegAlloc.h and Fragmento.h from TT. --- js/src/nanojit/Fragmento.h | 238 +++++++++++++++++++++++++++++++++++++ js/src/nanojit/RegAlloc.h | 79 ++++++++++++ js/src/nanojit/avmplus.h | 41 ++++--- js/src/nanojit/nanojit.h | 4 +- 4 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 js/src/nanojit/Fragmento.h create mode 100644 js/src/nanojit/RegAlloc.h diff --git a/js/src/nanojit/Fragmento.h b/js/src/nanojit/Fragmento.h new file mode 100644 index 00000000000..4d23e06a112 --- /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 AllocList; + + typedef avmplus::SortedMap 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__ diff --git a/js/src/nanojit/RegAlloc.h b/js/src/nanojit/RegAlloc.h new file mode 100644 index 00000000000..967af740337 --- /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__ diff --git a/js/src/nanojit/avmplus.h b/js/src/nanojit/avmplus.h index e075452c0f7..69ed644d2cf 100644 --- a/js/src/nanojit/avmplus.h +++ b/js/src/nanojit/avmplus.h @@ -56,6 +56,10 @@ class GC { }; +class GCHeap +{ +}; + class GCObject { }; @@ -68,6 +72,10 @@ class GCFinalizedObject namespace avmplus { + class InterpState + { + }; + class AvmCore { }; @@ -121,7 +129,7 @@ namespace avmplus uint32_t FASTCALL add(T value) { - if (len >= capacity()) { + if (len >= capacity) { grow(); } wb(len++, value); @@ -138,25 +146,20 @@ namespace avmplus 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); } @@ -199,20 +202,21 @@ namespace avmplus 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; } } @@ -241,7 +245,7 @@ namespace avmplus { // 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) @@ -259,14 +263,14 @@ namespace avmplus 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: @@ -284,8 +288,8 @@ namespace avmplus // 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; @@ -324,6 +328,7 @@ namespace avmplus private: T* data; uint32_t len; + uint32_t capacity; // ------------------------ DATA SECTION END }; diff --git a/js/src/nanojit/nanojit.h b/js/src/nanojit/nanojit.h index 65092cee0c5..63d63b3fa3e 100644 --- a/js/src/nanojit/nanojit.h +++ b/js/src/nanojit/nanojit.h @@ -159,8 +159,8 @@ namespace nanojit #include "Native.h" #include "LIR.h" -/*#include "RegAlloc.h" +#include "RegAlloc.h" #include "Fragmento.h" -#include "Assembler.h"*/ +/*#include "Assembler.h"*/ #endif // __nanojit_h_