├── .gitignore ├── Assembler.cpp ├── Assembler.h ├── Fragmento.cpp ├── Fragmento.h ├── LICENSE ├── LIR.cpp ├── LIR.h ├── LIRopcode.tbl ├── Native.h ├── NativeARM.cpp ├── NativeARM.h ├── NativeSparc.cpp ├── NativeSparc.h ├── NativeThumb.cpp ├── NativeThumb.h ├── Nativei386.cpp ├── Nativei386.h ├── README ├── RegAlloc.cpp ├── RegAlloc.h ├── TraceTreeDrawer.cpp ├── TraceTreeDrawer.h ├── avmplus.cpp ├── avmplus.h ├── example ├── example.cpp └── makefile ├── js-config.h ├── jsapi.h ├── jsautocfg.h ├── jsinttypes.h ├── jsotypes.h ├── jsstdint.h ├── jstypes.h ├── makefile ├── mozilla-config.h ├── nanojit.h └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *~ 3 | *.txt 4 | example 5 | *.a 6 | -------------------------------------------------------------------------------- /Assembler.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | 40 | #ifndef __nanojit_Assembler__ 41 | #define __nanojit_Assembler__ 42 | 43 | 44 | namespace nanojit 45 | { 46 | /** 47 | * Some notes on this Assembler (Emitter). 48 | * 49 | * The class RegAlloc is essentially the register allocator from MIR 50 | * 51 | * The Assembler class parses the LIR instructions starting at any point and converts 52 | * them to machine code. It does the translation using expression trees which are simply 53 | * LIR instructions in the stream that have side-effects. Any other instruction in the 54 | * stream is simply ignored. 55 | * This approach is interesting in that dead code elimination occurs for 'free', strength 56 | * reduction occurs fairly naturally, along with some other optimizations. 57 | * 58 | * A negative is that we require state as we 'push' and 'pop' nodes along the tree. 59 | * Also, this is most easily performed using recursion which may not be desirable in 60 | * the mobile environment. 61 | * 62 | */ 63 | 64 | #define STACK_GRANULARITY sizeof(void *) 65 | 66 | struct AR 67 | { 68 | LIns* entry[ NJ_MAX_STACK_ENTRY ]; /* maps to 4B contiguous locations relative to the frame pointer */ 69 | uint32_t tos; /* current top of stack entry */ 70 | uint32_t highwatermark; /* max tos hit */ 71 | uint32_t lowwatermark; /* we pre-allocate entries from 0 upto this index-1; so dynamic entries are added above this index */ 72 | }; 73 | 74 | #ifdef AVMPLUS_WIN32 75 | #define AVMPLUS_ALIGN16(type) __declspec(align(16)) type 76 | #else 77 | #define AVMPLUS_ALIGN16(type) type __attribute__ ((aligned (16))) 78 | #endif 79 | 80 | struct Stats 81 | { 82 | counter_define(steals;) 83 | counter_define(remats;) 84 | counter_define(spills;) 85 | counter_define(native;) 86 | counter_define(exitnative;) 87 | 88 | int32_t pages; 89 | NIns* codeStart; 90 | NIns* codeExitStart; 91 | 92 | DECLARE_PLATFORM_STATS() 93 | #ifdef __GNUC__ 94 | // inexplicably, gnuc gives padding/alignment warnings without this. pacify it. 95 | bool pad[4]; 96 | #endif 97 | }; 98 | 99 | class Fragmento; 100 | 101 | // error codes 102 | enum AssmError 103 | { 104 | None = 0 105 | ,OutOMem 106 | ,StackFull 107 | ,RegionFull 108 | ,MaxLength 109 | ,MaxExit 110 | ,MaxXJump 111 | ,UnknownPrim 112 | ,UnknownBranch 113 | }; 114 | 115 | typedef avmplus::List NInsList; 116 | typedef avmplus::SortedMap InsMap; 117 | typedef avmplus::SortedMap NInsMap; 118 | 119 | class LabelState MMGC_SUBCLASS_DECL 120 | { 121 | public: 122 | RegAlloc regs; 123 | NIns *addr; 124 | LabelState(NIns *a, RegAlloc &r) : regs(r), addr(a) 125 | {} 126 | }; 127 | 128 | class LabelStateMap 129 | { 130 | avmplus::GC *gc; 131 | avmplus::SortedMap labels; 132 | public: 133 | LabelStateMap(avmplus::GC *gc) : gc(gc), labels(gc) 134 | {} 135 | ~LabelStateMap(); 136 | 137 | void clear(); 138 | void add(LIns *label, NIns *addr, RegAlloc ®s); 139 | LabelState *get(LIns *); 140 | }; 141 | /** 142 | * Information about the activation record for the method is built up 143 | * as we generate machine code. As part of the prologue, we issue 144 | * a stack adjustment instruction and then later patch the adjustment 145 | * value. Temporary values can be placed into the AR as method calls 146 | * are issued. Also MIR_alloc instructions will consume space. 147 | */ 148 | class Assembler MMGC_SUBCLASS_DECL 149 | { 150 | friend class VerboseBlockReader; 151 | public: 152 | #ifdef NJ_VERBOSE 153 | static char outline[8192]; 154 | static char outlineEOL[512]; // string to be added to the end of the line 155 | static char* outputAlign(char* s, int col); 156 | 157 | void FASTCALL outputForEOL(const char* format, ...); 158 | void FASTCALL output(const char* s); 159 | void FASTCALL outputf(const char* format, ...); 160 | void FASTCALL output_asm(const char* s); 161 | 162 | bool _verbose, outputAddr, vpad[2]; // if outputAddr=true then next asm instr. will include address in output 163 | void printActivationState(); 164 | 165 | StringList* _outputCache; 166 | #endif 167 | 168 | Assembler(Fragmento* frago); 169 | ~Assembler() {} 170 | 171 | void assemble(Fragment* frag, NInsList& loopJumps); 172 | void endAssembly(Fragment* frag, NInsList& loopJumps); 173 | void beginAssembly(Fragment *frag, RegAllocMap* map); 174 | void copyRegisters(RegAlloc* copyTo); 175 | void releaseRegisters(); 176 | void patch(GuardRecord *lr); 177 | void patch(SideExit *exit); 178 | #ifdef NANOJIT_IA32 179 | void patch(SideExit* exit, SwitchInfo* si); 180 | #endif 181 | AssmError error() { return _err; } 182 | void setError(AssmError e) { _err = e; } 183 | void setCallTable(const CallInfo *functions); 184 | void pageReset(); 185 | int32_t codeBytes(); 186 | Page* handoverPages(bool exitPages=false); 187 | 188 | debug_only ( void pageValidate(); ) 189 | debug_only ( bool onPage(NIns* where, bool exitPages=false); ) 190 | 191 | // support calling out from a fragment ; used to debug the jit 192 | debug_only( void resourceConsistencyCheck(); ) 193 | debug_only( void registerConsistencyCheck(); ) 194 | 195 | Stats _stats; 196 | int hasLoop; 197 | 198 | private: 199 | 200 | void gen(LirFilter* toCompile, NInsList& loopJumps); 201 | NIns* genPrologue(); 202 | NIns* genEpilogue(); 203 | 204 | uint32_t arReserve(LIns* l); 205 | void arFree(uint32_t idx); 206 | void arReset(); 207 | 208 | Register registerAlloc(RegisterMask allow); 209 | void registerResetAll(); 210 | void evictRegs(RegisterMask regs); 211 | void evictScratchRegs(); 212 | void intersectRegisterState(RegAlloc& saved); 213 | void unionRegisterState(RegAlloc& saved); 214 | void assignSaved(RegAlloc &saved, RegisterMask skip); 215 | LInsp findVictim(RegAlloc& regs, RegisterMask allow); 216 | 217 | Register getBaseReg(LIns *i, int &d, RegisterMask allow); 218 | int findMemFor(LIns* i); 219 | Register findRegFor(LIns* i, RegisterMask allow); 220 | void findRegFor2(RegisterMask allow, LIns* ia, Reservation* &ra, LIns *ib, Reservation* &rb); 221 | Register findSpecificRegFor(LIns* i, Register w); 222 | Register prepResultReg(LIns *i, RegisterMask allow); 223 | void freeRsrcOf(LIns *i, bool pop); 224 | void evict(Register r); 225 | RegisterMask hint(LIns*i, RegisterMask allow); 226 | 227 | void resetInstructionPointer(); 228 | void recordStartingInstructionPointer(); 229 | 230 | NIns* pageAlloc(bool exitPage=false); 231 | void pagesFree(Page*& list); 232 | void internalReset(); 233 | bool canRemat(LIns*); 234 | 235 | Reservation* getresv(LIns *x) { 236 | Reservation* r = x->resv(); 237 | return r->used ? r : 0; 238 | } 239 | 240 | DWB(Fragmento*) _frago; 241 | avmplus::GC* _gc; 242 | DWB(Fragment*) _thisfrag; 243 | RegAllocMap* _branchStateMap; 244 | 245 | NIns* _nIns; // current native instruction 246 | NIns* _nExitIns; // current instruction in exit fragment page 247 | NIns* _startingIns; // starting location of code compilation for error handling 248 | NIns* _epilogue; 249 | Page* _nativePages; // list of NJ_PAGE_SIZE pages that have been alloc'd 250 | Page* _nativeExitPages; // list of pages that have been allocated for exit code 251 | AssmError _err; // 0 = means assemble() appears ok, otherwise it failed 252 | 253 | AR _activation; 254 | RegAlloc _allocator; 255 | 256 | LabelStateMap _labels; 257 | NInsMap _patches; 258 | bool _inExit, vpad2[3]; 259 | InsList pending_lives; 260 | 261 | void asm_cmp(LIns *cond); 262 | void asm_fcmp(LIns *cond); 263 | void asm_setcc(Register res, LIns *cond); 264 | NIns * asm_jmpcc(bool brOnFalse, LIns *cond, NIns *target); 265 | void asm_mmq(Register rd, int dd, Register rs, int ds); 266 | NIns* asm_exit(LInsp guard); 267 | NIns* asm_leave_trace(LInsp guard); 268 | void asm_qjoin(LIns *ins); 269 | void asm_store32(LIns *val, int d, LIns *base); 270 | void asm_store64(LIns *val, int d, LIns *base); 271 | void asm_restore(LInsp, Reservation*, Register); 272 | void asm_load(int d, Register r); 273 | void asm_spilli(LInsp i, Reservation *resv, bool pop); 274 | void asm_spill(Register rr, int d, bool pop, bool quad); 275 | void asm_load64(LInsp i); 276 | void asm_pusharg(LInsp p); 277 | void asm_quad(LInsp i); 278 | void asm_loop(LInsp i, NInsList& loopJumps); 279 | void asm_fcond(LInsp i); 280 | void asm_cond(LInsp i); 281 | void asm_arith(LInsp i); 282 | void asm_neg_not(LInsp i); 283 | void asm_ld(LInsp i); 284 | void asm_cmov(LInsp i); 285 | void asm_param(LInsp i); 286 | void asm_int(LInsp i); 287 | void asm_short(LInsp i); 288 | void asm_qlo(LInsp i); 289 | void asm_qhi(LInsp i); 290 | void asm_fneg(LInsp ins); 291 | void asm_fop(LInsp ins); 292 | void asm_i2f(LInsp ins); 293 | void asm_u2f(LInsp ins); 294 | Register asm_prep_fcall(Reservation *rR, LInsp ins); 295 | void asm_nongp_copy(Register r, Register s); 296 | void asm_call(LInsp); 297 | void asm_arg(ArgSize, LInsp, Register); 298 | Register asm_binop_rhs_reg(LInsp ins); 299 | NIns* asm_branch(bool branchOnFalse, LInsp cond, NIns* targ, bool isfar); 300 | void asm_switch(LIns* ins, NIns* target); 301 | void emitJumpTable(SwitchInfo* si, NIns* target); 302 | void assignSavedRegs(); 303 | void reserveSavedRegs(); 304 | void assignParamRegs(); 305 | void handleLoopCarriedExprs(); 306 | 307 | // flag values for nMarkExecute 308 | enum 309 | { 310 | PAGE_READ = 0x0, // here only for clarity: all permissions include READ 311 | PAGE_WRITE = 0x01, 312 | PAGE_EXEC = 0x02 313 | }; 314 | 315 | // platform specific implementation (see NativeXXX.cpp file) 316 | void nInit(AvmCore *); 317 | Register nRegisterAllocFromSet(int32_t set); 318 | void nRegisterResetAll(RegAlloc& a); 319 | void nMarkExecute(Page* page, int flags); 320 | NIns* nPatchBranch(NIns* branch, NIns* location); 321 | void nFragExit(LIns* guard); 322 | 323 | // platform specific methods 324 | public: 325 | const static Register savedRegs[NumSavedRegs]; 326 | DECLARE_PLATFORM_ASSEMBLER() 327 | 328 | private: 329 | debug_only( int32_t _fpuStkDepth; ) 330 | debug_only( int32_t _sv_fpuStkDepth; ) 331 | 332 | // since we generate backwards the depth is negative 333 | inline void fpu_push() { 334 | debug_only( ++_fpuStkDepth; /*char foo[8]= "FPUSTK0"; foo[6]-=_fpuStkDepth; output_asm(foo);*/ NanoAssert(_fpuStkDepth<=0); ) 335 | } 336 | inline void fpu_pop() { 337 | debug_only( --_fpuStkDepth; /*char foo[8]= "FPUSTK0"; foo[6]-=_fpuStkDepth; output_asm(foo);*/ NanoAssert(_fpuStkDepth<=0); ) 338 | } 339 | #ifdef AVMPLUS_PORTING_API 340 | // these pointers are required to store 341 | // the address range where code has been 342 | // modified so we can flush the instruction cache. 343 | void* _endJit2Addr; 344 | #endif // AVMPLUS_PORTING_API 345 | avmplus::Config &config; 346 | }; 347 | 348 | inline int32_t disp(Reservation* r) 349 | { 350 | return stack_direction((int32_t)STACK_GRANULARITY) * int32_t(r->arIndex) + NJ_STACK_OFFSET; 351 | } 352 | } 353 | #endif // __nanojit_Assembler__ 354 | -------------------------------------------------------------------------------- /Fragmento.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * Mozilla TraceMonkey Team 25 | * Asko Tontti 26 | * 27 | * Alternatively, the contents of this file may be used under the terms of 28 | * either the GNU General Public License Version 2 or later (the "GPL"), or 29 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 | * in which case the provisions of the GPL or the LGPL are applicable instead 31 | * of those above. If you wish to allow use of your version of this file only 32 | * under the terms of either the GPL or the LGPL, and not to allow others to 33 | * use your version of this file under the terms of the MPL, indicate your 34 | * decision by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL or the LGPL. If you do not delete 36 | * the provisions above, a recipient may use your version of this file under 37 | * the terms of any one of the MPL, the GPL or the LGPL. 38 | * 39 | * ***** END LICENSE BLOCK ***** */ 40 | 41 | #include "nanojit.h" 42 | #undef MEMORY_INFO 43 | 44 | namespace nanojit 45 | { 46 | #ifdef FEATURE_NANOJIT 47 | 48 | using namespace avmplus; 49 | 50 | static uint32_t calcSaneCacheSize(uint32_t in) 51 | { 52 | if (in < uint32_t(NJ_LOG2_PAGE_SIZE)) return NJ_LOG2_PAGE_SIZE; // at least 1 page 53 | if (in > 32) return 32; // 4GB should be enough for anyone 54 | return in; 55 | } 56 | 57 | /** 58 | * This is the main control center for creating and managing fragments. 59 | */ 60 | Fragmento::Fragmento(AvmCore* core, uint32_t cacheSizeLog2) 61 | : 62 | #ifdef NJ_VERBOSE 63 | enterCounts(NULL), 64 | mergeCounts(NULL), 65 | labels(NULL), 66 | #endif 67 | _frags(core->GetGC()), 68 | _freePages(core->GetGC(), 1024), 69 | _allocList(core->GetGC()), 70 | _gcHeap(NULL), 71 | _max_pages(1 << (calcSaneCacheSize(cacheSizeLog2) - NJ_LOG2_PAGE_SIZE)), 72 | _pagesGrowth(1) 73 | { 74 | #ifdef _DEBUG 75 | { 76 | // XXX These belong somewhere else, but I can't find the 77 | // right location right now. 78 | NanoStaticAssert((LIR_lt ^ 3) == LIR_ge); 79 | NanoStaticAssert((LIR_le ^ 3) == LIR_gt); 80 | NanoStaticAssert((LIR_ult ^ 3) == LIR_uge); 81 | NanoStaticAssert((LIR_ule ^ 3) == LIR_ugt); 82 | NanoStaticAssert((LIR_flt ^ 3) == LIR_fge); 83 | NanoStaticAssert((LIR_fle ^ 3) == LIR_fgt); 84 | 85 | /* Opcodes must be strictly increasing without holes. */ 86 | uint32_t count = 0; 87 | #define OPDEF(op, number, operands) \ 88 | NanoAssertMsg(LIR_##op == count++, "misnumbered opcode"); 89 | #define OPDEF64(op, number, operands) OPDEF(op, number, operands) 90 | #include "LIRopcode.tbl" 91 | #undef OPDEF 92 | #undef OPDEF64 93 | } 94 | #endif 95 | 96 | #ifdef MEMORY_INFO 97 | _allocList.set_meminfo_name("Fragmento._allocList"); 98 | #endif 99 | NanoAssert(_max_pages > _pagesGrowth); // shrink growth if needed 100 | _core = core; 101 | GC *gc = core->GetGC(); 102 | _assm = NJ_NEW(gc, nanojit::Assembler)(this); 103 | verbose_only( enterCounts = NJ_NEW(gc, BlockHist)(gc); ) 104 | verbose_only( mergeCounts = NJ_NEW(gc, BlockHist)(gc); ) 105 | 106 | memset(&_stats, 0, sizeof(_stats)); 107 | } 108 | 109 | Fragmento::~Fragmento() 110 | { 111 | AllocEntry *entry; 112 | 113 | clearFrags(); 114 | _frags.clear(); 115 | _freePages.clear(); 116 | while( _allocList.size() > 0 ) 117 | { 118 | //nj_dprintf("dealloc %x\n", (intptr_t)_allocList.get(_allocList.size()-1)); 119 | #ifdef MEMORY_INFO 120 | ChangeSizeExplicit("NanoJitMem", -1, _gcHeap->Size(_allocList.last())); 121 | #endif 122 | entry = _allocList.removeLast(); 123 | _gcHeap->Free( entry->page, entry->allocSize ); 124 | NJ_DELETE(entry); 125 | } 126 | NJ_DELETE(_assm); 127 | #if defined(NJ_VERBOSE) 128 | NJ_DELETE(enterCounts); 129 | NJ_DELETE(mergeCounts); 130 | #endif 131 | } 132 | 133 | void Fragmento::trackPages() 134 | { 135 | const uint32_t pageUse = _stats.pages - _freePages.size(); 136 | if (_stats.maxPageUse < pageUse) 137 | _stats.maxPageUse = pageUse; 138 | } 139 | 140 | Page* Fragmento::pageAlloc() 141 | { 142 | NanoAssert(sizeof(Page) == NJ_PAGE_SIZE); 143 | if (!_freePages.size()) { 144 | pagesGrow(_pagesGrowth); // try to get more mem 145 | if ((_pagesGrowth << 1) < _max_pages) 146 | _pagesGrowth <<= 1; 147 | } 148 | 149 | trackPages(); 150 | Page* page = 0; 151 | if (_freePages.size()) 152 | page = _freePages.removeLast(); 153 | return page; 154 | } 155 | 156 | void Fragmento::pagesRelease(PageList& l) 157 | { 158 | _freePages.add(l); 159 | l.clear(); 160 | NanoAssert(_freePages.size() <= _stats.pages); 161 | } 162 | 163 | void Fragmento::pageFree(Page* page) 164 | { 165 | _freePages.add(page); 166 | NanoAssert(_freePages.size() <= _stats.pages); 167 | } 168 | 169 | void Fragmento::pagesGrow(int32_t count) 170 | { 171 | NanoAssert(!_freePages.size()); 172 | MMGC_MEM_TYPE("NanojitFragmentoMem"); 173 | Page* memory = 0; 174 | GC *gc = _core->GetGC(); 175 | if (_stats.pages < _max_pages) 176 | { 177 | AllocEntry *entry; 178 | 179 | // make sure we don't grow beyond _max_pages 180 | if (_stats.pages + count > _max_pages) 181 | count = _max_pages - _stats.pages; 182 | if (count < 0) 183 | count = 0; 184 | // @todo nastiness that needs a fix'n 185 | _gcHeap = gc->GetGCHeap(); 186 | NanoAssert(int32_t(NJ_PAGE_SIZE)<=_gcHeap->kNativePageSize); 187 | 188 | // convert _max_pages to gc page count 189 | int32_t gcpages = (count*NJ_PAGE_SIZE) / _gcHeap->kNativePageSize; 190 | MMGC_MEM_TYPE("NanoJitMem"); 191 | memory = (Page*)_gcHeap->Alloc(gcpages); 192 | #ifdef MEMORY_INFO 193 | ChangeSizeExplicit("NanoJitMem", 1, _gcHeap->Size(memory)); 194 | #endif 195 | NanoAssert((uintptr_t)memory == pageTop(memory)); 196 | //nj_dprintf("head alloc of %d at %x of %d pages using nj page size of %d\n", gcpages, (intptr_t)memory, (intptr_t)_gcHeap->kNativePageSize, NJ_PAGE_SIZE); 197 | 198 | entry = NJ_NEW(gc, AllocEntry); 199 | entry->page = memory; 200 | entry->allocSize = gcpages; 201 | _allocList.add(entry); 202 | 203 | _stats.pages += count; 204 | Page* page = memory; 205 | while(--count >= 0) 206 | { 207 | //nj_dprintf("Fragmento::pageGrow adding page %x ; %d\n", (unsigned)page, _freePages.size()+1); 208 | _freePages.add(page++); 209 | } 210 | trackPages(); 211 | } 212 | } 213 | 214 | // Clear the fragment. This *does not* remove the fragment from the 215 | // map--the caller must take care of this. 216 | void Fragmento::clearFragment(Fragment* f) 217 | { 218 | Fragment *peer = f->peer; 219 | while (peer) { 220 | Fragment *next = peer->peer; 221 | peer->releaseTreeMem(this); 222 | NJ_DELETE(peer); 223 | peer = next; 224 | } 225 | f->releaseTreeMem(this); 226 | NJ_DELETE(f); 227 | } 228 | 229 | void Fragmento::clearFrags() 230 | { 231 | // reclaim any dangling native pages 232 | _assm->pageReset(); 233 | 234 | while (!_frags.isEmpty()) { 235 | clearFragment(_frags.removeLast()); 236 | } 237 | 238 | verbose_only( enterCounts->clear();) 239 | verbose_only( mergeCounts->clear();) 240 | verbose_only( _stats.flushes++ ); 241 | verbose_only( _stats.compiles = 0 ); 242 | //nj_dprintf("Fragmento.clearFrags %d free pages of %d\n", _stats.freePages, _stats.pages); 243 | } 244 | 245 | Assembler* Fragmento::assm() 246 | { 247 | return _assm; 248 | } 249 | 250 | AvmCore* Fragmento::core() 251 | { 252 | return _core; 253 | } 254 | 255 | Fragment* Fragmento::getAnchor(const void* ip) 256 | { 257 | Fragment *f = newFrag(ip); 258 | Fragment *p = _frags.get(ip); 259 | if (p) { 260 | f->first = p; 261 | /* append at the end of the peer list */ 262 | Fragment* next; 263 | while ((next = p->peer) != NULL) 264 | p = next; 265 | p->peer = f; 266 | } else { 267 | f->first = f; 268 | _frags.put(ip, f); /* this is the first fragment */ 269 | } 270 | f->anchor = f; 271 | f->root = f; 272 | f->kind = LoopTrace; 273 | verbose_only( addLabel(f, "T", _frags.size()); ) 274 | return f; 275 | } 276 | 277 | Fragment* Fragmento::getLoop(const void* ip) 278 | { 279 | return _frags.get(ip); 280 | } 281 | 282 | #ifdef NJ_VERBOSE 283 | void Fragmento::addLabel(Fragment *f, const char *prefix, int id) 284 | { 285 | char fragname[20]; 286 | sprintf(fragname,"%s%d", prefix, id); 287 | labels->add(f, sizeof(Fragment), 0, fragname); 288 | } 289 | #endif 290 | 291 | Fragment *Fragmento::createBranch(SideExit* exit, const void* ip) 292 | { 293 | Fragment *f = newBranch(exit->from, ip); 294 | f->kind = BranchTrace; 295 | f->treeBranches = f->root->treeBranches; 296 | f->root->treeBranches = f; 297 | return f; 298 | } 299 | 300 | #ifdef NJ_VERBOSE 301 | struct fragstats { 302 | int size; 303 | uint64_t traceDur; 304 | uint64_t interpDur; 305 | int lir, lirbytes; 306 | }; 307 | 308 | void Fragmento::dumpFragStats(Fragment *f, int level, fragstats &stat) 309 | { 310 | char buf[50]; 311 | sprintf(buf, "%*c%s", 1+level, ' ', labels->format(f)); 312 | 313 | int called = f->hits(); 314 | if (called >= 0) 315 | called += f->_called; 316 | else 317 | called = -(1<blacklistLevel) - called - 1; 318 | 319 | uint32_t main = f->_native - f->_exitNative; 320 | 321 | char cause[200]; 322 | if (f->_token && strcmp(f->_token,"loop")==0) 323 | sprintf(cause,"%s %d", f->_token, f->xjumpCount); 324 | else if (f->_token) { 325 | if (f->eot_target) { 326 | sprintf(cause,"%s %s", f->_token, labels->format(f->eot_target)); 327 | } else { 328 | strcpy(cause, f->_token); 329 | } 330 | } 331 | else 332 | cause[0] = 0; 333 | 334 | _assm->outputf("%-10s %7d %6d %6d %6d %4d %9llu %9llu %-12s %s", buf, 335 | called, f->guardCount, main, f->_native, f->compileNbr, f->traceTicks/1000, f->interpTicks/1000, 336 | cause, labels->format(f->ip)); 337 | 338 | stat.size += main; 339 | stat.traceDur += f->traceTicks; 340 | stat.interpDur += f->interpTicks; 341 | stat.lir += f->_lir; 342 | stat.lirbytes += f->_lirbytes; 343 | 344 | for (Fragment *x = f->branches; x != 0; x = x->nextbranch) 345 | if (x->kind != MergeTrace) 346 | dumpFragStats(x,level+1,stat); 347 | for (Fragment *x = f->branches; x != 0; x = x->nextbranch) 348 | if (x->kind == MergeTrace) 349 | dumpFragStats(x,level+1,stat); 350 | 351 | if (f->isAnchor() && f->branches != 0) { 352 | _assm->output(""); 353 | } 354 | } 355 | 356 | class DurData { public: 357 | DurData(): frag(0), traceDur(0), interpDur(0), size(0) {} 358 | DurData(int): frag(0), traceDur(0), interpDur(0), size(0) {} 359 | DurData(Fragment* f, uint64_t td, uint64_t id, int32_t s) 360 | : frag(f), traceDur(td), interpDur(id), size(s) {} 361 | Fragment* frag; 362 | uint64_t traceDur; 363 | uint64_t interpDur; 364 | int32_t size; 365 | }; 366 | 367 | void Fragmento::dumpRatio(const char *label, BlockHist *hist) 368 | { 369 | int total=0, unique=0; 370 | for (int i = 0, n=hist->size(); i < n; i++) { 371 | const void * id = hist->keyAt(i); 372 | int c = hist->get(id); 373 | if (c > 1) { 374 | //_assm->outputf("%d %X", c, id); 375 | unique += 1; 376 | } 377 | else if (c == 1) { 378 | unique += 1; 379 | } 380 | total += c; 381 | } 382 | _assm->outputf("%s total %d unique %d ratio %.1f%", label, total, unique, double(total)/unique); 383 | } 384 | 385 | void Fragmento::dumpStats() 386 | { 387 | bool vsave = _assm->_verbose; 388 | _assm->_verbose = true; 389 | 390 | _assm->output(""); 391 | dumpRatio("inline", enterCounts); 392 | dumpRatio("merges", mergeCounts); 393 | _assm->outputf("abc %d il %d (%.1fx) abc+il %d (%.1fx)", 394 | _stats.abcsize, _stats.ilsize, (double)_stats.ilsize/_stats.abcsize, 395 | _stats.abcsize + _stats.ilsize, 396 | double(_stats.abcsize+_stats.ilsize)/_stats.abcsize); 397 | 398 | int32_t count = _frags.size(); 399 | int32_t pages = _stats.pages; 400 | int32_t maxPageUse = _stats.maxPageUse; 401 | int32_t free = _freePages.size(); 402 | int32_t flushes = _stats.flushes; 403 | if (!count) 404 | { 405 | _assm->outputf("No fragments in cache, %d flushes", flushes); 406 | _assm->_verbose = vsave; 407 | return; 408 | } 409 | 410 | _assm->outputf("\nFragment statistics"); 411 | _assm->outputf(" loop trees: %d", count); 412 | _assm->outputf(" flushes: %d", flushes); 413 | _assm->outputf(" compiles: %d / %d", _stats.compiles, _stats.totalCompiles); 414 | _assm->outputf(" used: %dk / %dk", (pages-free)<<(NJ_LOG2_PAGE_SIZE-10), pages<<(NJ_LOG2_PAGE_SIZE-10)); 415 | _assm->outputf(" maxPageUse: %dk", (maxPageUse)<<(NJ_LOG2_PAGE_SIZE-10)); 416 | _assm->output("\ntrace calls guards main native gen T-trace T-interp"); 417 | 418 | avmplus::SortedMap durs(_core->gc); 419 | uint64_t totaldur=0; 420 | fragstats totalstat = { 0,0,0,0,0 }; 421 | for (int32_t i=0; ipeer) 442 | break; 443 | f = f->peer; 444 | } 445 | } 446 | uint64_t totaltrace = totalstat.traceDur; 447 | int totalsize = totalstat.size; 448 | 449 | _assm->outputf(""); 450 | _assm->outputf("lirbytes %d / lir %d = %.1f bytes/lir", totalstat.lirbytes, 451 | totalstat.lir, double(totalstat.lirbytes)/totalstat.lir); 452 | _assm->outputf(" trace interp"); 453 | _assm->outputf("%9lld (%2d%%) %9lld (%2d%%)", 454 | totaltrace/1000, int(100.0*totaltrace/totaldur), 455 | (totaldur-totaltrace)/1000, int(100.0*(totaldur-totaltrace)/totaldur)); 456 | _assm->outputf(""); 457 | _assm->outputf("trace ticks trace interp size"); 458 | for (int32_t i=durs.size()-1; i >= 0; i--) { 459 | uint64_t bothDur = durs.keyAt(i); 460 | DurData d = durs.get(bothDur); 461 | int size = d.size; 462 | _assm->outputf("%-4s %9lld (%2d%%) %9lld (%2d%%) %9lld (%2d%%) %6d (%2d%%) %s", 463 | labels->format(d.frag), 464 | bothDur/1000, int(100.0*bothDur/totaldur), 465 | d.traceDur/1000, int(100.0*d.traceDur/totaldur), 466 | d.interpDur/1000, int(100.0*d.interpDur/totaldur), 467 | size, int(100.0*size/totalsize), 468 | labels->format(d.frag->ip)); 469 | } 470 | 471 | _assm->_verbose = vsave; 472 | 473 | } 474 | 475 | void Fragmento::countBlock(BlockHist *hist, const void* ip) 476 | { 477 | int c = hist->count(ip); 478 | if (_assm->_verbose) 479 | _assm->outputf("++ %s %d", labels->format(ip), c); 480 | } 481 | 482 | void Fragmento::countIL(uint32_t il, uint32_t abc) 483 | { 484 | _stats.ilsize += il; 485 | _stats.abcsize += abc; 486 | } 487 | 488 | #ifdef AVMPLUS_VERBOSE 489 | void Fragmento::drawTrees(char *fileName) { 490 | drawTraceTrees(this, this->_frags, this->_core, fileName); 491 | } 492 | #endif 493 | #endif // NJ_VERBOSE 494 | 495 | // 496 | // Fragment 497 | // 498 | Fragment::Fragment(const void* _ip) 499 | : 500 | #ifdef NJ_VERBOSE 501 | _called(0), 502 | _native(0), 503 | _exitNative(0), 504 | _lir(0), 505 | _lirbytes(0), 506 | _token(NULL), 507 | traceTicks(0), 508 | interpTicks(0), 509 | eot_target(NULL), 510 | sid(0), 511 | compileNbr(0), 512 | #endif 513 | treeBranches(NULL), 514 | branches(NULL), 515 | nextbranch(NULL), 516 | anchor(NULL), 517 | root(NULL), 518 | parent(NULL), 519 | first(NULL), 520 | peer(NULL), 521 | lirbuf(NULL), 522 | lastIns(NULL), 523 | spawnedFrom(NULL), 524 | kind(LoopTrace), 525 | ip(_ip), 526 | guardCount(0), 527 | xjumpCount(0), 528 | recordAttempts(0), 529 | blacklistLevel(0), 530 | fragEntry(NULL), 531 | loopEntry(NULL), 532 | vmprivate(NULL), 533 | _code(NULL), 534 | _hits(0), 535 | _pages(NULL) 536 | { 537 | } 538 | 539 | Fragment::~Fragment() 540 | { 541 | onDestroy(); 542 | NanoAssert(_pages == 0); 543 | } 544 | 545 | void Fragment::blacklist() 546 | { 547 | blacklistLevel++; 548 | _hits = -(1<gc; 554 | Fragment *f = NJ_NEW(gc, Fragment)(ip); 555 | f->blacklistLevel = 5; 556 | return f; 557 | } 558 | 559 | Fragment *Fragmento::newBranch(Fragment *from, const void* ip) 560 | { 561 | Fragment *f = newFrag(ip); 562 | f->anchor = from->anchor; 563 | f->root = from->root; 564 | f->xjumpCount = from->xjumpCount; 565 | /*// prepend 566 | f->nextbranch = from->branches; 567 | from->branches = f;*/ 568 | // append 569 | if (!from->branches) { 570 | from->branches = f; 571 | } else { 572 | Fragment *p = from->branches; 573 | while (p->nextbranch != 0) 574 | p = p->nextbranch; 575 | p->nextbranch = f; 576 | } 577 | return f; 578 | } 579 | 580 | void Fragment::releaseLirBuffer() 581 | { 582 | lastIns = 0; 583 | } 584 | 585 | void Fragment::releaseCode(Fragmento* frago) 586 | { 587 | _code = 0; 588 | while(_pages) 589 | { 590 | Page* next = _pages->next; 591 | frago->pageFree(_pages); 592 | _pages = next; 593 | } 594 | } 595 | 596 | void Fragment::releaseTreeMem(Fragmento* frago) 597 | { 598 | releaseLirBuffer(); 599 | releaseCode(frago); 600 | 601 | // now do it for all branches 602 | Fragment* branch = branches; 603 | while(branch) 604 | { 605 | Fragment* next = branch->nextbranch; 606 | branch->releaseTreeMem(frago); // @todo safer here to recurse in case we support nested trees 607 | NJ_DELETE(branch); 608 | branch = next; 609 | } 610 | } 611 | #endif /* FEATURE_NANOJIT */ 612 | } 613 | 614 | 615 | -------------------------------------------------------------------------------- /Fragmento.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * Mozilla TraceMonkey Team 25 | * Asko Tontti 26 | * 27 | * Alternatively, the contents of this file may be used under the terms of 28 | * either the GNU General Public License Version 2 or later (the "GPL"), or 29 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 | * in which case the provisions of the GPL or the LGPL are applicable instead 31 | * of those above. If you wish to allow use of your version of this file only 32 | * under the terms of either the GPL or the LGPL, and not to allow others to 33 | * use your version of this file under the terms of the MPL, indicate your 34 | * decision by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL or the LGPL. If you do not delete 36 | * the provisions above, a recipient may use your version of this file under 37 | * the terms of any one of the MPL, the GPL or the LGPL. 38 | * 39 | * ***** END LICENSE BLOCK ***** */ 40 | 41 | 42 | #ifndef __nanojit_Fragmento__ 43 | #define __nanojit_Fragmento__ 44 | 45 | #ifdef AVMPLUS_VERBOSE 46 | extern void drawTraceTrees(Fragmento *frago, FragmentMap * _frags, avmplus::AvmCore *core, char *fileName); 47 | #endif 48 | 49 | namespace nanojit 50 | { 51 | struct GuardRecord; 52 | class Assembler; 53 | 54 | struct PageHeader 55 | { 56 | struct Page *next; 57 | }; 58 | struct Page: public PageHeader 59 | { 60 | union { 61 | // Conceptually, the lir array holds mostly LIns values (plus some 62 | // skip payloads and call arguments). But we use int8_t as the 63 | // element type here so the array size can be expressed in bytes. 64 | int8_t lir[NJ_PAGE_SIZE-sizeof(PageHeader)]; 65 | NIns code[(NJ_PAGE_SIZE-sizeof(PageHeader))/sizeof(NIns)]; 66 | }; 67 | }; 68 | struct AllocEntry : public avmplus::GCObject 69 | { 70 | Page *page; 71 | uint32_t allocSize; 72 | }; 73 | typedef avmplus::List AllocList; 74 | 75 | typedef avmplus::GCSortedMap BlockSortedMap; 76 | class BlockHist: public BlockSortedMap 77 | { 78 | public: 79 | BlockHist(avmplus::GC*gc) : BlockSortedMap(gc) 80 | { 81 | } 82 | uint32_t count(const void *p) { 83 | uint32_t c = 1+get(p); 84 | put(p, c); 85 | return c; 86 | } 87 | }; 88 | 89 | struct fragstats; 90 | /* 91 | * 92 | * This is the main control center for creating and managing fragments. 93 | */ 94 | class Fragmento : public avmplus::GCFinalizedObject 95 | { 96 | public: 97 | Fragmento(AvmCore* core, uint32_t cacheSizeLog2); 98 | ~Fragmento(); 99 | 100 | void addMemory(void* firstPage, uint32_t pageCount); // gives memory to the Assembler 101 | Assembler* assm(); 102 | AvmCore* core(); 103 | Page* pageAlloc(); 104 | void pageFree(Page* page); 105 | void pagesRelease(PageList& list); 106 | 107 | Fragment* getLoop(const void* ip); 108 | Fragment* getAnchor(const void* ip); 109 | // Remove one fragment. The caller is responsible for making sure 110 | // that this does not destroy any resources shared with other 111 | // fragments (such as a LirBuffer or this fragment itself as a 112 | // jump target). 113 | void clearFrags(); // clear all fragments from the cache 114 | Fragment* createBranch(SideExit *exit, const void* ip); 115 | Fragment* newFrag(const void* ip); 116 | Fragment* newBranch(Fragment *from, const void* ip); 117 | 118 | verbose_only ( uint32_t pageCount(); ) 119 | verbose_only ( void dumpStats(); ) 120 | verbose_only ( void dumpRatio(const char*, BlockHist*);) 121 | verbose_only ( void dumpFragStats(Fragment*, int level, fragstats&); ) 122 | verbose_only ( void countBlock(BlockHist*, const void* pc); ) 123 | verbose_only ( void countIL(uint32_t il, uint32_t abc); ) 124 | verbose_only( void addLabel(Fragment* f, const char *prefix, int id); ) 125 | 126 | // stats 127 | struct 128 | { 129 | uint32_t pages; // pages consumed 130 | uint32_t maxPageUse; // highwater mark of (pages-freePages) 131 | uint32_t flushes, ilsize, abcsize, compiles, totalCompiles; 132 | } 133 | _stats; 134 | 135 | verbose_only( DWB(BlockHist*) enterCounts; ) 136 | verbose_only( DWB(BlockHist*) mergeCounts; ) 137 | verbose_only( DWB(LabelMap*) labels; ) 138 | 139 | #ifdef AVMPLUS_VERBOSE 140 | void drawTrees(char *fileName); 141 | #endif 142 | 143 | uint32_t cacheUsed() const { return (_stats.pages-_freePages.size())< Fragment ptr */ 153 | PageList _freePages; 154 | 155 | /* unmanaged mem */ 156 | AllocList _allocList; 157 | avmplus::GCHeap* _gcHeap; 158 | 159 | const uint32_t _max_pages; 160 | uint32_t _pagesGrowth; 161 | }; 162 | 163 | enum TraceKind { 164 | LoopTrace, 165 | BranchTrace, 166 | MergeTrace 167 | }; 168 | 169 | /** 170 | * Fragments are linear sequences of native code that have a single entry 171 | * point at the start of the fragment and may have one or more exit points 172 | * 173 | * It may turn out that that this arrangement causes too much traffic 174 | * between d and i-caches and that we need to carve up the structure differently. 175 | */ 176 | class Fragment : public avmplus::GCFinalizedObject 177 | { 178 | public: 179 | Fragment(const void*); 180 | ~Fragment(); 181 | 182 | NIns* code() { return _code; } 183 | Page* pages() { return _pages; } 184 | void setCode(NIns* codee, Page* pages) { _code = codee; _pages = pages; } 185 | int32_t& hits() { return _hits; } 186 | void blacklist(); 187 | bool isBlacklisted() { return _hits < 0; } 188 | void releaseLirBuffer(); 189 | void releaseCode(Fragmento* frago); 190 | void releaseTreeMem(Fragmento* frago); 191 | bool isAnchor() { return anchor == this; } 192 | bool isRoot() { return root == this; } 193 | void onDestroy(); 194 | 195 | verbose_only( uint32_t _called; ) 196 | verbose_only( uint32_t _native; ) 197 | verbose_only( uint32_t _exitNative; ) 198 | verbose_only( uint32_t _lir; ) 199 | verbose_only( uint32_t _lirbytes; ) 200 | verbose_only( const char* _token; ) 201 | verbose_only( uint64_t traceTicks; ) 202 | verbose_only( uint64_t interpTicks; ) 203 | verbose_only( DWB(Fragment*) eot_target; ) 204 | verbose_only( uint32_t sid;) 205 | verbose_only( uint32_t compileNbr;) 206 | 207 | DWB(Fragment*) treeBranches; 208 | DWB(Fragment*) branches; 209 | DWB(Fragment*) nextbranch; 210 | DWB(Fragment*) anchor; 211 | DWB(Fragment*) root; 212 | DWB(Fragment*) parent; 213 | DWB(Fragment*) first; 214 | DWB(Fragment*) peer; 215 | DWB(LirBuffer*) lirbuf; 216 | LIns* lastIns; 217 | SideExit* spawnedFrom; 218 | 219 | TraceKind kind; 220 | const void* ip; 221 | uint32_t guardCount; 222 | uint32_t xjumpCount; 223 | uint32_t recordAttempts; 224 | int32_t blacklistLevel; 225 | NIns* fragEntry; 226 | NIns* loopEntry; 227 | void* vmprivate; 228 | 229 | private: 230 | NIns* _code; // ptr to start of code 231 | GuardRecord* _links; // code which is linked (or pending to be) to this fragment 232 | int32_t _hits; 233 | Page* _pages; // native code pages 234 | }; 235 | } 236 | #endif // __nanojit_Fragmento__ 237 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Version: MPL 1.1/GPL 2.0/LGPL 2.1 2 | 3 | The contents of this file are subject to the Mozilla Public License Version 4 | 1.1 (the "License"); you may not use this file except in compliance with 5 | the License. You may obtain a copy of the License at 6 | http://www.mozilla.org/MPL/ 7 | 8 | Software distributed under the License is distributed on an "AS IS" basis, 9 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 10 | for the specific language governing rights and limitations under the 11 | License. 12 | 13 | Alternatively, the contents of this file may be used under the terms of 14 | either the GNU General Public License Version 2 or later (the "GPL"), or 15 | the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 16 | in which case the provisions of the GPL or the LGPL are applicable instead 17 | of those above. If you wish to allow use of your version of this file only 18 | under the terms of either the GPL or the LGPL, and not to allow others to 19 | use your version of this file under the terms of the MPL, indicate your 20 | decision by deleting the provisions above and replace them with the notice 21 | and other provisions required by the GPL or the LGPL. If you do not delete 22 | the provisions above, a recipient may use your version of this file under 23 | the terms of any one of the MPL, the GPL or the LGPL. -------------------------------------------------------------------------------- /LIR.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #ifndef __nanojit_LIR__ 40 | #define __nanojit_LIR__ 41 | 42 | /** 43 | * Fundamentally, the arguments to the various operands can be grouped along 44 | * two dimensions. One dimension is size: can the arguments fit into a 32-bit 45 | * register, or not? The other dimension is whether the argument is an integer 46 | * (including pointers) or a floating-point value. In all comments below, 47 | * "integer" means integer of any size, including 64-bit, unless otherwise 48 | * specified. All floating-point values are always 64-bit. Below, "quad" is 49 | * used for a 64-bit value that might be either integer or floating-point. 50 | */ 51 | namespace nanojit 52 | { 53 | enum LOpcode 54 | #if defined(_MSC_VER) && _MSC_VER >= 1400 55 | : unsigned 56 | #endif 57 | { 58 | // flags; upper bits reserved 59 | LIR64 = 0x40, // result is double or quad 60 | 61 | #define OPDEF(op, number, args) \ 62 | LIR_##op = (number), 63 | #define OPDEF64(op, number, args) \ 64 | LIR_##op = ((number) | LIR64), 65 | #include "LIRopcode.tbl" 66 | LIR_sentinel 67 | #undef OPDEF 68 | #undef OPDEF64 69 | }; 70 | 71 | #if defined NANOJIT_64BIT 72 | #define LIR_ldp LIR_ldq 73 | #define LIR_stp LIR_stq 74 | #define LIR_piadd LIR_qiadd 75 | #define LIR_piand LIR_qiand 76 | #define LIR_pilsh LIR_qilsh 77 | #define LIR_pcmov LIR_qcmov 78 | #define LIR_pior LIR_qior 79 | #else 80 | #define LIR_ldp LIR_ld 81 | #define LIR_stp LIR_st 82 | #define LIR_piadd LIR_add 83 | #define LIR_piand LIR_and 84 | #define LIR_pilsh LIR_lsh 85 | #define LIR_pcmov LIR_cmov 86 | #define LIR_pior LIR_or 87 | #endif 88 | 89 | struct GuardRecord; 90 | struct SideExit; 91 | struct Page; 92 | 93 | enum AbiKind { 94 | ABI_FASTCALL, 95 | ABI_THISCALL, 96 | ABI_STDCALL, 97 | ABI_CDECL 98 | }; 99 | 100 | enum ArgSize { 101 | ARGSIZE_NONE = 0, 102 | ARGSIZE_F = 1, 103 | ARGSIZE_LO = 2, 104 | ARGSIZE_Q = 3, 105 | _ARGSIZE_MASK_INT = 2, 106 | _ARGSIZE_MASK_ANY = 3 107 | }; 108 | 109 | struct CallInfo 110 | { 111 | uintptr_t _address; 112 | uint32_t _argtypes:18; // 9 2-bit fields indicating arg type, by ARGSIZE above (including ret type): a1 a2 a3 a4 a5 ret 113 | uint8_t _cse:1; // true if no side effects 114 | uint8_t _fold:1; // true if no side effects 115 | AbiKind _abi:3; 116 | verbose_only ( const char* _name; ) 117 | 118 | uint32_t FASTCALL _count_args(uint32_t mask) const; 119 | uint32_t get_sizes(ArgSize*) const; 120 | 121 | inline uint32_t FASTCALL count_args() const { 122 | return _count_args(_ARGSIZE_MASK_ANY); 123 | } 124 | inline uint32_t FASTCALL count_iargs() const { 125 | return _count_args(_ARGSIZE_MASK_INT); 126 | } 127 | // fargs = args - iargs 128 | }; 129 | 130 | /* 131 | * Record for extra data used to compile switches as jump tables. 132 | */ 133 | struct SwitchInfo 134 | { 135 | NIns** table; // Jump table; a jump address is NIns* 136 | uint32_t count; // Number of table entries 137 | // Index value at last execution of the switch. The index value 138 | // is the offset into the jump table. Thus it is computed as 139 | // (switch expression) - (lowest case value). 140 | uint32_t index; 141 | }; 142 | 143 | inline bool isCseOpcode(LOpcode op) { 144 | op = LOpcode(op & ~LIR64); 145 | return op >= LIR_int && op <= LIR_uge; 146 | } 147 | inline bool isRetOpcode(LOpcode op) { 148 | return (op & ~LIR64) == LIR_ret; 149 | } 150 | 151 | // Sun Studio requires explicitly declaring signed int bit-field 152 | #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 153 | #define _sign_int signed int 154 | #else 155 | #define _sign_int int32_t 156 | #endif 157 | 158 | // The opcode is not logically part of the Reservation, but we include it 159 | // in this struct to ensure that opcode plus the Reservation fits in a 160 | // single word. Yuk. 161 | struct Reservation 162 | { 163 | uint32_t arIndex:16; // index into stack frame. displ is -4*arIndex 164 | Register reg:7; // register UnknownReg implies not in register 165 | uint32_t used:1; // when set, the reservation is active 166 | LOpcode code:8; 167 | }; 168 | 169 | // Low-level Instruction. 4 words per instruction -- it's important this 170 | // doesn't change unintentionally, so it is checked in LIR.cpp by an 171 | // assertion in initOpcodeAndClearResv(). 172 | // The first word is the same for all LIns kinds; the last three differ. 173 | class LIns 174 | { 175 | friend class LirBufWriter; 176 | 177 | // 2-operand form. Used for most LIns kinds, including LIR_skip (for 178 | // which oprnd_1 is the target). 179 | struct u_type 180 | { 181 | // Nb: oprnd_1 and oprnd_2 layout must match that in sti_type 182 | // because oprnd1() and oprnd2() are used for both. 183 | LIns* oprnd_1; 184 | 185 | LIns* oprnd_2; 186 | }; 187 | 188 | // Used for LIR_sti and LIR_stqi. 189 | struct sti_type 190 | { 191 | // Nb: oprnd_1 and oprnd_2 layout must match that in u_type 192 | // because oprnd1() and oprnd2() are used for both. 193 | LIns* oprnd_1; 194 | 195 | LIns* oprnd_2; 196 | 197 | int32_t disp; 198 | }; 199 | 200 | // Used for LIR_call and LIR_param. 201 | struct c_type 202 | { 203 | uintptr_t imm8a:8; // call: 0 (not used); param: arg 204 | uintptr_t imm8b:8; // call: argc; param: kind 205 | 206 | const CallInfo* ci; // call: callInfo; param: NULL (not used) 207 | }; 208 | 209 | // Used for LIR_int. 210 | struct i_type 211 | { 212 | int32_t imm32; 213 | }; 214 | 215 | // Used for LIR_quad. 216 | struct i64_type 217 | { 218 | int32_t imm64_0; 219 | int32_t imm64_1; 220 | }; 221 | 222 | #undef _sign_int 223 | 224 | // 1st word: fields shared by all LIns kinds. The reservation fields 225 | // are read/written during assembly. 226 | Reservation firstWord; 227 | 228 | // 2nd, 3rd and 4th words: differ depending on the LIns kind. 229 | union 230 | { 231 | u_type u; 232 | c_type c; 233 | i_type i; 234 | i64_type i64; 235 | sti_type sti; 236 | }; 237 | 238 | public: 239 | LIns* oprnd1() const { 240 | NanoAssert(isOp1() || isOp2() || isLoad() || isStore()); 241 | return u.oprnd_1; 242 | } 243 | LIns* oprnd2() const { 244 | NanoAssert(isOp2() || isLoad() || isStore()); 245 | return u.oprnd_2; 246 | } 247 | 248 | inline LOpcode opcode() const { return firstWord.code; } 249 | inline uint8_t imm8() const { NanoAssert(isop(LIR_param)); return c.imm8a; } 250 | inline uint8_t imm8b() const { NanoAssert(isop(LIR_param)); return c.imm8b; } 251 | inline int32_t imm32() const { NanoAssert(isconst()); return i.imm32; } 252 | inline int32_t imm64_0() const { NanoAssert(isconstq()); return i64.imm64_0; } 253 | inline int32_t imm64_1() const { NanoAssert(isconstq()); return i64.imm64_1; } 254 | uint64_t imm64() const; 255 | double imm64f() const; 256 | Reservation* resv() { return &firstWord; } 257 | void* payload() const; 258 | inline Page* page() { return (Page*) alignTo(this,NJ_PAGE_SIZE); } 259 | inline int32_t size() const { 260 | NanoAssert(isop(LIR_alloc)); 261 | return i.imm32<<2; 262 | } 263 | inline void setSize(int32_t bytes) { 264 | NanoAssert(isop(LIR_alloc) && (bytes&3)==0 && isU16(bytes>>2)); 265 | i.imm32 = bytes>>2; 266 | } 267 | 268 | LIns* arg(uint32_t i); 269 | 270 | inline int32_t immdisp() const 271 | { 272 | NanoAssert(isStore()); 273 | return sti.disp; 274 | } 275 | 276 | inline void* constvalp() const 277 | { 278 | #ifdef AVMPLUS_64BIT 279 | return (void*)imm64(); 280 | #else 281 | return (void*)imm32(); 282 | #endif 283 | } 284 | 285 | bool isCse(const CallInfo *functions) const; 286 | bool isRet() const { return nanojit::isRetOpcode(firstWord.code); } 287 | bool isop(LOpcode o) const { return firstWord.code == o; } 288 | #if defined(_DEBUG) 289 | bool isOp1() const; // true for unary ops 290 | bool isOp2() const; // true for binary ops 291 | #endif 292 | bool isQuad() const; 293 | bool isCond() const; 294 | bool isFloat() const; 295 | bool isCmp() const; 296 | bool isCall() const { 297 | LOpcode op = LOpcode(firstWord.code & ~LIR64); 298 | return op == LIR_call; 299 | } 300 | bool isStore() const { 301 | LOpcode op = LOpcode(firstWord.code & ~LIR64); 302 | return op == LIR_sti; 303 | } 304 | bool isLoad() const { 305 | LOpcode op = firstWord.code; 306 | return op == LIR_ldq || op == LIR_ld || op == LIR_ldc || 307 | op == LIR_ldqc || op == LIR_ldcs || op == LIR_ldcb; 308 | } 309 | bool isGuard() const { 310 | LOpcode op = firstWord.code; 311 | return op == LIR_x || op == LIR_xf || op == LIR_xt || 312 | op == LIR_loop || op == LIR_xbarrier || op == LIR_xtbl; 313 | } 314 | // True if the instruction is a 32-bit or smaller constant integer. 315 | bool isconst() const { return firstWord.code == LIR_int; } 316 | // True if the instruction is a 32-bit or smaller constant integer and 317 | // has the value val when treated as a 32-bit signed integer. 318 | bool isconstval(int32_t val) const; 319 | // True if the instruction is a constant quad value. 320 | bool isconstq() const; 321 | // True if the instruction is a constant pointer value. 322 | bool isconstp() const; 323 | bool isBranch() const { 324 | return isop(LIR_jt) || isop(LIR_jf) || isop(LIR_j); 325 | } 326 | void setimm32(int32_t x) { NanoAssert(isconst()); i.imm32 = x; } 327 | // Set the opcode and clear resv. 328 | void initOpcodeAndClearResv(LOpcode); 329 | Reservation* initResv(); 330 | void clearResv(); 331 | 332 | // operand-setting methods 333 | void setOprnd1(LIns* r) { 334 | NanoAssert(isOp1() || isOp2() || isLoad() || isStore()); 335 | u.oprnd_1 = r; 336 | } 337 | void setOprnd2(LIns* r) { 338 | NanoAssert(isOp2() || isLoad() || isStore()); 339 | u.oprnd_2 = r; 340 | } 341 | void setDisp(int32_t d) { 342 | NanoAssert(isStore()); 343 | sti.disp = d; 344 | } 345 | void setTarget(LIns* t); 346 | LIns* getTarget(); 347 | 348 | GuardRecord *record(); 349 | 350 | inline uint32_t argc() const { 351 | NanoAssert(isCall()); 352 | return c.imm8b; 353 | } 354 | const CallInfo *callInfo() const; 355 | }; 356 | typedef LIns* LInsp; 357 | 358 | LIns* FASTCALL callArgN(LInsp i, uint32_t n); 359 | extern const uint8_t operandCount[]; 360 | 361 | class Fragmento; // @todo remove this ; needed for minbuild for some reason?!? Should not be compiling this code at all 362 | class LirFilter; 363 | 364 | // make it a GCObject so we can explicitly delete it early 365 | class LirWriter : public avmplus::GCObject 366 | { 367 | public: 368 | LirWriter *out; 369 | const CallInfo *_functions; 370 | 371 | virtual ~LirWriter() {} 372 | LirWriter(LirWriter* out) 373 | : out(out), _functions(out?out->_functions : 0) {} 374 | 375 | virtual LInsp ins0(LOpcode v) { 376 | return out->ins0(v); 377 | } 378 | virtual LInsp ins1(LOpcode v, LIns* a) { 379 | return out->ins1(v, a); 380 | } 381 | virtual LInsp ins2(LOpcode v, LIns* a, LIns* b) { 382 | return out->ins2(v, a, b); 383 | } 384 | virtual LInsp insGuard(LOpcode v, LIns *c, LIns *x) { 385 | return out->insGuard(v, c, x); 386 | } 387 | virtual LInsp insBranch(LOpcode v, LInsp condition, LInsp to) { 388 | return out->insBranch(v, condition, to); 389 | } 390 | // arg: 0=first, 1=second, ... 391 | // kind: 0=arg 1=saved-reg 392 | virtual LInsp insParam(int32_t arg, int32_t kind) { 393 | return out->insParam(arg, kind); 394 | } 395 | virtual LInsp insImm(int32_t imm) { 396 | return out->insImm(imm); 397 | } 398 | virtual LInsp insImmq(uint64_t imm) { 399 | return out->insImmq(imm); 400 | } 401 | virtual LInsp insLoad(LOpcode op, LIns* base, LIns* d) { 402 | return out->insLoad(op, base, d); 403 | } 404 | virtual LInsp insStorei(LIns* value, LIns* base, int32_t d) { 405 | return out->insStorei(value, base, d); 406 | } 407 | virtual LInsp insCall(const CallInfo *call, LInsp args[]) { 408 | return out->insCall(call, args); 409 | } 410 | virtual LInsp insAlloc(int32_t size) { 411 | return out->insAlloc(size); 412 | } 413 | virtual LInsp insSkip(size_t size) { 414 | return out->insSkip(size); 415 | } 416 | 417 | // convenience 418 | LIns* insLoadi(LIns *base, int disp); 419 | LIns* insLoad(LOpcode op, LIns *base, int disp); 420 | // Inserts a conditional to execute and branches to execute if 421 | // the condition is true and false respectively. 422 | LIns* ins_choose(LIns* cond, LIns* iftrue, LIns* iffalse); 423 | // Inserts an integer comparison to 0 424 | LIns* ins_eq0(LIns* oprnd1); 425 | // Inserts a binary operation where the second operand is an 426 | // integer immediate. 427 | LIns* ins2i(LOpcode op, LIns *oprnd1, int32_t); 428 | LIns* qjoin(LInsp lo, LInsp hi); 429 | LIns* insImmPtr(const void *ptr); 430 | LIns* insImmf(double f); 431 | }; 432 | 433 | 434 | // Each page has a header; the rest of it holds code. 435 | #define NJ_PAGE_CODE_AREA_SZB (NJ_PAGE_SIZE - sizeof(PageHeader)) 436 | 437 | // The first instruction on a page is always a start instruction, or a 438 | // payload-less skip instruction linking to the previous page. The 439 | // biggest possible instruction would take up the entire rest of the page. 440 | #define NJ_MAX_LINS_SZB (NJ_PAGE_CODE_AREA_SZB - sizeof(LIns)) 441 | 442 | // The maximum skip payload size is determined by the maximum instruction 443 | // size. We require that a skip's payload be adjacent to the skip LIns 444 | // itself. 445 | #define NJ_MAX_SKIP_PAYLOAD_SZB (NJ_MAX_LINS_SZB - sizeof(LIns)) 446 | 447 | 448 | #ifdef NJ_VERBOSE 449 | extern const char* lirNames[]; 450 | 451 | /** 452 | * map address ranges to meaningful names. 453 | */ 454 | class LabelMap MMGC_SUBCLASS_DECL 455 | { 456 | LabelMap* parent; 457 | class Entry MMGC_SUBCLASS_DECL 458 | { 459 | public: 460 | Entry(int) : name(0), size(0), align(0) {} 461 | Entry(avmplus::String *n, size_t s, size_t a) : name(n),size(s),align(a) {} 462 | ~Entry(); 463 | DRCWB(avmplus::String*) name; 464 | size_t size:29, align:3; 465 | }; 466 | avmplus::SortedMap names; 467 | bool addrs, pad[3]; 468 | char buf[1000], *end; 469 | void formatAddr(const void *p, char *buf); 470 | public: 471 | avmplus::AvmCore *core; 472 | LabelMap(avmplus::AvmCore *, LabelMap* parent); 473 | ~LabelMap(); 474 | void add(const void *p, size_t size, size_t align, const char *name); 475 | void add(const void *p, size_t size, size_t align, avmplus::String*); 476 | const char *dup(const char *); 477 | const char *format(const void *p); 478 | void promoteAll(const void *newbase); 479 | void clear(); 480 | }; 481 | 482 | class LirNameMap MMGC_SUBCLASS_DECL 483 | { 484 | template 485 | class CountMap: public avmplus::SortedMap { 486 | public: 487 | CountMap(avmplus::GC*gc) : avmplus::SortedMap(gc) {} 488 | int add(Key k) { 489 | int c = 1; 490 | if (containsKey(k)) { 491 | c = 1+get(k); 492 | } 493 | put(k,c); 494 | return c; 495 | } 496 | }; 497 | CountMap lircounts; 498 | CountMap funccounts; 499 | 500 | class Entry MMGC_SUBCLASS_DECL 501 | { 502 | public: 503 | Entry(int) : name(0) {} 504 | Entry(avmplus::String *n) : name(n) {} 505 | ~Entry(); 506 | DRCWB(avmplus::String*) name; 507 | }; 508 | avmplus::SortedMap names; 509 | LabelMap *labels; 510 | void formatImm(int32_t c, char *buf); 511 | public: 512 | 513 | LirNameMap(avmplus::GC *gc, LabelMap *r) 514 | : lircounts(gc), 515 | funccounts(gc), 516 | names(gc), 517 | labels(r) 518 | {} 519 | ~LirNameMap(); 520 | 521 | void addName(LInsp i, const char *s); 522 | bool addName(LInsp i, avmplus::String *s); 523 | void copyName(LInsp i, const char *s, int suffix); 524 | const char *formatRef(LIns *ref); 525 | const char *formatIns(LInsp i); 526 | void formatGuard(LInsp i, char *buf); 527 | }; 528 | 529 | 530 | class VerboseWriter : public LirWriter 531 | { 532 | InsList code; 533 | DWB(LirNameMap*) names; 534 | public: 535 | VerboseWriter(avmplus::GC *gc, LirWriter *out, LirNameMap* names) 536 | : LirWriter(out), code(gc), names(names) 537 | {} 538 | 539 | LInsp add(LInsp i) { 540 | if (i) 541 | code.add(i); 542 | return i; 543 | } 544 | 545 | LInsp add_flush(LInsp i) { 546 | if ((i = add(i)) != 0) 547 | flush(); 548 | return i; 549 | } 550 | 551 | void flush() 552 | { 553 | int n = code.size(); 554 | if (n) { 555 | for (int i=0; i < n; i++) 556 | nj_dprintf(" %s\n",names->formatIns(code[i])); 557 | code.clear(); 558 | if (n > 1) 559 | nj_dprintf("\n"); 560 | } 561 | } 562 | 563 | LIns* insGuard(LOpcode op, LInsp cond, LIns *x) { 564 | return add_flush(out->insGuard(op,cond,x)); 565 | } 566 | 567 | LIns* insBranch(LOpcode v, LInsp condition, LInsp to) { 568 | return add_flush(out->insBranch(v, condition, to)); 569 | } 570 | 571 | LIns* ins0(LOpcode v) { 572 | if (v == LIR_label || v == LIR_start) { 573 | flush(); 574 | } 575 | return add(out->ins0(v)); 576 | } 577 | 578 | LIns* ins1(LOpcode v, LInsp a) { 579 | return isRetOpcode(v) ? add_flush(out->ins1(v, a)) : add(out->ins1(v, a)); 580 | } 581 | LIns* ins2(LOpcode v, LInsp a, LInsp b) { 582 | return v == LIR_2 ? out->ins2(v,a,b) : add(out->ins2(v, a, b)); 583 | } 584 | LIns* insCall(const CallInfo *call, LInsp args[]) { 585 | return add_flush(out->insCall(call, args)); 586 | } 587 | LIns* insParam(int32_t i, int32_t kind) { 588 | return add(out->insParam(i, kind)); 589 | } 590 | LIns* insLoad(LOpcode v, LInsp base, LInsp disp) { 591 | return add(out->insLoad(v, base, disp)); 592 | } 593 | LIns* insStorei(LInsp v, LInsp b, int32_t d) { 594 | return add(out->insStorei(v, b, d)); 595 | } 596 | LIns* insAlloc(int32_t size) { 597 | return add(out->insAlloc(size)); 598 | } 599 | LIns* insImm(int32_t imm) { 600 | return add(out->insImm(imm)); 601 | } 602 | LIns* insImmq(uint64_t imm) { 603 | return add(out->insImmq(imm)); 604 | } 605 | }; 606 | 607 | #endif 608 | 609 | class ExprFilter: public LirWriter 610 | { 611 | public: 612 | ExprFilter(LirWriter *out) : LirWriter(out) {} 613 | LIns* ins1(LOpcode v, LIns* a); 614 | LIns* ins2(LOpcode v, LIns* a, LIns* b); 615 | LIns* insGuard(LOpcode, LIns *cond, LIns *); 616 | LIns* insBranch(LOpcode, LIns *cond, LIns *target); 617 | }; 618 | 619 | // @todo, this could be replaced by a generic HashMap or HashSet, if we had one 620 | class LInsHashSet 621 | { 622 | // must be a power of 2. 623 | // don't start too small, or we'll waste time growing and rehashing. 624 | // don't start too large, will waste memory. 625 | static const uint32_t kInitialCap = 64; 626 | 627 | LInsp *m_list; // explicit WB's are used, no DWB needed. 628 | uint32_t m_used, m_cap; 629 | avmplus::GC* m_gc; 630 | 631 | static uint32_t FASTCALL hashcode(LInsp i); 632 | uint32_t FASTCALL find(LInsp name, uint32_t hash, const LInsp *list, uint32_t cap); 633 | static bool FASTCALL equals(LInsp a, LInsp b); 634 | void FASTCALL grow(); 635 | 636 | public: 637 | 638 | LInsHashSet(avmplus::GC* gc); 639 | ~LInsHashSet(); 640 | LInsp find32(int32_t a, uint32_t &i); 641 | LInsp find64(uint64_t a, uint32_t &i); 642 | LInsp find1(LOpcode v, LInsp a, uint32_t &i); 643 | LInsp find2(LOpcode v, LInsp a, LInsp b, uint32_t &i); 644 | LInsp findcall(const CallInfo *call, uint32_t argc, LInsp args[], uint32_t &i); 645 | LInsp add(LInsp i, uint32_t k); 646 | void replace(LInsp i); 647 | void clear(); 648 | 649 | static uint32_t FASTCALL hashimm(int32_t); 650 | static uint32_t FASTCALL hashimmq(uint64_t); 651 | static uint32_t FASTCALL hash1(LOpcode v, LInsp); 652 | static uint32_t FASTCALL hash2(LOpcode v, LInsp, LInsp); 653 | static uint32_t FASTCALL hashcall(const CallInfo *call, uint32_t argc, LInsp args[]); 654 | }; 655 | 656 | class CseFilter: public LirWriter 657 | { 658 | public: 659 | LInsHashSet exprs; 660 | CseFilter(LirWriter *out, avmplus::GC *gc); 661 | LIns* insImm(int32_t imm); 662 | LIns* insImmq(uint64_t q); 663 | LIns* ins0(LOpcode v); 664 | LIns* ins1(LOpcode v, LInsp); 665 | LIns* ins2(LOpcode v, LInsp, LInsp); 666 | LIns* insLoad(LOpcode v, LInsp b, LInsp d); 667 | LIns* insCall(const CallInfo *call, LInsp args[]); 668 | LIns* insGuard(LOpcode op, LInsp cond, LIns *x); 669 | }; 670 | 671 | class LirBuffer : public avmplus::GCFinalizedObject 672 | { 673 | public: 674 | DWB(Fragmento*) _frago; 675 | LirBuffer(Fragmento* frago, const CallInfo* functions); 676 | virtual ~LirBuffer(); 677 | void clear(); 678 | void rewind(); 679 | uintptr_t makeRoom(size_t szB); // make room for an instruction 680 | LInsp lastWritten(); // most recently written instruction 681 | bool outOMem() { return _noMem != 0; } 682 | 683 | debug_only (void validate() const;) 684 | verbose_only(DWB(LirNameMap*) names;) 685 | 686 | int32_t insCount(); 687 | size_t byteCount(); 688 | 689 | // stats 690 | struct 691 | { 692 | uint32_t lir; // # instructions 693 | } 694 | _stats; 695 | 696 | const CallInfo* _functions; 697 | AbiKind abi; 698 | LInsp state,param1,sp,rp; 699 | LInsp savedRegs[NumSavedRegs]; 700 | bool explicitSavedRegs; 701 | 702 | protected: 703 | Page* pageAlloc(); 704 | void moveToNewPage(uintptr_t addrOfLastLInsOnCurrentPage); 705 | 706 | PageList _pages; 707 | Page* _nextPage; // allocated in preperation of a needing to growing the buffer 708 | uintptr_t _unused; // next unused instruction slot 709 | int _noMem; // set if ran out of memory when writing to buffer 710 | }; 711 | 712 | class LirBufWriter : public LirWriter 713 | { 714 | DWB(LirBuffer*) _buf; // underlying buffer housing the instructions 715 | 716 | public: 717 | LirBufWriter(LirBuffer* buf) 718 | : LirWriter(0), _buf(buf) { 719 | _functions = buf->_functions; 720 | } 721 | 722 | // LirWriter interface 723 | LInsp insLoad(LOpcode op, LInsp base, LInsp off); 724 | LInsp insStorei(LInsp o1, LInsp o2, int32_t imm); 725 | LInsp ins0(LOpcode op); 726 | LInsp ins1(LOpcode op, LInsp o1); 727 | LInsp ins2(LOpcode op, LInsp o1, LInsp o2); 728 | LInsp insParam(int32_t i, int32_t kind); 729 | LInsp insImm(int32_t imm); 730 | LInsp insImmq(uint64_t imm); 731 | LInsp insCall(const CallInfo *call, LInsp args[]); 732 | LInsp insGuard(LOpcode op, LInsp cond, LIns *x); 733 | LInsp insBranch(LOpcode v, LInsp condition, LInsp to); 734 | LInsp insAlloc(int32_t size); 735 | LInsp insSkip(size_t); 736 | }; 737 | 738 | class LirFilter 739 | { 740 | public: 741 | LirFilter *in; 742 | LirFilter(LirFilter *in) : in(in) {} 743 | virtual ~LirFilter(){} 744 | 745 | virtual LInsp read() { 746 | return in->read(); 747 | } 748 | virtual LInsp pos() { 749 | return in->pos(); 750 | } 751 | }; 752 | 753 | // concrete 754 | class LirReader : public LirFilter 755 | { 756 | LInsp _i; // current instruction that this decoder is operating on. 757 | 758 | public: 759 | LirReader(LirBuffer* buf) : LirFilter(0), _i(buf->lastWritten()) { } 760 | LirReader(LInsp i) : LirFilter(0), _i(i) { } 761 | virtual ~LirReader() {} 762 | 763 | // LirReader i/f 764 | LInsp read(); // advance to the prior instruction 765 | LInsp pos() { 766 | return _i; 767 | } 768 | void setpos(LIns *i) { 769 | _i = i; 770 | } 771 | }; 772 | 773 | class Assembler; 774 | 775 | void compile(Assembler *assm, Fragment *frag); 776 | verbose_only(void live(avmplus::GC *gc, LirBuffer *lirbuf);) 777 | 778 | class StackFilter: public LirFilter 779 | { 780 | avmplus::GC *gc; 781 | LirBuffer *lirbuf; 782 | LInsp sp; 783 | avmplus::BitSet stk; 784 | int top; 785 | int getTop(LInsp br); 786 | public: 787 | StackFilter(LirFilter *in, avmplus::GC *gc, LirBuffer *lirbuf, LInsp sp); 788 | virtual ~StackFilter() {} 789 | LInsp read(); 790 | }; 791 | 792 | class CseReader: public LirFilter 793 | { 794 | LInsHashSet *exprs; 795 | const CallInfo *functions; 796 | public: 797 | CseReader(LirFilter *in, LInsHashSet *exprs, const CallInfo*); 798 | LInsp read(); 799 | }; 800 | 801 | // eliminate redundant loads by watching for stores & mutator calls 802 | class LoadFilter: public LirWriter 803 | { 804 | public: 805 | LInsp sp, rp; 806 | LInsHashSet exprs; 807 | void clear(LInsp p); 808 | public: 809 | LoadFilter(LirWriter *out, avmplus::GC *gc) 810 | : LirWriter(out), exprs(gc) { } 811 | 812 | LInsp ins0(LOpcode); 813 | LInsp insLoad(LOpcode, LInsp base, LInsp disp); 814 | LInsp insStorei(LInsp v, LInsp b, int32_t d); 815 | LInsp insCall(const CallInfo *call, LInsp args[]); 816 | }; 817 | } 818 | #endif // __nanojit_LIR__ 819 | -------------------------------------------------------------------------------- /LIRopcode.tbl: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * vim: set ts=8 sw=4 et tw=0 ft=C: 3 | * 4 | * ***** BEGIN LICENSE BLOCK ***** 5 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 | * 7 | * The contents of this file are subject to the Mozilla Public License Version 8 | * 1.1 (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * http://www.mozilla.org/MPL/ 11 | * 12 | * Software distributed under the License is distributed on an "AS IS" basis, 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 | * for the specific language governing rights and limitations under the 15 | * License. 16 | * 17 | * The Original Code is SpiderMonkey nanojit. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * the Mozilla Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 2008 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * Jeff Walden 26 | * 27 | * Alternatively, the contents of this file may be used under the terms of 28 | * either of the GNU General Public License Version 2 or later (the "GPL"), 29 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 | * in which case the provisions of the GPL or the LGPL are applicable instead 31 | * of those above. If you wish to allow use of your version of this file only 32 | * under the terms of either the GPL or the LGPL, and not to allow others to 33 | * use your version of this file under the terms of the MPL, indicate your 34 | * decision by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL or the LGPL. If you do not delete 36 | * the provisions above, a recipient may use your version of this file under 37 | * the terms of any one of the MPL, the GPL or the LGPL. 38 | * 39 | * ***** END LICENSE BLOCK ***** */ 40 | 41 | /* 42 | * Definitions of LIR opcodes. If you need to allocate an opcode, look 43 | * for a name of the form unused* and claim it. 44 | * 45 | * Includers must define OPDEF and OPDEF64 macros of the following forms: 46 | * 47 | * #define OPDEF(op,val,operands) ... 48 | * #define OPDEF64(op,val,operands) ... 49 | * 50 | * Selected arguments can then be used within the macro expansions. 51 | * 52 | * Field Description 53 | * op Bytecode name, token-pasted after "LIR_" to form an LOpcode 54 | * val Bytecode value, which is the LOpcode enumerator value 55 | * operands Number of operands for this instruction 56 | * 57 | * This file is best viewed with 128 columns: 58 | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 59 | */ 60 | 61 | /* op val name operands */ 62 | 63 | /* special operations (must be 0..N) */ 64 | OPDEF(start, 0, 0) 65 | OPDEF(unused1, 1, 0) 66 | OPDEF(skip, 2, 0) 67 | OPDEF(unused3, 3, 0) 68 | OPDEF(unused4, 4, 0) 69 | 70 | OPDEF(unused5, 5, 2) 71 | OPDEF(unused6, 6, 2) 72 | 73 | /* non-pure operations */ 74 | OPDEF(addp, 7, 2) 75 | OPDEF(param, 8, 0) 76 | OPDEF(unused9, 9, 2) 77 | OPDEF(ld, 10, 2) // 32-bit load 78 | OPDEF(alloc, 11, 0) // alloca some stack space 79 | OPDEF(sti, 12, 2) // 32-bit store 80 | OPDEF(ret, 13, 1) 81 | OPDEF(live, 14, 1) // extend live range of reference 82 | OPDEF(unused15, 15, 0) // indirect call 83 | OPDEF(call, 16, 0) // subroutine call returning a 32-bit value 84 | 85 | /* guards */ 86 | OPDEF(loop, 17, 0) // loop fragment 87 | OPDEF(x, 18, 0) // exit always 88 | 89 | /* branches */ 90 | OPDEF(j, 19, 0) // jump always 91 | OPDEF(jt, 20, 1) // jump true 92 | OPDEF(jf, 21, 1) // jump false 93 | OPDEF(label, 22, 0) // a jump target 94 | OPDEF(ji, 23, 2) // jump indirect 95 | 96 | /* operators */ 97 | 98 | /* 99 | * NB: Opcodes LIR_int through LIR_uge must remain continuous to aid in 100 | * common-subexpression-elimination detection code. 101 | */ 102 | 103 | OPDEF(int, 24, 0) // constant 32-bit integer 104 | OPDEF(cmov, 25, 2) // conditional move (op1=cond, op2=cond(iftrue,iffalse)) 105 | #if defined(NANOJIT_64BIT) 106 | OPDEF(callh, 26, 0) 107 | #else 108 | OPDEF(callh, 26, 1) 109 | #endif 110 | 111 | /* 112 | * feq though fge must only be used on float arguments. They return integers. 113 | * For all except feq, (op ^ 1) is the op which flips the 114 | * left and right sides of the comparison, so (lt ^ 1) == gt, or the operator 115 | * "<" is xored with 1 to get ">". Similarly, (op ^ 3) is the complement of 116 | * op, so (lt ^ 1) == ge, or the complement of the operator "<" is ">=" xored 117 | * with 3. NB: These opcodes must remain continuous so that comparison-opcode 118 | * detection works correctly. 119 | */ 120 | OPDEF(feq, 27, 2) // floating-point equality [2 float inputs] 121 | OPDEF(flt, 28, 2) // floating-point less than: arg1 < arg2 122 | OPDEF(fgt, 29, 2) // floating-point greater than: arg1 > arg2 123 | OPDEF(fle, 30, 2) // arg1 <= arg2, both floating-point 124 | OPDEF(fge, 31, 2) // arg1 >= arg2, both floating-point 125 | 126 | OPDEF(ldcb, 32, 2) // non-volatile 8-bit load 127 | OPDEF(ldcs, 33, 2) // non-volatile 16-bit load 128 | OPDEF(ldc, 34, 2) // non-volatile 32-bit load 129 | 130 | // neg through ush are all integer operations 131 | OPDEF(neg, 35, 1) // numeric negation [ 1 integer input / integer output ] 132 | OPDEF(add, 36, 2) // integer addition [ 2 operand integer intputs / integer output ] 133 | OPDEF(sub, 37, 2) // integer subtraction 134 | OPDEF(mul, 38, 2) // integer multiplication 135 | OPDEF(div, 39, 2) 136 | OPDEF(mod, 40, 1) 137 | 138 | OPDEF(and, 41, 2) 139 | OPDEF(or, 42, 2) 140 | OPDEF(xor, 43, 2) 141 | OPDEF(not, 44, 1) 142 | OPDEF(lsh, 45, 2) 143 | OPDEF(rsh, 46, 2) // >> 144 | OPDEF(ush, 47, 2) // >>> 145 | 146 | // conditional guards, op^1 to complement. Only things that are 147 | // isCond() can be passed to these. 148 | OPDEF(xt, 48, 1) // exit if true 0x30 0011 0000 149 | OPDEF(xf, 49, 1) // exit if false 0x31 0011 0001 150 | 151 | // qlo and qhi take a single quad argument and return its low and high 152 | // 32 bits respectively as 32-bit integers. 153 | OPDEF(qlo, 50, 1) 154 | OPDEF(qhi, 51, 1) 155 | 156 | OPDEF(unused52, 52, 0) 157 | 158 | OPDEF(ov, 53, 1) 159 | OPDEF(cs, 54, 1) 160 | 161 | // Integer (all sizes) relational operators. (op ^ 1) is the op which flips the 162 | // left and right sides of the comparison, so (lt ^ 1) == gt, or the operator 163 | // "<" is xored with 1 to get ">". Similarly, (op ^ 3) is the complement of 164 | // op, so (lt ^ 1) == ge, or the complement of the operator "<" is ">=" xored 165 | // with 3. 'u' prefix indicates the unsigned integer variant. 166 | // NB: These opcodes must remain continuous so that comparison-opcode detection 167 | // works correctly. 168 | OPDEF(eq, 55, 2) // integer equality 169 | OPDEF(lt, 56, 2) // 0x38 0011 1000 170 | OPDEF(gt, 57, 2) // 0x39 0011 1001 171 | OPDEF(le, 58, 2) // 0x3A 0011 1010 172 | OPDEF(ge, 59, 2) // 0x3B 0011 1011 173 | OPDEF(ult, 60, 2) // 0x3C 0011 1100 174 | OPDEF(ugt, 61, 2) // 0x3D 0011 1101 175 | OPDEF(ule, 62, 2) // 0x3E 0011 1110 176 | OPDEF(uge, 63, 2) // 0x3F 0011 1111 177 | 178 | OPDEF64(2, 0, 2) // wraps a pair of refs 179 | OPDEF64(file, 1, 2) 180 | OPDEF64(line, 2, 2) 181 | OPDEF64(xbarrier, 3, 1) // memory barrier (dummy guard) 182 | OPDEF64(xtbl, 4, 1) // exit via indirect jump 183 | 184 | OPDEF64(unused5_64, 5, 2) 185 | OPDEF64(unused6_64, 6, 2) 186 | OPDEF64(unused7_64, 7, 2) 187 | OPDEF64(unused8_64, 8, 2) 188 | 189 | OPDEF64(unused9_64, 9, 2) 190 | OPDEF64(ldq, LIR_ld, 2) // quad load 191 | 192 | OPDEF64(unused11_64, 11, 2) 193 | 194 | OPDEF64(stqi, LIR_sti, 2) // quad store 195 | OPDEF64(fret, LIR_ret, 1) 196 | 197 | OPDEF64(unused14_64, 14, 2) 198 | OPDEF64(unused15_64, 15, 2) 199 | 200 | OPDEF64(fcall, LIR_call, 0) // subroutine call returning quad 201 | 202 | OPDEF64(unused17_64, 17, 2) 203 | OPDEF64(unused18_64, 18, 2) 204 | OPDEF64(unused19_64, 19, 2) 205 | OPDEF64(unused20_64, 20, 2) 206 | OPDEF64(unused21_64, 21, 2) 207 | OPDEF64(unused22_64, 22, 2) 208 | OPDEF64(unused23_64, 23, 2) 209 | 210 | // We strip of the 64bit flag and compare that the opcode is between LIR_int 211 | // and LIR_uge to decide whether we can CSE the opcode. All opcodes below 212 | // this marker are subject to CSE. 213 | 214 | OPDEF64(quad, LIR_int, 0) // quad constant value 215 | OPDEF64(qcmov, LIR_cmov, 2) 216 | OPDEF64(unused26_64, 26, 2) 217 | 218 | OPDEF64(unused27_64, 27, 2) 219 | OPDEF64(unused28_64, 28, 2) 220 | OPDEF64(unused29_64, 29, 2) 221 | OPDEF64(unused30_64, 30, 2) 222 | OPDEF64(unused31_64, 31, 2) 223 | OPDEF64(unused32_64, 32, 2) 224 | OPDEF64(unused33_64, 33, 2) 225 | 226 | OPDEF64(ldqc, LIR_ldc, 2) 227 | 228 | /* floating-point arithmetic operations */ 229 | OPDEF64(fneg, LIR_neg, 1) 230 | OPDEF64(fadd, LIR_add, 2) 231 | OPDEF64(fsub, LIR_sub, 2) 232 | OPDEF64(fmul, LIR_mul, 2) 233 | OPDEF64(fdiv, LIR_div, 2) 234 | OPDEF64(fmod, LIR_mod, 2) 235 | 236 | OPDEF64(qiand, 41, 2) 237 | OPDEF64(qiadd, 42, 2) 238 | OPDEF64(qior, 43, 2) 239 | OPDEF64(qilsh, 44, 2) 240 | OPDEF64(qjoin, 45, 2) // 1st arg is low 32 bits, 2nd arg is high 32 bits 241 | 242 | OPDEF64(i2f, 46, 1) // convert an integer to a float 243 | OPDEF64(u2f, 47, 1) // convert an unsigned integer to a float 244 | 245 | OPDEF64(unused48_64, 48, 2) 246 | OPDEF64(unused49_64, 49, 2) 247 | OPDEF64(unused50_64, 50, 2) 248 | OPDEF64(unused51_64, 51, 2) 249 | OPDEF64(unused52_64, 52, 2) 250 | OPDEF64(unused53_64, 53, 2) 251 | OPDEF64(unused54_64, 54, 2) 252 | OPDEF64(unused55_64, 55, 2) 253 | OPDEF64(unused56_64, 56, 2) 254 | OPDEF64(unused57_64, 57, 2) 255 | OPDEF64(unused58_64, 58, 2) 256 | OPDEF64(unused59_64, 59, 2) 257 | OPDEF64(unused60_64, 60, 2) 258 | OPDEF64(unused61_64, 61, 2) 259 | OPDEF64(unused62_64, 62, 2) 260 | OPDEF64(unused63_64, 63, 2) 261 | -------------------------------------------------------------------------------- /Native.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | 40 | #ifndef __nanojit_Native__ 41 | #define __nanojit_Native__ 42 | 43 | 44 | #ifdef NANOJIT_IA32 45 | #include "Nativei386.h" 46 | #elif defined(NANOJIT_ARM) 47 | #include "NativeARM.h" 48 | #elif defined(NANOJIT_PPC) 49 | #include "NativePpc.h" 50 | #elif defined(NANOJIT_SPARC) 51 | #include "NativeSparc.h" 52 | #elif defined(NANOJIT_AMD64) 53 | #include "NativeAMD64.h" 54 | #else 55 | #error "unknown nanojit architecture" 56 | #endif 57 | 58 | namespace nanojit { 59 | const size_t NJ_PAGE_SIZE = 1 << NJ_LOG2_PAGE_SIZE; 60 | 61 | class Fragment; 62 | struct SideExit; 63 | struct SwitchInfo; 64 | 65 | struct GuardRecord 66 | { 67 | void* jmp; 68 | GuardRecord* next; 69 | SideExit* exit; 70 | }; 71 | 72 | struct SideExit 73 | { 74 | GuardRecord* guards; 75 | Fragment* from; 76 | Fragment* target; 77 | SwitchInfo* switchInfo; 78 | 79 | void addGuard(GuardRecord* gr) 80 | { 81 | NanoAssert(gr->next == NULL); 82 | NanoAssert(guards != gr); 83 | gr->next = guards; 84 | guards = gr; 85 | } 86 | }; 87 | } 88 | 89 | #ifdef NJ_STACK_GROWTH_UP 90 | #define stack_direction(n) n 91 | #else 92 | #define stack_direction(n) -n 93 | #endif 94 | 95 | #define isSPorFP(r) ( (r)==SP || (r)==FP ) 96 | 97 | #if defined(_MSC_VER) && _MSC_VER < 1400 98 | static void asm_output(const char *f, ...) {} 99 | #define gpn(r) regNames[(r)] 100 | #define fpn(r) regNames[(r)] 101 | #elif defined(NJ_VERBOSE) 102 | #define asm_output(...) do {\ 103 | counter_increment(native);\ 104 | if (verbose_enabled()) {\ 105 | outline[0]='\0';\ 106 | if (outputAddr) sprintf(outline, " %10p ",_nIns);\ 107 | else sprintf(outline, " ");\ 108 | sprintf(&outline[14], ##__VA_ARGS__);\ 109 | Assembler::outputAlign(outline, 45);\ 110 | RegAlloc::formatRegisters(_allocator, outline, _thisfrag);\ 111 | Assembler::output_asm(outline);\ 112 | outputAddr=false; /* set =true if you like to see addresses for each native instruction */ \ 113 | }\ 114 | } while (0) /* no semi */ 115 | #define gpn(r) regNames[(r)] 116 | #define fpn(r) regNames[(r)] 117 | #else 118 | #define asm_output(...) 119 | #define gpn(r) 120 | #define fpn(r) 121 | #endif /* NJ_VERBOSE */ 122 | 123 | #endif // __nanojit_Native__ 124 | -------------------------------------------------------------------------------- /NativeSparc.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * leon.sha@sun.com 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | 41 | #ifndef __nanojit_NativeSparc__ 42 | #define __nanojit_NativeSparc__ 43 | 44 | 45 | #define count_instr() 46 | #define count_ret() 47 | #define count_push() 48 | #define count_pop() 49 | #define count_st() 50 | #define count_stq() 51 | #define count_ld() 52 | #define count_ldq() 53 | #define count_call() 54 | #define count_calli() 55 | #define count_prolog() 56 | #define count_alu() 57 | #define count_mov() 58 | #define count_fpu() 59 | #define count_jmp() 60 | #define count_jcc() 61 | #define count_fpuld() 62 | #define count_aluld() 63 | #define count_alust() 64 | #define count_pushld() 65 | #define count_imt() 66 | 67 | namespace nanojit 68 | { 69 | #ifdef MMGC_SPARC 70 | const int NJ_LOG2_PAGE_SIZE = 12; // 4K 71 | #else 72 | const int NJ_LOG2_PAGE_SIZE = 13; // 8K 73 | #endif 74 | const int NJ_MAX_REGISTERS = 30; // L0 - L7, I0 - I5, F2 - F14 75 | const int NJ_STACK_OFFSET = 0; 76 | 77 | const int LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect 78 | 79 | #define NJ_MAX_STACK_ENTRY 256 80 | #define NJ_MAX_PARAMETERS 1 81 | 82 | const int NJ_ALIGN_STACK = 16; 83 | 84 | typedef uint32_t NIns; 85 | 86 | // These are used as register numbers in various parts of the code 87 | typedef enum 88 | { 89 | G0 = 0, 90 | G1 = 1, 91 | G2 = 2, 92 | G3 = 3, 93 | G4 = 4, 94 | G5 = 5, // Reserved for system 95 | G6 = 6, // Reserved for system 96 | G7 = 7, // Reserved for system 97 | 98 | O0 = 8, 99 | O1 = 9, 100 | O2 = 10, 101 | O3 = 11, 102 | O4 = 12, 103 | O5 = 13, 104 | O6 = 14, // SP 105 | O7 = 15, // Not used. 106 | 107 | L0 = 16, 108 | L1 = 17, 109 | L2 = 18, 110 | L3 = 19, 111 | L4 = 20, 112 | L5 = 21, 113 | L6 = 22, 114 | L7 = 23, 115 | 116 | I0 = 24, 117 | I1 = 25, 118 | I2 = 26, 119 | I3 = 27, 120 | I4 = 28, 121 | I5 = 29, 122 | I6 = 30, // FP 123 | I7 = 31, // Not used 124 | 125 | SP = O6, 126 | FP = I6, 127 | 128 | F0 = 0, 129 | F1 = 1, 130 | F2 = 2, 131 | F3 = 3, 132 | F4 = 4, 133 | F5 = 5, 134 | F6 = 6, 135 | F7 = 7, 136 | F8 = 8, 137 | F9 = 9, 138 | F10 = 10, 139 | F11 = 11, 140 | F12 = 12, 141 | F13 = 13, 142 | F14 = 14, 143 | F15 = 15, 144 | F16 = 16, 145 | F17 = 17, 146 | F18 = 18, 147 | F19 = 19, 148 | F20 = 20, 149 | F21 = 21, 150 | F22 = 22, 151 | F23 = 23, 152 | F24 = 24, 153 | F25 = 25, 154 | F26 = 26, 155 | F27 = 27, 156 | F28 = 28, 157 | F29 = 29, 158 | F30 = 30, 159 | F31 = 31, 160 | 161 | // helpers 162 | FRAME_PTR = G4, 163 | 164 | FirstReg = 0, 165 | LastReg = 29, 166 | UnknownReg = 30 167 | } 168 | Register; 169 | 170 | // We only use 32 registers to be managed. 171 | // So we choose some of them. 172 | // And other unmanaged registers we can use them directly. 173 | // The registers that can be used directly are G0-G4, L0, L2, L4, L6 174 | // SP, FP, F8-F12, F24-F28 175 | typedef int RegisterMask; 176 | #define _rmask_(r) (1<<(r)) 177 | 178 | static const int NumSavedRegs = 6; 179 | static const RegisterMask SavedRegs = 1<_address) - ((int)_nIns) + 4; \ 214 | int i = 0x40000000 | ((offset >> 2) & 0x3FFFFFFF); \ 215 | IMM32(i); \ 216 | verbose_only(asm_output("call %s",(c->_name));) \ 217 | } while (0) 218 | 219 | #define Format_2_1(rd, op2, imm22) do { \ 220 | int i = rd << 25 | op2 << 22 | (imm22 & 0x3FFFFF); \ 221 | IMM32(i); \ 222 | } while (0) 223 | 224 | #define Format_2_2(a, cond, op2, disp22) \ 225 | Format_2_1((a & 0x1) << 4 | (cond & 0xF), op2, disp22) 226 | 227 | #define Format_2_3(a, cond, op2, cc1, cc0, p, disp19) \ 228 | Format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | (disp19 & 0x7FFFF)) 229 | 230 | #define Format_2_4(a, rcond, op2, d16hi, p, rs1, d16lo) \ 231 | Format_2_2(a, (rcond & 0x7), op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | (d16lo & 0x3FFF)) 232 | 233 | #define Format_3(op1, rd, op3, bits19) do { \ 234 | int i = op1 << 30 | rd << 25 | op3 << 19 | (bits19 & 0x7FFFF); \ 235 | IMM32(i); \ 236 | } while (0) 237 | 238 | #define Format_3_1(op1, rd, op3, rs1, bit8, rs2) \ 239 | Format_3(op1, rd, op3, rs1 << 14 | (bit8 & 0xFF) << 5 | rs2) 240 | 241 | #define Format_3_1I(op1, rd, op3, rs1, simm13) \ 242 | Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (simm13 & 0x1FFF)) 243 | 244 | #define Format_3_2(op1, rd, op3, rs1, rcond, rs2) \ 245 | Format_3(op1, rd, op3, rs1 << 14 | (rcond & 0x3) << 10 | rs2) 246 | 247 | #define Format_3_2I(op1, rd, op3, rs1, rcond, simm10) \ 248 | Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (rcond & 0x3) << 10 | (simm10 & 0x1FFF)) 249 | 250 | #define Format_3_3(op1, rd, op3, rs1, cmask, mmask) \ 251 | Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (cmask & 0x7) << 5 | (mmask & 0xF)) 252 | 253 | #define Format_3_4(op1, rd, op3, bits19) \ 254 | Format_3(op1, rd, op3, bits19) 255 | 256 | #define Format_3_5(op1, rd, op3, rs1, x, rs2) \ 257 | Format_3(op1, rd, op3, rs1 << 14 | (x & 0x1) << 12 | rs2) 258 | 259 | #define Format_3_6(op1, rd, op3, rs1, shcnt32) \ 260 | Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (shcnt32 & 0x3F)) 261 | 262 | #define Format_3_7(op1, rd, op3, rs1, shcnt64) \ 263 | Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x7F)) 264 | 265 | #define Format_3_8(op1, rd, op3, rs1, bits9, rs2) \ 266 | Format_3(op1, rd, op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2) 267 | 268 | #define Format_3_9(op1, cc1, cc0, op3, rs1, bits9, rs2) \ 269 | Format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2) 270 | 271 | #define Format_4_1(rd, op3, rs1, cc1, cc0, rs2) \ 272 | Format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2) 273 | 274 | #define Format_4_1I(rd, op3, rs1, cc1, cc0, simm11) \ 275 | Format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | (simm11 & 0x7FF)) 276 | 277 | #define Format_4_2(rd, op3, cc2, cond, cc1, cc0, rs2) \ 278 | Format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2) 279 | 280 | #define Format_4_2I(rd, op3, cc2, cond, cc1, cc0, simm11) \ 281 | Format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF)) 282 | 283 | #define Format_4_3(rd, op3, rs1, cc1, cc0, swap_trap) \ 284 | Format_3(2, rd, op3, rs1 << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (swap_trap & 0x7F)) 285 | 286 | #define Format_4_4(rd, op3, rs1, rcond, opf_low, rs2) \ 287 | Format_3(2, rd, op3, rs1 << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | rs2) 288 | 289 | #define Format_4_5(rd, op3, cond, opf_cc, opf_low, rs2) \ 290 | Format_3(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | rs2) 291 | 292 | #define ADDCC(rs1, rs2, rd) \ 293 | do { \ 294 | asm_output("addcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 295 | Format_3_1(2, rd, 0x10, rs1, 0, rs2); \ 296 | } while (0) 297 | 298 | #define ADD(rs1, rs2, rd) \ 299 | do { \ 300 | asm_output("add %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 301 | Format_3_1(2, rd, 0, rs1, 0, rs2); \ 302 | } while (0) 303 | 304 | #define AND(rs1, rs2, rd) \ 305 | do { \ 306 | asm_output("and %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 307 | Format_3_1(2, rd, 0x1, rs1, 0, rs2); \ 308 | } while (0) 309 | 310 | #define BA(a, dsp22) \ 311 | do { \ 312 | asm_output("ba %p", _nIns + dsp22 - 1); \ 313 | Format_2_2(a, 0x8, 0x2, dsp22); \ 314 | } while (0) 315 | 316 | #define BE(a, dsp22) \ 317 | do { \ 318 | asm_output("be %p", _nIns + dsp22 - 1); \ 319 | Format_2_2(a, 0x1, 0x2, dsp22); \ 320 | } while (0) 321 | 322 | #define BG(a, dsp22) \ 323 | do { \ 324 | asm_output("bg %p", _nIns + dsp22 - 1); \ 325 | Format_2_2(a, 0xA, 0x2, dsp22); \ 326 | } while (0) 327 | 328 | #define BGU(a, dsp22) \ 329 | do { \ 330 | asm_output("bgu %p", _nIns + dsp22 - 1); \ 331 | Format_2_2(a, 0xC, 0x2, dsp22); \ 332 | } while (0) 333 | 334 | #define BGE(a, dsp22) \ 335 | do { \ 336 | asm_output("bge %p", _nIns + dsp22 - 1); \ 337 | Format_2_2(a, 0xB, 0x2, dsp22); \ 338 | } while (0) 339 | 340 | #define BL(a, dsp22) \ 341 | do { \ 342 | asm_output("bl %p", _nIns + dsp22 - 1); \ 343 | Format_2_2(a, 0x3, 0x2, dsp22); \ 344 | } while (0) 345 | 346 | #define BLE(a, dsp22) \ 347 | do { \ 348 | asm_output("ble %p", _nIns + dsp22 - 1); \ 349 | Format_2_2(a, 0x2, 0x2, dsp22); \ 350 | } while (0) 351 | 352 | #define BLEU(a, dsp22) \ 353 | do { \ 354 | asm_output("bleu %p", _nIns + dsp22 - 1); \ 355 | Format_2_2(a, 0x4, 0x2, dsp22); \ 356 | } while (0) 357 | 358 | #define BCC(a, dsp22) \ 359 | do { \ 360 | asm_output("bcc %p", _nIns + dsp22 - 1); \ 361 | Format_2_2(a, 0xd, 0x2, dsp22); \ 362 | } while (0) 363 | 364 | #define BCS(a, dsp22) \ 365 | do { \ 366 | asm_output("bcs %p", _nIns + dsp22 - 1); \ 367 | Format_2_2(a, 0x5, 0x2, dsp22); \ 368 | } while (0) 369 | 370 | #define BVC(a, dsp22) \ 371 | do { \ 372 | asm_output("bvc %p", _nIns + dsp22 - 1); \ 373 | Format_2_2(a, 0xf, 0x2, dsp22); \ 374 | } while (0) 375 | 376 | #define BVS(a, dsp22) \ 377 | do { \ 378 | asm_output("bvc %p", _nIns + dsp22 - 1); \ 379 | Format_2_2(a, 0x7, 0x2, dsp22); \ 380 | } while (0) 381 | 382 | #define BNE(a, dsp22) \ 383 | do { \ 384 | asm_output("bne %p", _nIns + dsp22 - 1); \ 385 | Format_2_2(a, 0x9, 0x2, dsp22); \ 386 | } while (0) 387 | 388 | #define FABSS(rs2, rd) \ 389 | do { \ 390 | asm_output("fabs %s, %s", gpn(rs2+32), gpn(rd+32)); \ 391 | Format_3_8(2, rd, 0x34, 0, 0x9, rs2); \ 392 | } while (0) 393 | 394 | #define FADDD(rs1, rs2, rd) \ 395 | do { \ 396 | asm_output("faddd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ 397 | Format_3_8(2, rd, 0x34, rs1, 0x42, rs2); \ 398 | } while (0) 399 | 400 | #define FBE(a, dsp22) \ 401 | do { \ 402 | asm_output("fbe %p", _nIns + dsp22 - 1); \ 403 | Format_2_2(a, 0x9, 0x6, dsp22); \ 404 | } while(0) 405 | 406 | #define FBNE(a, dsp22) \ 407 | do { \ 408 | asm_output("fbne %p", _nIns + dsp22 - 1); \ 409 | Format_2_2(a, 0x1, 0x6, dsp22); \ 410 | } while(0) 411 | 412 | #define FBUE(a, dsp22) \ 413 | do { \ 414 | asm_output("fbue %p", _nIns + dsp22 - 1); \ 415 | Format_2_2(a, 0xA, 0x6, dsp22); \ 416 | } while(0) 417 | 418 | #define FBG(a, dsp22) \ 419 | do { \ 420 | asm_output("fng %p", _nIns + dsp22 - 1); \ 421 | Format_2_2(a, 0x6, 0x6, dsp22); \ 422 | } while(0) 423 | 424 | #define FBUG(a, dsp22) \ 425 | do { \ 426 | asm_output("fbug %p", _nIns + dsp22 - 1); \ 427 | Format_2_2(a, 0x5, 0x6, dsp22); \ 428 | } while(0) 429 | 430 | #define FBGE(a, dsp22) \ 431 | do { \ 432 | asm_output("fbge %p", _nIns + dsp22 - 1); \ 433 | Format_2_2(a, 0xB, 0x6, dsp22); \ 434 | } while(0) 435 | 436 | #define FBUGE(a, dsp22) \ 437 | do { \ 438 | asm_output("fbuge %p", _nIns + dsp22 - 1); \ 439 | Format_2_2(a, 0xC, 0x6, dsp22); \ 440 | } while(0) 441 | 442 | #define FBL(a, dsp22) \ 443 | do { \ 444 | asm_output("fbl %p", _nIns + dsp22 - 1); \ 445 | Format_2_2(a, 0x4, 0x6, dsp22); \ 446 | } while(0) 447 | 448 | #define FBLE(a, dsp22) \ 449 | do { \ 450 | asm_output("fble %p", _nIns + dsp22 - 1); \ 451 | Format_2_2(a, 0xD, 0x6, dsp22); \ 452 | } while(0) 453 | 454 | #define FCMPD(rs1, rs2) \ 455 | do { \ 456 | asm_output("fcmpd %s, %s", gpn(rs1+32), gpn(rs2+32)); \ 457 | Format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2); \ 458 | } while (0) 459 | 460 | #define FSUBD(rs1, rs2, rd) \ 461 | do { \ 462 | asm_output("fsubd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ 463 | Format_3_8(2, rd, 0x34, rs1, 0x46, rs2); \ 464 | } while (0) 465 | 466 | #define FMULD(rs1, rs2, rd) \ 467 | do { \ 468 | asm_output("fmuld %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ 469 | Format_3_8(2, rd, 0x34, rs1, 0x4a, rs2); \ 470 | } while (0) 471 | 472 | #define FDIVD(rs1, rs2, rd) \ 473 | do { \ 474 | asm_output("fdivd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ 475 | Format_3_8(2, rd, 0x34, rs1, 0x4e, rs2); \ 476 | } while (0) 477 | 478 | #define FMOVD(rs2, rd) \ 479 | do { \ 480 | asm_output("fmovd %s, %s", gpn(rs2+32), gpn(rd+32)); \ 481 | Format_3_8(2, rd, 0x34, 0, 0x2, rs2); \ 482 | } while (0) 483 | 484 | #define FNEGD(rs2, rd) \ 485 | do { \ 486 | asm_output("fnegd %s, %s", gpn(rs2+32), gpn(rd+32)); \ 487 | Format_3_8(2, rd, 0x34, 0, 0x6, rs2); \ 488 | } while (0) 489 | 490 | #define FITOD(rs2, rd) \ 491 | do { \ 492 | asm_output("fitod %s, %s", gpn(rs2+32), gpn(rd+32)); \ 493 | Format_3_8(2, rd, 0x34, 0, 0xc8, rs2); \ 494 | } while (0) 495 | 496 | #define JMPL(rs1, rs2, rd) \ 497 | do { \ 498 | asm_output("jmpl [%s + %s]", gpn(rs1), gpn(rs2)); \ 499 | Format_3_1(2, rd, 0x38, rs1, 0, rs2); \ 500 | } while (0) 501 | 502 | #define JMPLI(rs1, simm13, rd) \ 503 | do { \ 504 | asm_output("jmpl [%s + %d]", gpn(rs1), simm13); \ 505 | Format_3_1I(2, rd, 0x38, rs1, simm13); \ 506 | } while (0) 507 | 508 | #define LDF(rs1, rs2, rd) \ 509 | do { \ 510 | asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd+32)); \ 511 | Format_3_1(3, rd, 0x20, rs1, 0, rs2); \ 512 | } while (0) 513 | 514 | #define LDFI(rs1, simm13, rd) \ 515 | do { \ 516 | asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd+32)); \ 517 | Format_3_1I(3, rd, 0x20, rs1, simm13); \ 518 | } while (0) 519 | 520 | #define LDUB(rs1, rs2, rd) \ 521 | do { \ 522 | asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 523 | Format_3_1(3, rd, 0x1, rs1, 0, rs2); \ 524 | } while (0) 525 | 526 | #define LDUBI(rs1, simm13, rd) \ 527 | do { \ 528 | asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ 529 | Format_3_1I(3, rd, 0x1, rs1, simm13); \ 530 | } while (0) 531 | 532 | #define LDUH(rs1, rs2, rd) \ 533 | do { \ 534 | asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 535 | Format_3_1(3, rd, 0x2, rs1, 0, rs2); \ 536 | } while (0) 537 | 538 | #define LDUHI(rs1, simm13, rd) \ 539 | do { \ 540 | asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ 541 | Format_3_1I(3, rd, 0x2, rs1, simm13); \ 542 | } while (0) 543 | 544 | #define LDSW(rs1, rs2, rd) \ 545 | do { \ 546 | asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 547 | Format_3_1(3, rd, 0x8, rs1, 0, rs2); \ 548 | } while (0) 549 | 550 | #define LDSWI(rs1, simm13, rd) \ 551 | do { \ 552 | asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ 553 | Format_3_1I(3, rd, 0x8, rs1, simm13); \ 554 | } while (0) 555 | 556 | #define MOVE(rs, cc2, cc1, cc0, rd) \ 557 | do { \ 558 | asm_output("move %s, %s", gpn(rs), gpn(rd)); \ 559 | Format_4_2(rd, 0x2c, cc2, 1, cc1, cc0, rs); \ 560 | } while (0) 561 | 562 | #define MOVNE(rs, cc2, cc1, cc0, rd) \ 563 | do { \ 564 | asm_output("movne %s, %s", gpn(rs), gpn(rd)); \ 565 | Format_4_2(rd, 0x2c, cc2, 9, cc1, cc0, rs); \ 566 | } while (0) 567 | 568 | #define MOVL(rs, cc2, cc1, cc0, rd) \ 569 | do { \ 570 | asm_output("movl %s, %s", gpn(rs), gpn(rd)); \ 571 | Format_4_2(rd, 0x2c, cc2, 3, cc1, cc0, rs); \ 572 | } while (0) 573 | 574 | #define MOVLE(rs, cc2, cc1, cc0, rd) \ 575 | do { \ 576 | asm_output("movle %s, %s", gpn(rs), gpn(rd)); \ 577 | Format_4_2(rd, 0x2c, cc2, 2, cc1, cc0, rs); \ 578 | } while (0) 579 | 580 | #define MOVG(rs, cc2, cc1, cc0, rd) \ 581 | do { \ 582 | asm_output("movg %s, %s", gpn(rs), gpn(rd)); \ 583 | Format_4_2(rd, 0x2c, cc2, 0xa, cc1, cc0, rs); \ 584 | } while (0) 585 | 586 | #define MOVGE(rs, cc2, cc1, cc0, rd) \ 587 | do { \ 588 | asm_output("movge %s, %s", gpn(rs), gpn(rd)); \ 589 | Format_4_2(rd, 0x2c, cc2, 0xb, cc1, cc0, rs); \ 590 | } while (0) 591 | 592 | #define MOVCS(rs, cc2, cc1, cc0, rd) \ 593 | do { \ 594 | asm_output("movcs %s, %s", gpn(rs), gpn(rd)); \ 595 | Format_4_2(rd, 0x2c, cc2, 5, cc1, cc0, rs); \ 596 | } while (0) 597 | 598 | #define MOVLEU(rs, cc2, cc1, cc0, rd) \ 599 | do { \ 600 | asm_output("movleu %s, %s", gpn(rs), gpn(rd)); \ 601 | Format_4_2(rd, 0x2c, cc2, 4, cc1, cc0, rs); \ 602 | } while (0) 603 | 604 | #define MOVGU(rs, cc2, cc1, cc0, rd) \ 605 | do { \ 606 | asm_output("movgu %s, %s", gpn(rs), gpn(rd)); \ 607 | Format_4_2(rd, 0x2c, cc2, 0xc, cc1, cc0, rs); \ 608 | } while (0) 609 | 610 | #define MOVCC(rs, cc2, cc1, cc0, rd) \ 611 | do { \ 612 | asm_output("movcc %s, %s", gpn(rs), gpn(rd)); \ 613 | Format_4_2(rd, 0x2c, cc2, 0xd, cc1, cc0, rs); \ 614 | } while (0) 615 | 616 | #define MOVVC(rs, cc2, cc1, cc0, rd) \ 617 | do { \ 618 | asm_output("movvc %s, %s", gpn(rs), gpn(rd)); \ 619 | Format_4_2(rd, 0x2c, cc2, 0xf, cc1, cc0, rs); \ 620 | } while (0) 621 | 622 | #define MOVEI(simm11, cc2, cc1, cc0, rd) \ 623 | do { \ 624 | asm_output("move %d, %s", simm11, gpn(rd)); \ 625 | Format_4_2I(rd, 0x2c, cc2, 1, cc1, cc0, simm11); \ 626 | } while (0) 627 | 628 | #define MOVFEI(simm11, cc2, cc1, cc0, rd) \ 629 | do { \ 630 | asm_output("move %d, %s", simm11, gpn(rd)); \ 631 | Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ 632 | } while (0) 633 | 634 | #define MOVNEI(simm11, cc2, cc1, cc0, rd) \ 635 | do { \ 636 | asm_output("move %d, %s", simm11, gpn(rd)); \ 637 | Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ 638 | } while (0) 639 | 640 | #define MOVLI(simm11, cc2, cc1, cc0, rd) \ 641 | do { \ 642 | asm_output("move %d, %s", simm11, gpn(rd)); \ 643 | Format_4_2I(rd, 0x2c, cc2, 3, cc1, cc0, simm11); \ 644 | } while (0) 645 | 646 | #define MOVFLI(simm11, cc2, cc1, cc0, rd) \ 647 | do { \ 648 | asm_output("move %d, %s", simm11, gpn(rd)); \ 649 | Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ 650 | } while (0) 651 | 652 | #define MOVLEI(simm11, cc2, cc1, cc0, rd) \ 653 | do { \ 654 | asm_output("movle %d, %s", simm11, gpn(rd)); \ 655 | Format_4_2I(rd, 0x2c, cc2, 2, cc1, cc0, simm11); \ 656 | } while (0) 657 | 658 | #define MOVFLEI(simm11, cc2, cc1, cc0, rd) \ 659 | do { \ 660 | asm_output("movle %d, %s", simm11, gpn(rd)); \ 661 | Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ 662 | } while (0) 663 | 664 | #define MOVGI(simm11, cc2, cc1, cc0, rd) \ 665 | do { \ 666 | asm_output("movg %d, %s", simm11, gpn(rd)); \ 667 | Format_4_2I(rd, 0x2c, cc2, 0xa, cc1, cc0, simm11); \ 668 | } while (0) 669 | 670 | #define MOVFGI(simm11, cc2, cc1, cc0, rd) \ 671 | do { \ 672 | asm_output("movg %d, %s", simm11, gpn(rd)); \ 673 | Format_4_2I(rd, 0x2c, cc2, 6, cc1, cc0, simm11); \ 674 | } while (0) 675 | 676 | #define MOVGEI(simm11, cc2, cc1, cc0, rd) \ 677 | do { \ 678 | asm_output("movge %d, %s", simm11, gpn(rd)); \ 679 | Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ 680 | } while (0) 681 | 682 | #define MOVFGEI(simm11, cc2, cc1, cc0, rd) \ 683 | do { \ 684 | asm_output("movge %d, %s", simm11, gpn(rd)); \ 685 | Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ 686 | } while (0) 687 | 688 | #define MOVCSI(simm11, cc2, cc1, cc0, rd) \ 689 | do { \ 690 | asm_output("movcs %d, %s", simm11, gpn(rd)); \ 691 | Format_4_2I(rd, 0x2c, cc2, 5, cc1, cc0, simm11); \ 692 | } while (0) 693 | 694 | #define MOVLEUI(simm11, cc2, cc1, cc0, rd) \ 695 | do { \ 696 | asm_output("movleu %d, %s", simm11, gpn(rd)); \ 697 | Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ 698 | } while (0) 699 | 700 | #define MOVGUI(simm11, cc2, cc1, cc0, rd) \ 701 | do { \ 702 | asm_output("movgu %d, %s", simm11, gpn(rd)); \ 703 | Format_4_2I(rd, 0x2c, cc2, 0xc, cc1, cc0, simm11); \ 704 | } while (0) 705 | 706 | #define MOVCCI(simm11, cc2, cc1, cc0, rd) \ 707 | do { \ 708 | asm_output("movcc %d, %s", simm11, gpn(rd)); \ 709 | Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ 710 | } while (0) 711 | 712 | #define MOVVSI(simm11, cc2, cc1, cc0, rd) \ 713 | do { \ 714 | asm_output("movvs %d, %s", simm11, gpn(rd)); \ 715 | Format_4_2I(rd, 0x2c, cc2, 7, cc1, cc0, simm11); \ 716 | } while (0) 717 | 718 | #define MULX(rs1, rs2, rd) \ 719 | do { \ 720 | asm_output("mul %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 721 | Format_3_1(2, rd, 0x9, rs1, 0, rs2); \ 722 | } while (0) 723 | 724 | #define NOP() \ 725 | do { \ 726 | asm_output("nop"); \ 727 | Format_2_1(0, 0x4, 0); \ 728 | } while (0) 729 | 730 | #define ORI(rs1, simm13, rd) \ 731 | do { \ 732 | asm_output("or %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ 733 | Format_3_1I(2, rd, 0x2, rs1, simm13); \ 734 | } while (0) 735 | 736 | #define OR(rs1, rs2, rd) \ 737 | do { \ 738 | asm_output("or %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 739 | Format_3_1(2, rd, 0x2, rs1, 0, rs2); \ 740 | } while (0) 741 | 742 | #define ORN(rs1, rs2, rd) \ 743 | do { \ 744 | asm_output("orn %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 745 | Format_3_1(2, rd, 0x6, rs1, 0, rs2); \ 746 | } while (0) 747 | 748 | #define ANDCC(rs1, rs2, rd) \ 749 | do { \ 750 | asm_output("andcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 751 | Format_3_1(2, rd, 0x11, rs1, 0, rs2); \ 752 | } while (0) 753 | 754 | #define RESTORE(rs1, rs2, rd) \ 755 | do { \ 756 | asm_output("restore"); \ 757 | Format_3_1(2, rd, 0x3D, rs1, 0, rs2); \ 758 | } while (0) 759 | 760 | #define SAVEI(rs1, simm13, rd) \ 761 | do { \ 762 | asm_output("save %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ 763 | Format_3_1I(2, rd, 0x3C, rs1, simm13); \ 764 | } while (0) 765 | 766 | #define SAVE(rs1, rs2, rd) \ 767 | do { \ 768 | asm_output("save %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 769 | Format_3_1(2, rd, 0x3C, rs1, 0, rs2); \ 770 | } while (0) 771 | 772 | #define SETHI(imm22, rd) \ 773 | do { \ 774 | asm_output("sethi %p, %s", imm22, gpn(rd)); \ 775 | Format_2_1(rd, 0x4, (imm22 >> 10)); \ 776 | } while (0) 777 | 778 | #define SLL(rs1, rs2, rd) \ 779 | do { \ 780 | asm_output("sll %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 781 | Format_3_5(2, rd, 0x25, rs1, 0, rs2); \ 782 | } while (0) 783 | 784 | #define SRA(rs1, rs2, rd) \ 785 | do { \ 786 | asm_output("sra %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 787 | Format_3_5(2, rd, 0x27, rs1, 0, rs2); \ 788 | } while (0) 789 | 790 | #define SRL(rs1, rs2, rd) \ 791 | do { \ 792 | asm_output("srl %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 793 | Format_3_5(2, rd, 0x26, rs1, 0, rs2); \ 794 | } while (0) 795 | 796 | #define STF(rd, rs1, rs2) \ 797 | do { \ 798 | asm_output("st %s, [%s + %s]", gpn(rd+32), gpn(rs1), gpn(rs2)); \ 799 | Format_3_1(3, rd, 0x24, rs1, 0, rs2); \ 800 | } while (0) 801 | 802 | #define STFI(rd, simm13, rs1) \ 803 | do { \ 804 | asm_output("st %s, [%s + %d]", gpn(rd+32), gpn(rs1), simm13); \ 805 | Format_3_1I(3, rd, 0x24, rs1, simm13); \ 806 | } while (0) 807 | 808 | #define STW(rd, rs2, rs1) \ 809 | do { \ 810 | asm_output("st %s, [%s + %s]", gpn(rd), gpn(rs1), gpn(rs2)); \ 811 | Format_3_1(3, rd, 0x4, rs1, 0, rs2); \ 812 | } while (0) 813 | 814 | #define STWI(rd, simm13, rs1) \ 815 | do { \ 816 | asm_output("st %s, [%s + %d]", gpn(rd), gpn(rs1), simm13); \ 817 | Format_3_1I(3, rd, 0x4, rs1, simm13); \ 818 | } while (0) 819 | 820 | #define SUBCC(rs1, rs2, rd) \ 821 | do { \ 822 | asm_output("subcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 823 | Format_3_1(2, rd, 0x14, rs1, 0, rs2); \ 824 | } while (0) 825 | 826 | #define SUB(rs1, rs2, rd) \ 827 | do { \ 828 | asm_output("sub %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 829 | Format_3_1(2, rd, 0x4, rs1, 0, rs2); \ 830 | } while (0) 831 | 832 | #define XOR(rs1, rs2, rd) \ 833 | do { \ 834 | asm_output("xor %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ 835 | Format_3_1(2, rd, 0x3, rs1, 0, rs2); \ 836 | } while (0) 837 | 838 | // Returns true if imm below 13-bit unsigned immediate) 839 | #define isIMM13(imm) \ 840 | (imm) <= 4095 && (imm) >= -4096 841 | 842 | #define isIMM19(imm) \ 843 | (imm) <= 0x3ffff && (imm) >= -0x40000 844 | 845 | #define isIMM22(imm) \ 846 | (imm) <= 0x1fffff && (imm) >= -0x200000 847 | 848 | #define SET32(imm32, rd) \ 849 | if(isIMM13(imm32)) { \ 850 | ORI(G0, imm32, rd); \ 851 | } else { \ 852 | ORI(rd, imm32 & 0x3FF, rd); \ 853 | SETHI(imm32, rd); \ 854 | } 855 | 856 | #define STDF32(rd, imm32, rs1) \ 857 | if(isIMM13(imm32+4)) { \ 858 | STFI(rd+1, imm32+4, rs1); \ 859 | STFI(rd, imm32, rs1); \ 860 | } else { \ 861 | STF(rd+1, L0, rs1); \ 862 | SET32(imm32+4, L0); \ 863 | STF(rd, L0, rs1); \ 864 | SET32(imm32, L0); \ 865 | } 866 | 867 | #define LDDF32(rs1, imm32, rd) \ 868 | if(isIMM13(imm32+4)) { \ 869 | LDFI(rs1, imm32+4, rd+1); \ 870 | LDFI(rs1, imm32, rd); \ 871 | } else { \ 872 | LDF(rs1, L0, rd+1); \ 873 | SET32(imm32+4, L0); \ 874 | LDF(rs1, L0, rd); \ 875 | SET32(imm32, L0); \ 876 | } 877 | 878 | #define STW32(rd, imm32, rs1) \ 879 | if(isIMM13(imm32)) { \ 880 | STWI(rd, imm32, rs1); \ 881 | } else { \ 882 | STW(rd, L0, rs1); \ 883 | SET32(imm32, L0); \ 884 | } 885 | 886 | #define LDUB32(rs1, imm32, rd) \ 887 | if(isIMM13(imm32)) { \ 888 | LDUBI(rs1, imm32, rd); \ 889 | } else { \ 890 | LDUB(rs1, L0, rd); \ 891 | SET32(imm32, L0); \ 892 | } 893 | 894 | #define LDUH32(rs1, imm32, rd) \ 895 | if(isIMM13(imm32)) { \ 896 | LDUHI(rs1, imm32, rd); \ 897 | } else { \ 898 | LDUH(rs1, L0, rd); \ 899 | SET32(imm32, L0); \ 900 | } 901 | 902 | #define LDSW32(rs1, imm32, rd) \ 903 | if(isIMM13(imm32)) { \ 904 | LDSWI(rs1, imm32, rd); \ 905 | } else { \ 906 | LDSW(rs1, L0, rd); \ 907 | SET32(imm32, L0); \ 908 | } 909 | 910 | 911 | // general Assemble 912 | #define JMP_long_nocheck(t) do { NOP(); JMPL(G0, G2, G0); ORI(G2, t & 0x3FF, G2); SETHI(t, G2); } while(0) 913 | #define JMP_long(t) do { underrunProtect(16); JMP_long_nocheck(t); } while(0) 914 | #define JMP_long_placeholder() JMP_long(0) 915 | 916 | #define JCC(t, tt) \ 917 | underrunProtect(32); \ 918 | tt = ((intptr_t)t - (intptr_t)_nIns + 8) >> 2; \ 919 | if( !(isIMM22((int32_t)tt)) ) { \ 920 | NOP(); \ 921 | JMPL(G0, G2, G0); \ 922 | SET32((intptr_t)t, G2); \ 923 | NOP(); \ 924 | BA(0, 5); \ 925 | tt = 4; \ 926 | } \ 927 | NOP() 928 | 929 | #define JMP(t) do { \ 930 | if (!t) { \ 931 | JMP_long_placeholder(); \ 932 | } else { \ 933 | intptr_t tt; \ 934 | JCC(t, tt); \ 935 | BA(0, tt); \ 936 | } \ 937 | } while(0) 938 | 939 | #define MR(d, s) do { underrunProtect(4); ORI(s, 0, d); } while(0) 940 | 941 | } 942 | #endif // __nanojit_NativeSparc__ 943 | -------------------------------------------------------------------------------- /NativeThumb.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | 40 | #ifndef __nanojit_NativeThumb__ 41 | #define __nanojit_NativeThumb__ 42 | 43 | 44 | namespace nanojit 45 | { 46 | const int NJ_LOG2_PAGE_SIZE = 12; // 4K 47 | const int NJ_MAX_REGISTERS = 6; // R0-R5 48 | const int NJ_MAX_STACK_ENTRY = 256; 49 | const int NJ_MAX_PARAMETERS = 1; 50 | const int NJ_ALIGN_STACK = 8; 51 | const int NJ_STACK_OFFSET = 8; 52 | 53 | #define NJ_CONSTANT_POOLS 54 | const int NJ_MAX_CPOOL_OFFSET = 1024; 55 | const int NJ_CPOOL_SIZE = 16; 56 | 57 | #define NJ_SOFTFLOAT 58 | #define NJ_STACK_GROWTH_UP 59 | #define NJ_THUMB_JIT 60 | 61 | const int LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect 62 | 63 | typedef unsigned short NIns; 64 | 65 | /* ARM registers */ 66 | typedef enum 67 | { 68 | R0 = 0, // 32bit return value, aka A1 69 | R1 = 1, // msw of 64bit return value, A2 70 | R2 = 2, // A3 71 | R3 = 3, // A4 72 | R4 = 4, // V1 73 | R5 = 5, // V2 74 | R6 = 6, // V3 75 | R7 = 7, // V4 76 | R8 = 8, // V5 77 | R9 = 9, // V6, SB (stack base) 78 | R10 = 10, // V7, SL 79 | FP = 11, // V8, frame pointer 80 | IP = 12, // intra-procedure call scratch register 81 | SP = 13, // stack pointer 82 | LR = 14, // link register (BL sets LR = return address) 83 | PC = 15, // program counter 84 | 85 | FirstReg = 0, 86 | LastReg = 5, 87 | Scratch = 6, 88 | UnknownReg = 6 89 | } 90 | Register; 91 | 92 | typedef int RegisterMask; 93 | typedef struct _FragInfo 94 | { 95 | RegisterMask needRestoring; 96 | NIns* epilogue; 97 | } 98 | FragInfo; 99 | 100 | static const int NumSavedRegs = 4; 101 | static const RegisterMask SavedRegs = 1<=0 && (i)<32);\ 240 | *(--_nIns) = (NIns)(0x0000 | ((i)<<6) | ((r)<<3) | (r)); \ 241 | asm_output("lsl %s,%d",gpn(r),(i));\ 242 | } while(0) 243 | 244 | 245 | 246 | #define TEST(d,s) do{underrunProtect(2); *(--_nIns) = (NIns)(0x4200 | ((d)<<3) | (s)); asm_output("test %s,%s",gpn(d),gpn(s));} while(0) 247 | #define CMP(l,r) do{underrunProtect(2); *(--_nIns) = (NIns)(0x4280 | ((r)<<3) | (l)); asm_output("cmp %s,%s",gpn(l),gpn(r));} while(0) 248 | 249 | #define CMPi(_r,_i) do{ \ 250 | if (_i<0) { \ 251 | NanoAssert(isS16((_i))); \ 252 | if ((_i)>-256) { \ 253 | underrunProtect(4); \ 254 | *(--_nIns) = (NIns)(0x42C0 | ((Scratch)<<3) | (_r)); \ 255 | asm_output("cmn %s,%s",gpn(_r),gpn(Scratch)); \ 256 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((-(_i))&0xFF) ); \ 257 | asm_output("mov %s,%d",gpn(Scratch),(_i));} \ 258 | else { \ 259 | NanoAssert(!((_i)&3)); \ 260 | underrunProtect(10); \ 261 | *(--_nIns) = (NIns)(0x42C0 | ((Scratch)<<3) | (_r)); \ 262 | asm_output("cmn %s,%s",gpn(_r),gpn(Scratch)); \ 263 | *(--_nIns) = (NIns)(0x0000 | (2<<6) | (Scratch<<3) | (Scratch) );\ 264 | asm_output("lsl %s,%d",gpn(Scratch),2); \ 265 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((-(_i)/4)&0xFF) ); \ 266 | asm_output("mov %s,%d",gpn(Scratch),(_i));} \ 267 | } else { \ 268 | if ((_i)>255) { \ 269 | int pad=0; \ 270 | underrunProtect(2*(7)); \ 271 | *(--_nIns) = (NIns)(0x4280 | ((Scratch)<<3) | (_r)); \ 272 | asm_output("cmp %s,%X",gpn(_r),(_i)); \ 273 | if ( (((int)(_nIns-2))%4) != 0) pad=1; \ 274 | if (pad) { \ 275 | *(--_nIns) = 0xBAAD; \ 276 | asm_output("PAD 0xBAAD"); } \ 277 | *(--_nIns) = (short)((_i) >> 16); \ 278 | *(--_nIns) = (short)((_i) & 0xFFFF); \ 279 | asm_output("imm %d", (_i)); \ 280 | *(--_nIns) = 0xBAAD; \ 281 | asm_output("PAD 0xBAAD"); \ 282 | if (pad) *(--_nIns) = (NIns)(0xE000 | (6>>1)); \ 283 | else *(--_nIns) = (NIns)(0xE000 | (4>>1)); \ 284 | asm_output("b %X", (int)_nIns+(pad?6:4)+4); \ 285 | *(--_nIns) = (NIns)(0x4800 | ((Scratch)<<8) | (1));} \ 286 | else { \ 287 | NanoAssert((_i)<256); \ 288 | underrunProtect(2); \ 289 | *(--_nIns) = (NIns)(0x2800 | ((_r)<<8) | ((_i)&0xFF)); \ 290 | asm_output("cmp %s,%X",gpn(_r),(_i));} \ 291 | } } while(0) 292 | 293 | #define MR(d,s) do { \ 294 | underrunProtect(2); \ 295 | if (((d)<8) && ((s)<8)) \ 296 | *(--_nIns) = (NIns)(0x1C00 | ((s)<<3) | (d)); \ 297 | else { \ 298 | if (d<8) *(--_nIns) = (NIns)(0x4600 | ((s)<<3) | ((d)&7)); \ 299 | else *(--_nIns) = (NIns)(0x4600 | (1<<7) | ((s)<<3) | ((d)&7));\ 300 | } asm_output("mov %s,%s",gpn(d),gpn(s)); } while (0) 301 | 302 | // Thumb doesn't support conditional-move 303 | #define MREQ(d,s) do { NanoAssert(0); } while (0) 304 | #define MRNE(d,s) do { NanoAssert(0); } while (0) 305 | #define MRL(d,s) do { NanoAssert(0); } while (0) 306 | #define MRLE(d,s) do { NanoAssert(0); } while (0) 307 | #define MRG(d,s) do { NanoAssert(0); } while (0) 308 | #define MRGE(d,s) do { NanoAssert(0); } while (0) 309 | #define MRB(d,s) do { NanoAssert(0); } while (0) 310 | #define MRBE(d,s) do { NanoAssert(0); } while (0) 311 | #define MRA(d,s) do { NanoAssert(0); } while (0) 312 | #define MRAE(d,s) do { NanoAssert(0); } while (0) 313 | #define MRNC(d,s) do { NanoAssert(0); } while (0) 314 | #define MRNO(d,s) do { NanoAssert(0); } while (0) 315 | 316 | #define LD(reg,offset,base) do{ \ 317 | int off = (offset) >> 2; \ 318 | if (base==PC){ \ 319 | underrunProtect(2); \ 320 | NanoAssert(off>=0 && off<256); \ 321 | *(--_nIns) = (NIns)(0x4800 | ((reg)<<8) | (off&0xFF)); \ 322 | asm_output("ld %s,%d(%s)",gpn(reg),(offset),gpn(base)); \ 323 | } else if (base==SP) { \ 324 | NanoAssert(off>=0); \ 325 | if (off<256){ \ 326 | underrunProtect(2); \ 327 | *(--_nIns) = (NIns)(0x9800 | ((reg)<<8) | (off&0xFF));} \ 328 | else { \ 329 | underrunProtect(4); \ 330 | int rem = (offset) - 1020; NanoAssert(rem<125); \ 331 | *(--_nIns) = (NIns)(0x6800 | (rem&0x1F)<<6 | (reg)<<3 | (reg)); \ 332 | *(--_nIns) = (NIns)(0xA800 | ((reg)<<8) | (0xFF));} \ 333 | asm_output("ld %s,%d(%s)",gpn(reg),(offset),gpn(base)); \ 334 | } else if ((offset)<0) { \ 335 | underrunProtect(8); \ 336 | *(--_nIns) = (NIns)(0x5800 | (Scratch<<6) | (base<<3) | (reg)); \ 337 | asm_output("ld %s,%d(%s)",gpn(reg),(offset),gpn(Scratch)); \ 338 | *(--_nIns) = (NIns)(0x4240 | (Scratch<<3) | Scratch); \ 339 | asm_output("neg %s,%s",gpn(Scratch),gpn(Scratch)); \ 340 | if ((offset)<-255){ \ 341 | NanoAssert( (offset)>=-1020); \ 342 | *(--_nIns) = (NIns)(0x0000 | (2<<6) | (Scratch<<3) | (Scratch) ); \ 343 | asm_output("lsl %s,%d",gpn(Scratch),2); \ 344 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((-(off))&0xFF) ); \ 345 | asm_output("mov %s,%d",gpn(Scratch),(offset));} \ 346 | else { \ 347 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((-(offset))&0xFF) ); \ 348 | asm_output("mov %s,%d",gpn(Scratch),(offset));} \ 349 | } else { \ 350 | if ((off)<32) { \ 351 | underrunProtect(2); \ 352 | *(--_nIns) = (NIns)(0x6800 | ((off&0x1F)<<6) | ((base)<<3) | (reg)); \ 353 | asm_output("ld %s,%d(%s)",gpn(reg),(offset),gpn(base));} \ 354 | else { \ 355 | underrunProtect(2); \ 356 | *(--_nIns) = (NIns)(0x5800 | (Scratch<<6) | (base<<3) | (reg)); \ 357 | asm_output("ld %s,%d(%s)",gpn(reg),(offset),gpn(Scratch)); \ 358 | LDi(Scratch, (offset));}} \ 359 | } while(0) 360 | 361 | // load 8-bit, zero extend (aka LDRB) 362 | // note, only 5-bit offsets (!) are supported for this, but that's all we need at the moment, 363 | // and we get a nice advantage in Thumb mode... 364 | #define LD8Z(_r,_d,_b) do{ \ 365 | NanoAssert((_d)>=0 && (_d)<=31);\ 366 | underrunProtect(2);\ 367 | *(--_nIns) = (NIns)(0x7800 | (((_d)&31)<<6) | ((_b)<<3) | (_r) ); \ 368 | asm_output("ldrb %s,%d(%s)", gpn(_r),(_d),gpn(_b));\ 369 | } while(0) 370 | 371 | 372 | #define LEA(_r,_d,_b) do{ \ 373 | NanoAssert((_d)>=0); \ 374 | if (_b!=SP) NanoAssert(0); \ 375 | if ((int)(_d)<=1020 && (_d)>=0) { \ 376 | underrunProtect(2); \ 377 | *(--_nIns) = (NIns)(0xA800 | ((_r)<<8) | ((_d)>>2));} \ 378 | else { \ 379 | underrunProtect(4); \ 380 | int rem = (_d) - 1020; NanoAssert(rem<256); \ 381 | *(--_nIns) = (NIns)(0x3000 | ((_r)<<8) | ((rem)&0xFF)); \ 382 | *(--_nIns) = (NIns)(0xA800 | ((_r)<<8) | (0xFF));} \ 383 | asm_output("lea %s, %d(SP)", gpn(_r), _d); \ 384 | } while(0) 385 | 386 | 387 | //NanoAssert((t)<2048); 388 | #define JMP_long_nochk_offset(t) do { \ 389 | *(--_nIns) = (NIns)(0xF800 | (((t)&0xFFF)>>1) ); \ 390 | *(--_nIns) = (NIns)(0xF000 | (((t)>>12)&0x7FF) ); \ 391 | asm_output("BL offset=%d",int(t));} while (0) 392 | 393 | #define JMP_long_placeholder() BL(_nIns) 394 | 395 | // conditional branch 396 | enum { 397 | EQ=0, 398 | NE, 399 | CSHS, 400 | CCLO, 401 | MI, 402 | PL, 403 | VS, 404 | VC, 405 | HI, 406 | LS, 407 | GE, 408 | LT, 409 | GT, 410 | LE, 411 | AL, 412 | NV 413 | }; 414 | 415 | 416 | #define JA(t) B_cond(HI,t) 417 | #define JNA(t) B_cond(LS,t) 418 | #define JB(t) B_cond(CCLO,t) 419 | #define JNB(t) B_cond(CSHS,t) 420 | #define JE(t) B_cond(EQ,t) 421 | #define JNE(t) B_cond(NE,t) 422 | #define JBE(t) B_cond(LS,t) 423 | #define JNBE(t) B_cond(HI,t) 424 | #define JAE(t) B_cond(CSHS,t) 425 | #define JNAE(t) B_cond(CCLO,t) 426 | #define JL(t) B_cond(LT,t) 427 | #define JNL(t) B_cond(GE,t) 428 | #define JG(t) B_cond(GT,t) 429 | #define JNG(t) B_cond(LE,t) 430 | #define JLE(t) B_cond(LE,t) 431 | #define JNLE(t) B_cond(GT,t) 432 | #define JGE(t) B_cond(GE,t) 433 | #define JNGE(t) B_cond(LT,t) 434 | #define JC(t) B_cond(CSHS,t) 435 | #define JNC(t) B_cond(CCLO,t) 436 | #define JO(t) B_cond(VS,t) 437 | #define JNO(t) B_cond(VC,t) 438 | 439 | // B(cond) +4 - if condition, skip to MOV 440 | // EOR R, R - set register to 0 441 | // B(AL) +2 - skip over next 442 | // MOV R, 1 - set register to 1 443 | #define SET(r,cond) \ 444 | underrunProtect(10); \ 445 | *(--_nIns) = (NIns)(0x0000); \ 446 | *(--_nIns) = (NIns)(0x2000 | (r<<8) | (1)); \ 447 | *(--_nIns) = (NIns)(0xE000 | 1 ); \ 448 | *(--_nIns) = (NIns)(0x4040 | (r<<3) | r); \ 449 | *(--_nIns) = (NIns)(0xD000 | ((cond)<<8) | (1) ); 450 | 451 | #define SETE(r) do {SET(r,EQ); asm_output("sete %s",gpn(r)); } while(0) 452 | #define SETL(r) do {SET(r,LT); asm_output("setl %s",gpn(r)); } while(0) 453 | #define SETLE(r) do {SET(r,LE); asm_output("setle %s",gpn(r)); } while(0) 454 | #define SETG(r) do {SET(r,GT); asm_output("setg %s",gpn(r)); } while(0) 455 | #define SETGE(r) do {SET(r,GE); asm_output("setge %s",gpn(r)); } while(0) 456 | #define SETB(r) do {SET(r,CCLO); asm_output("setb %s",gpn(r)); } while(0) 457 | #define SETBE(r) do {SET(r,LS); asm_output("setbe %s",gpn(r)); } while(0) 458 | #define SETAE(r) do {SET(r,CSHS); asm_output("setae %s",gpn(r)); } while(0) /* warning, untested */ 459 | #define SETA(r) do {SET(r,HI); asm_output("seta %s",gpn(r)); } while(0) /* warning, untested */ 460 | #define SETC(r) do {SET(r,CSHS); asm_output("setc %s",gpn(r)); } while(0) /* warning, untested */ 461 | #define SETO(r) do {SET(r,VS); asm_output("seto %s",gpn(r)); } while(0) /* warning, untested */ 462 | 463 | // This zero-extends a reg that has been set using one of the SET macros, 464 | // but is a NOOP on ARM/Thumb 465 | #define MOVZX8(r,r2) 466 | 467 | // If the offset is 0-255, no problem, just load 8-bit imm 468 | // If the offset is greater than that, we load the SP 469 | // 470 | // If offset is 8-bit, we 471 | // MOV Scratch, SP 472 | // MOV _r, offset 473 | // LDRSH _r, offset, Scratch 474 | // 475 | // else 476 | // ADD_sp Scratch, offset/4 477 | // MOV _r, offset%4 478 | // LDRSH _r, Scratch, _r 479 | #define LD16S(_r,_d,_b) do{ \ 480 | if (_b==SP) { \ 481 | NanoAssert((int)(_d)>=0); \ 482 | if (isU8(_d)) { \ 483 | underrunProtect(6); \ 484 | *(--_nIns) = (NIns)(0x5E00 | ((_r)<<6) | (Scratch<<3) | (_r) ); \ 485 | *(--_nIns) = (NIns)(0x2000 | ((_r)<<8) | (_d)&0xFF ); \ 486 | *(--_nIns) = (NIns)(0x4600 | (SP<<3) | Scratch );} \ 487 | else { \ 488 | underrunProtect(6); \ 489 | *(--_nIns) = (NIns)(0x5E00 | ((_r)<<6) | (Scratch<<3) | (_r) ); \ 490 | *(--_nIns) = (NIns)(0x2000 | ((_r)<<8) | ((_d)%4) ); \ 491 | *(--_nIns) = (NIns)(0xA800 | (Scratch<<8) | (alignTo((_d), 4))/4);} \ 492 | } else { \ 493 | if ((_d)<0) { \ 494 | if ((_d)<-255) { \ 495 | NanoAssert((_d)>=-510); \ 496 | underrunProtect(8); \ 497 | int rem = -(_d) - 255; \ 498 | *(--_nIns) = (NIns)(0x5E00 | (Scratch<<6) | ((_b)<<3) | (_r)); \ 499 | *(--_nIns) = (NIns)(0x4240 | (Scratch<<3) | Scratch); \ 500 | *(--_nIns) = (NIns)(0x3000 | (Scratch<<8) | (rem&0xFF)); \ 501 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | 0xFF );} \ 502 | else { \ 503 | underrunProtect(6); \ 504 | *(--_nIns) = (NIns)(0x5E00 | ((Scratch)<<6) | ((_b)<<3) | (_r) ); \ 505 | *(--_nIns) = (NIns)(0x4240 | (Scratch<<3) | Scratch); \ 506 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((-(_d))&0xFF) );}} \ 507 | else if ((int)(_d)<256) { \ 508 | underrunProtect(4); \ 509 | *(--_nIns) = (NIns)(0x5E00 | (Scratch<<6) | ((_b)<<3) | (_r)); \ 510 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | ((_d)&0xFF) );} \ 511 | else { \ 512 | NanoAssert((int)(_d)<=510); \ 513 | underrunProtect(6); \ 514 | int rem = (_d) - 255; \ 515 | *(--_nIns) = (NIns)(0x5E00 | (Scratch<<6) | ((_b)<<3) | (_r)); \ 516 | *(--_nIns) = (NIns)(0x3000 | (Scratch<<8) | (rem&0xFF)); \ 517 | *(--_nIns) = (NIns)(0x2000 | (Scratch<<8) | 0xFF );} \ 518 | } asm_output("movsx %s, %d(%s)", gpn(_r), (_d), gpn(_b)); } while(0) 519 | 520 | //*(--_nIns) = (NIns)(0x8800 | (((_d)>>1)<<6) | (Scratch<<3) | (_r));\ 521 | //*(--_nIns) = (NIns)(0x4600 | (SP<<3) | Scratch );} \ 522 | 523 | 524 | } 525 | #endif // __nanojit_NativeThumb__ 526 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | [ Note: I've deprecated this library and will no longer be updating it ] 2 | [ Mozilla and Adobe have recently merged their Nanojit implementations ] 3 | [ and set up a shared repository to develop it further: ] 4 | [ ] 5 | [ http://hg.mozilla.org/projects/nanojit-central ] 6 | [ ] 7 | [ I've created a git repository that mirrors this at: ] 8 | [ ] 9 | [ http://github.com/doublec/nanojit-central ] 10 | [ ] 11 | 12 | Nanojit 13 | ======= 14 | 15 | Nanojit is a small cross platform C++ library that emits machine 16 | code. It was originally part of Adobe's Tamarin ActionScript VM. It is 17 | also used by Mozilla in their 'TraceMonkey' JavaScript implementation. 18 | 19 | I'm using it in a couple of my projects so I pulled the source out of 20 | those projects and made it into its own repository. The current source 21 | was refreshed from Mozilla's mozilla-central repository at commit id 22 | 968dfb (http://hg.mozilla.org/mozilla-central). 23 | 24 | I'll periodically update from the original repositories to get bug 25 | fixes and improvements. 26 | 27 | License 28 | ======= 29 | 30 | The source code is tri-licensed under MPL 1.1/GPL 2.0/LGPL 2.1. See 31 | the LICENSE file for details. 32 | 33 | Build 34 | ===== 35 | 36 | A makefile is provided. It currently only builds a version of nanojit 37 | for x86 machine code generation. Feel free to tweak, submit patches, 38 | etc to fix this. 39 | 40 | Documentation 41 | ============= 42 | 43 | See the documentation at the Mozilla developer site: 44 | 45 | https://developer.mozilla.org/En/Nanojit 46 | 47 | The example program from that documentation is in the 'example' 48 | subdirectory. 49 | 50 | Contact 51 | =============== 52 | 53 | The location of this version of nanojit is: 54 | 55 | http://github.com/doublec/nanojit 56 | 57 | I can be reached: 58 | 59 | Chris Double 60 | chris.double@double.co.nz 61 | http://www.bluishcoder.co.nz 62 | -------------------------------------------------------------------------------- /RegAlloc.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #include "nanojit.h" 40 | 41 | namespace nanojit 42 | { 43 | #ifdef FEATURE_NANOJIT 44 | 45 | /** 46 | * Generic register allocation routines. 47 | */ 48 | void RegAlloc::clear() 49 | { 50 | free = 0; 51 | used = 0; 52 | memset(active, 0, (LastReg+1) * sizeof(LIns*)); 53 | } 54 | 55 | bool RegAlloc::isFree(Register r) 56 | { 57 | NanoAssert(r != UnknownReg); 58 | return (free & rmask(r)) != 0; 59 | } 60 | 61 | void RegAlloc::addFree(Register r) 62 | { 63 | NanoAssert(!isFree(r)); 64 | free |= rmask(r); 65 | } 66 | 67 | void RegAlloc::addActive(Register r, LIns* v) 68 | { 69 | // Count++; 70 | NanoAssert(v && r != UnknownReg && active[r] == NULL ); 71 | active[r] = v; 72 | useActive(r); 73 | } 74 | 75 | void RegAlloc::useActive(Register r) 76 | { 77 | NanoAssert(r != UnknownReg && active[r] != NULL); 78 | usepri[r] = priority++; 79 | } 80 | 81 | void RegAlloc::removeActive(Register r) 82 | { 83 | //registerReleaseCount++; 84 | NanoAssert(r != UnknownReg); 85 | NanoAssert(active[r] != NULL); 86 | 87 | // remove the given register from the active list 88 | active[r] = NULL; 89 | } 90 | 91 | void RegAlloc::retire(Register r) 92 | { 93 | NanoAssert(r != UnknownReg); 94 | NanoAssert(active[r] != NULL); 95 | active[r] = NULL; 96 | free |= rmask(r); 97 | } 98 | 99 | #ifdef NJ_VERBOSE 100 | /* static */ void RegAlloc::formatRegisters(RegAlloc& regs, char* s, Fragment *frag) 101 | { 102 | if (!frag || !frag->lirbuf) 103 | return; 104 | LirNameMap *names = frag->lirbuf->names; 105 | for(int i=0; i<(LastReg+1); i++) 106 | { 107 | LIns* ins = regs.active[i]; 108 | Register r = (Register)i; 109 | if (ins && regs.isFree(r)) 110 | { NanoAssertMsg( 0, "Coding error; register is both free and active! " ); } 111 | //if (!ins && !regs.isFree(r)) 112 | // { NanoAssertMsg( 0, "Coding error; register is not in the free list when it should be" ); } 113 | if (!ins) 114 | continue; 115 | 116 | s += strlen(s); 117 | const char* rname = ins->isQuad() ? fpn(r) : gpn(r); 118 | sprintf(s, " %s(%s)", rname, names->formatRef(ins)); 119 | } 120 | } 121 | #endif /* NJ_VERBOSE */ 122 | 123 | #ifdef _DEBUG 124 | 125 | uint32_t RegAlloc::countFree() 126 | { 127 | int cnt = 0; 128 | for(Register i=FirstReg; i <= LastReg; i = nextreg(i)) 129 | cnt += isFree(i) ? 1 : 0; 130 | return cnt; 131 | } 132 | 133 | uint32_t RegAlloc::countActive() 134 | { 135 | int cnt = 0; 136 | for(Register i=FirstReg; i <= LastReg; i = nextreg(i)) 137 | cnt += active[i] ? 1 : 0; 138 | return cnt; 139 | } 140 | 141 | void RegAlloc::checkCount() 142 | { 143 | NanoAssert(count == (countActive() + countFree())); 144 | } 145 | 146 | bool RegAlloc::isConsistent(Register r, LIns* i) 147 | { 148 | NanoAssert(r != UnknownReg); 149 | return (isFree(r) && !getActive(r) && !i) || 150 | (!isFree(r) && getActive(r)== i && i ); 151 | } 152 | 153 | #endif /*DEBUG*/ 154 | #endif /* FEATURE_NANOJIT */ 155 | } 156 | -------------------------------------------------------------------------------- /RegAlloc.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | 40 | #ifndef __nanojit_RegAlloc__ 41 | #define __nanojit_RegAlloc__ 42 | 43 | 44 | namespace nanojit 45 | { 46 | inline RegisterMask rmask(Register r) 47 | { 48 | return 1 << r; 49 | } 50 | 51 | class RegAlloc MMGC_SUBCLASS_DECL 52 | { 53 | public: 54 | RegAlloc() : free(0), used(0), priority(0) {} 55 | void clear(); 56 | bool isFree(Register r); 57 | void addFree(Register r); 58 | void addActive(Register r, LIns* ins); 59 | void useActive(Register r); 60 | void removeActive(Register r); 61 | void retire(Register r); 62 | bool isValid() { 63 | return (free|used) != 0; 64 | } 65 | 66 | int32_t getPriority(Register r) { 67 | NanoAssert(r != UnknownReg && active[r]); 68 | return usepri[r]; 69 | } 70 | 71 | LIns* getActive(Register r) { 72 | NanoAssert(r != UnknownReg); 73 | return active[r]; 74 | } 75 | 76 | debug_only( uint32_t countFree(); ) 77 | debug_only( uint32_t countActive(); ) 78 | debug_only( void checkCount(); ) 79 | debug_only( bool isConsistent(Register r, LIns* v); ) 80 | debug_only( uint32_t count; ) 81 | debug_only( RegisterMask managed; ) // bitfield of 0..NJ_MAX_REGISTERS denoting which are under our management 82 | 83 | LIns* active[LastReg + 1]; // active[r] = OP that defines r 84 | int32_t usepri[LastReg + 1]; // used priority. lower = more likely to spill. 85 | RegisterMask free; 86 | RegisterMask used; 87 | int32_t priority; 88 | 89 | verbose_only( static void formatRegisters(RegAlloc& regs, char* s, Fragment*); ) 90 | 91 | DECLARE_PLATFORM_REGALLOC() 92 | }; 93 | } 94 | #endif // __nanojit_RegAlloc__ 95 | -------------------------------------------------------------------------------- /TraceTreeDrawer.cpp: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is [Open Source Virtual Machine]. 15 | * 16 | * The Initial Developer of the Original Code is 17 | * Adobe System Incorporated. 18 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 19 | * the Initial Developer. All Rights Reserved. 20 | * 21 | * Contributor(s): 22 | * Adobe AS3 Team 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either the GNU General Public License Version 2 or later (the "GPL"), or 26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | #include 39 | #include "nanojit.h" 40 | 41 | #define verbose_draw_only(x) 42 | 43 | namespace nanojit { 44 | 45 | #ifdef AVMPLUS_VERBOSE 46 | using namespace avmplus; 47 | 48 | TraceTreeDrawer::TraceTreeDrawer(Fragmento *frago, AvmCore *core, char *fileName) { 49 | this->_frago = frago; 50 | this->_core = core; 51 | this->_labels = frago->labels; 52 | this->_fileName = fileName; 53 | } 54 | 55 | TraceTreeDrawer::~TraceTreeDrawer() { 56 | } 57 | 58 | void TraceTreeDrawer::addNode(Fragment *fragment, const char *color) { 59 | fprintf(_fstream, "\n" 60 | "\n" 61 | "\n" 62 | "\n" 63 | "%s" 64 | " %s" //fragment->ip 65 | "\n" 66 | "\n" 67 | "\n" 68 | "\n" 69 | "\n", 70 | (int)fragment, 71 | _labels->format(fragment), 72 | _labels->format(fragment->ip), color); 73 | } 74 | 75 | void TraceTreeDrawer::addNode(Fragment *fragment) { 76 | if (!fragment->isAnchor()) 77 | addNode(fragment, "FFCC99"); // standard color 78 | else 79 | addNode(fragment, "CCFFFF"); // Root node 80 | } 81 | 82 | void TraceTreeDrawer::addEdge(Fragment *from, Fragment *to) { 83 | this->addNode(from); 84 | this->addNode(to); 85 | 86 | // Create the edge 87 | fprintf(_fstream, "\n", (int)from, (int)to); 88 | drawDirectedEdge(); 89 | fprintf(_fstream, "\n"); 90 | } 91 | 92 | void TraceTreeDrawer::recursiveDraw(Fragment *root) { 93 | if (!isCompiled(root)) { 94 | return; 95 | } 96 | 97 | addBackEdges(root); 98 | 99 | Fragment *lastDrawnBranch = root; 100 | for (Fragment *treeBranch = root->branches; treeBranch != 0; treeBranch = treeBranch->nextbranch) { 101 | if (!isMergeFragment(treeBranch)) { 102 | struct SideExit* exit = treeBranch->spawnedFrom->exit(); 103 | if (isValidSideExit(exit) && isCompiled(treeBranch)) { 104 | verbose_draw_only(nj_dprintf("Adding edge between %s and %s\n", _labels->format(lastDrawnBranch), _labels->format(treeBranch))); 105 | 106 | this->addEdge(lastDrawnBranch, treeBranch); 107 | lastDrawnBranch = treeBranch; 108 | } 109 | 110 | recursiveDraw(treeBranch); 111 | } 112 | else { 113 | addMergeNode(treeBranch); 114 | } // end ifelse 115 | } // end for loop 116 | } 117 | 118 | void TraceTreeDrawer::addBackEdges(Fragment *root) { 119 | // At the end of a tree, find out where it goes 120 | if (isCrossFragment(root)) { 121 | if (root->eot_target) { 122 | verbose_draw_only(nj_dprintf("Found a cross fragment %s TO %s \n", _labels->format(root), _labels->format(root->eot_target))); 123 | this->addEdge(root, root->eot_target); 124 | } 125 | } 126 | else if (isBackEdgeSideExit(root)) { 127 | verbose_draw_only(nj_dprintf("Adding anchor branch edge from %s TO %s\n", _labels->format(root), _labels->format(root->anchor))); 128 | this->addEdge(root, root->anchor); 129 | } 130 | else if (isSingleTrace(root)) { 131 | verbose_draw_only(nj_dprintf("Found a single trace %s\n", _labels->format(root))); 132 | this->addEdge(root, root); 133 | } 134 | else if (isSpawnedTrace(root)) { 135 | struct SideExit *exit = root->spawnedFrom->exit(); 136 | if (isValidSideExit(exit) && isCompiled(root)) { 137 | verbose_draw_only(nj_dprintf("Found a spawned side exit from %s that is a spawn and compiled %s\n", _labels->format(root), _labels->format(exit->from))); 138 | this->addEdge(root, root->parent); 139 | } 140 | } 141 | else if (hasEndOfTraceFrag(root)) { 142 | verbose_draw_only(nj_dprintf("%s has an EOT to %s\n", _labels->format(root), _labels->format(root->eot_target))); 143 | addEdge(root, root->eot_target); 144 | } 145 | } 146 | 147 | void TraceTreeDrawer::addMergeNode(Fragment *mergeRoot) { 148 | verbose_draw_only(nj_dprintf("Found a merge fragment %s and anchor %s\n", _labels->format(mergeRoot), _labels->format(mergeRoot->anchor))); 149 | 150 | if (hasCompiledBranch(mergeRoot)) { 151 | verbose_draw_only(nj_dprintf("Found a branch to %s\n", _labels->format(mergeRoot->branches))); 152 | addEdge(mergeRoot, mergeRoot->branches); 153 | recursiveDraw(mergeRoot->branches); 154 | } 155 | 156 | if (hasEndOfTraceFrag(mergeRoot)) { 157 | verbose_draw_only(nj_dprintf("Merge with an EOT to %s\n", _labels->format(mergeRoot->eot_target))); 158 | addEdge(mergeRoot, mergeRoot->eot_target); 159 | } 160 | else { 161 | verbose_draw_only(nj_dprintf("Merge to anchor %s\n", _labels->format(mergeRoot->anchor))); 162 | addEdge(mergeRoot, mergeRoot->anchor); 163 | } 164 | } 165 | 166 | void TraceTreeDrawer::draw(Fragment *root) { 167 | this->recursiveDraw(root); 168 | 169 | verbose_draw_only(nj_dprintf("\nFinished drawing, printing status\n")); 170 | verbose_draw_only(this->printTreeStatus(root)); 171 | } 172 | 173 | void TraceTreeDrawer::createGraphHeader() { 174 | char outputFileName[128]; 175 | const char *graphMLExtension = ".graphml"; 176 | 177 | int fileNameLength = strlen(this->_fileName); 178 | memset(outputFileName, 0, sizeof(outputFileName)); 179 | strncat(outputFileName, this->_fileName, 128); 180 | strncat(outputFileName + fileNameLength - 1, graphMLExtension, 128); // -1 to overwrite the \0 181 | 182 | verbose_draw_only(nj_dprintf("output file name is %s\n", outputFileName)); 183 | this->_fstream = fopen(outputFileName, "w"); 184 | 185 | fprintf(_fstream, "\n" 186 | "\n" 187 | "\n" 188 | "\n" 189 | "\n" 190 | "\n" 191 | "\n"); 192 | 193 | } 194 | 195 | void TraceTreeDrawer::createGraphFooter() { 196 | fprintf(_fstream, " "); 197 | fclose(this->_fstream); 198 | } 199 | 200 | bool TraceTreeDrawer::isValidSideExit(struct SideExit *exit) { 201 | return exit != 0; 202 | } 203 | 204 | bool TraceTreeDrawer::isCompiled(Fragment *f) { 205 | return f->compileNbr != 0; 206 | } 207 | 208 | bool TraceTreeDrawer::isLoopFragment(Fragment *f) { 209 | return f->kind == LoopTrace; 210 | } 211 | 212 | bool TraceTreeDrawer::isCrossFragment(Fragment *f) { 213 | return f->kind == BranchTrace; 214 | } 215 | 216 | bool TraceTreeDrawer::isMergeFragment(Fragment *f) { 217 | return f->kind == MergeTrace; 218 | } 219 | 220 | bool TraceTreeDrawer::isSingleTrace(Fragment *f) { 221 | return f->isAnchor() && !hasCompiledBranch(f); 222 | } 223 | 224 | bool TraceTreeDrawer::hasCompiledBranch(Fragment *f) { 225 | for (Fragment *current = f->branches; current != 0; current = current->nextbranch) { 226 | if (isCompiled(current)) { 227 | return true; 228 | } 229 | } 230 | 231 | return false; 232 | } 233 | 234 | bool TraceTreeDrawer::isSpawnedTrace(Fragment *f) { 235 | return f->spawnedFrom != 0; 236 | } 237 | 238 | bool TraceTreeDrawer::isBackEdgeSideExit(Fragment *f) { 239 | return !f->branches && !f->isAnchor(); 240 | } 241 | 242 | bool TraceTreeDrawer::hasEndOfTraceFrag(Fragment *f) { 243 | return (f->eot_target) && (f != f->eot_target); 244 | } 245 | 246 | void TraceTreeDrawer::drawDirectedEdge() { 247 | // Make it directed 248 | fprintf(_fstream, "\n" 249 | "\n" 250 | "\n" 251 | "\n" 252 | "\n"); 253 | } 254 | 255 | void TraceTreeDrawer::printTreeStatus(Fragment *root) { 256 | if (!isCompiled(root)) { 257 | return; 258 | } 259 | 260 | nj_dprintf("\nRoot is %s\n", _labels->format(root)); 261 | if (root->spawnedFrom) { 262 | if (root->compileNbr) { 263 | nj_dprintf("Found a root that is a spawn and compiled %s\n", _labels->format(root->parent)); 264 | } 265 | } 266 | 267 | for (Fragment *x = root->branches; x != 0; x = x->nextbranch) { 268 | if (x->kind != MergeTrace) { 269 | struct SideExit* exit = x->spawnedFrom->exit(); 270 | if (exit && x->compileNbr) { 271 | nj_dprintf("Found one with an SID and compiled %s\n", _labels->format(x)); 272 | } 273 | 274 | printTreeStatus(x); 275 | } 276 | } 277 | nj_dprintf("\n"); 278 | } 279 | #endif 280 | } 281 | 282 | 283 | void drawTraceTrees(nanojit::Fragmento *frago, nanojit::FragmentMap * _frags, avmplus::AvmCore *core, char *fileName) { 284 | #ifdef AVMPLUS_VERBOSE 285 | nanojit::TraceTreeDrawer *traceDrawer = new (core->gc) nanojit::TraceTreeDrawer(frago, core, fileName); 286 | traceDrawer->createGraphHeader(); 287 | 288 | int32_t count = _frags->size(); 289 | for (int32_t i=0; iat(i); 292 | // Count only fragments which have something compiled. Needs the -Dverbose flag 293 | if (frag->compileNbr) { 294 | traceDrawer->draw(frag); 295 | } 296 | } 297 | 298 | traceDrawer->createGraphFooter(); 299 | #else 300 | (void)frago; 301 | (void)_frags; 302 | (void)core; 303 | (void)fileName; 304 | #endif 305 | } 306 | 307 | -------------------------------------------------------------------------------- /TraceTreeDrawer.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is [Open Source Virtual Machine]. 15 | * 16 | * The Initial Developer of the Original Code is 17 | * Adobe System Incorporated. 18 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 19 | * the Initial Developer. All Rights Reserved. 20 | * 21 | * Contributor(s): 22 | * Adobe AS3 Team 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either the GNU General Public License Version 2 or later (the "GPL"), or 26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | #ifndef __nanojit_TraceTreeDrawer__ 39 | #define __nanojit_TraceTreeDrawer__ 40 | #include 41 | 42 | namespace nanojit { 43 | #ifdef AVMPLUS_VERBOSE 44 | using namespace avmplus; 45 | 46 | class TraceTreeDrawer : public GCFinalizedObject { 47 | public: 48 | TraceTreeDrawer(Fragmento *frago, AvmCore *core, char *fileName); 49 | ~TraceTreeDrawer(); 50 | 51 | void createGraphHeader(); 52 | void createGraphFooter(); 53 | 54 | void addEdge(Fragment *from, Fragment *to); 55 | void addNode(Fragment *fragment); 56 | void addNode(Fragment *fragment, const char *color); 57 | 58 | void draw(Fragment *rootFragment); 59 | void recursiveDraw(Fragment *root); 60 | 61 | private: 62 | FILE* _fstream; 63 | DWB(AvmCore *) _core; 64 | DWB(Fragmento *) _frago; 65 | DWB(LabelMap *) _labels; 66 | char * _fileName; 67 | 68 | void addBackEdges(Fragment *f); 69 | void addMergeNode(Fragment *f); 70 | 71 | bool isValidSideExit(struct SideExit *exit); 72 | bool isCompiled(Fragment *f); 73 | bool isLoopFragment(Fragment *f); 74 | bool isCrossFragment(Fragment *f); 75 | bool isMergeFragment(Fragment *f); 76 | bool isSingleTrace(Fragment *f); 77 | bool isSpawnedTrace(Fragment *f); 78 | bool isBackEdgeSideExit(Fragment *f); 79 | bool hasEndOfTraceFrag(Fragment *f); 80 | bool hasCompiledBranch(Fragment *f); 81 | 82 | void printTreeStatus(Fragment *root); 83 | void drawDirectedEdge(); 84 | }; 85 | #endif 86 | } 87 | 88 | #endif /*TRACETREEDRAWER_H_*/ 89 | -------------------------------------------------------------------------------- /avmplus.cpp: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 1.1 (the 5 | * "License"); you may not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at http://www.mozilla.org/MPL/ 7 | * 8 | * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 9 | * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 10 | * language governing rights and limitations under the License. 11 | * 12 | * The Original Code is [Open Source Virtual Machine.] 13 | * 14 | * The Initial Developer of the Original Code is Adobe System Incorporated. Portions created 15 | * by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights 16 | * Reserved. 17 | * 18 | * Contributor(s): Adobe AS3 Team 19 | * Andreas Gal 20 | * 21 | * Alternatively, the contents of this file may be used under the terms of either the GNU 22 | * General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public 23 | * License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the 24 | * LGPL are applicable instead of those above. If you wish to allow use of your version of this 25 | * file only under the terms of either the GPL or the LGPL, and not to allow others to use your 26 | * version of this file under the terms of the MPL, indicate your decision by deleting provisions 27 | * above and replace them with the notice and other provisions required by the GPL or the 28 | * LGPL. If you do not delete the provisions above, a recipient may use your version of this file 29 | * under the terms of any one of the MPL, the GPL or the LGPL. 30 | * 31 | ***** END LICENSE BLOCK ***** */ 32 | 33 | #include "avmplus.h" 34 | 35 | using namespace avmplus; 36 | 37 | Config AvmCore::config; 38 | static GC _gc; 39 | GC* AvmCore::gc = &_gc; 40 | GCHeap GC::heap; 41 | String* AvmCore::k_str[] = { (String*)"" }; 42 | 43 | #ifdef _DEBUG 44 | // NanoAssertFail matches JS_Assert in jsutil.cpp. 45 | void NanoAssertFail() 46 | { 47 | #if defined(WIN32) 48 | DebugBreak(); 49 | exit(3); 50 | #elif defined(XP_OS2) || (defined(__GNUC__) && defined(__i386)) 51 | asm("int $3"); 52 | #endif 53 | 54 | abort(); 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /example/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "jstypes.h" 4 | #include "nanojit.h" 5 | 6 | using namespace nanojit; 7 | using namespace std; 8 | 9 | const uint32_t CACHE_SIZE_LOG2 = 20; 10 | 11 | #if defined(NJ_VERBOSE) 12 | void 13 | nanojit::LirNameMap::formatGuard(LIns *i, char *out) 14 | { 15 | } 16 | #endif 17 | 18 | void nanojit::Fragment::onDestroy() { 19 | } 20 | 21 | int nanojit::StackFilter::getTop(LInsp guard) 22 | { 23 | return 0; 24 | } 25 | 26 | int main() 27 | { 28 | // Set up the basic Nanojit objects. 29 | avmplus::GC *gc = new avmplus::GC; 30 | if (!gc) 31 | return 1; 32 | avmplus::AvmCore core; 33 | 34 | #ifdef DEBUG 35 | core.config.verbose = 1; // Show disassembly of generated traces. 36 | #endif 37 | Fragmento *fragmento = new (gc) Fragmento(&core, CACHE_SIZE_LOG2); 38 | LirBuffer *buf = new (gc) LirBuffer(fragmento, NULL); 39 | 40 | // Create a Fragment to hold some native code. 41 | Fragment *f = new (gc) Fragment(NULL); 42 | f->lirbuf = buf; 43 | f->root = f; 44 | 45 | // Create a LIR writer, with verbose output if DEBUG. 46 | LirBufWriter writer0(buf); 47 | 48 | #ifdef DEBUG 49 | fragmento->labels = new (gc) LabelMap(&core, NULL); 50 | buf->names = new (gc) LirNameMap(gc, NULL, fragmento->labels); 51 | VerboseWriter writer(gc, &writer0, buf->names); 52 | #else 53 | LirBufWriter& writer = writer0; 54 | 55 | #endif 56 | 57 | // Write a few LIR instructions to the buffer: add the first parameter 58 | // to the constant 2. 59 | writer.ins0(LIR_start); 60 | LIns *two = writer.insImm(2); 61 | LIns *firstParam = writer.insParam(0, 0); 62 | LIns *result = writer.ins2(LIR_add, firstParam, two); 63 | writer.ins1(LIR_ret, result); 64 | 65 | // Emit a LIR_loop instruction. It won't be reached, but there's 66 | // an assertion in Nanojit that trips if a fragment doesn't end with 67 | // a guard (a bug in Nanojit). 68 | LIns *rec_ins = writer0.insSkip(sizeof(GuardRecord) + sizeof(SideExit)); 69 | GuardRecord *guard = (GuardRecord *) rec_ins->payload(); 70 | memset(guard, 0, sizeof(*guard)); 71 | SideExit *exit = (SideExit *)(guard + 1); 72 | guard->exit = exit; 73 | guard->exit->target = f; 74 | f->lastIns = writer.insGuard(LIR_loop, writer.insImm(1), rec_ins); 75 | 76 | // Compile the fragment. 77 | compile(fragmento->assm(), f); 78 | if (fragmento->assm()->error() != None) { 79 | fprintf(stderr, "error compiling fragment\n"); 80 | return 1; 81 | } 82 | printf("Compilation successful.\n"); 83 | 84 | // Call the compiled function. 85 | typedef JS_FASTCALL int32_t (*AddTwoFn)(int32_t); 86 | AddTwoFn fn = reinterpret_cast(f->code()); 87 | printf("2 + 5 = %d\n", fn(5)); 88 | 89 | delete buf; 90 | delete f; 91 | #ifdef DEBUG 92 | delete fragmento->labels; 93 | #endif 94 | delete fragmento; 95 | delete gc; 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /example/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -include mozilla-config.h 2 | 3 | all: example 4 | 5 | example: example.o 6 | g++ -o example example.o ../libnanojit.a 7 | 8 | example.o: example.cpp 9 | g++ -c -I.. $(CFLAGS) -o example.o example.cpp 10 | 11 | clean: 12 | rm example.o 13 | rm example -------------------------------------------------------------------------------- /js-config.h: -------------------------------------------------------------------------------- 1 | /* js-config.h. Generated automatically by configure. */ 2 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 3 | * vim: set ts=8 sw=4 et tw=78: 4 | * 5 | * ***** BEGIN LICENSE BLOCK ***** 6 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 7 | * 8 | * The contents of this file are subject to the Mozilla Public License Version 9 | * 1.1 (the "License"); you may not use this file except in compliance with 10 | * the License. You may obtain a copy of the License at 11 | * http://www.mozilla.org/MPL/ 12 | * 13 | * Software distributed under the License is distributed on an "AS IS" basis, 14 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 15 | * for the specific language governing rights and limitations under the 16 | * License. 17 | * 18 | * The Original Code is Mozilla Communicator client code, released 19 | * March 31, 1998. 20 | * 21 | * The Initial Developer of the Original Code is 22 | * Netscape Communications Corporation. 23 | * Portions created by the Initial Developer are Copyright (C) 1998 24 | * the Initial Developer. All Rights Reserved. 25 | * 26 | * Contributor(s): 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * either of the GNU General Public License Version 2 or later (the "GPL"), 30 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 31 | * in which case the provisions of the GPL or the LGPL are applicable instead 32 | * of those above. If you wish to allow use of your version of this file only 33 | * under the terms of either the GPL or the LGPL, and not to allow others to 34 | * use your version of this file under the terms of the MPL, indicate your 35 | * decision by deleting the provisions above and replace them with the notice 36 | * and other provisions required by the GPL or the LGPL. If you do not delete 37 | * the provisions above, a recipient may use your version of this file under 38 | * the terms of any one of the MPL, the GPL or the LGPL. 39 | * 40 | * ***** END LICENSE BLOCK ***** */ 41 | 42 | #ifndef js_config_h___ 43 | #define js_config_h___ 44 | 45 | #define FEATURE_NANOJIT 1 46 | 47 | /* Definitions set at build time that affect SpiderMonkey's public API. 48 | This header file is generated by the SpiderMonkey configure script, 49 | and installed along with jsapi.h. */ 50 | 51 | /* Define to 1 if SpiderMonkey should support multi-threaded clients. */ 52 | #define JS_THREADSAFE 1 53 | 54 | /* Define to 1 if SpiderMonkey should support the ability to perform 55 | entirely too much GC. */ 56 | /* #undef JS_GC_ZEAL */ 57 | 58 | /* Define to 1 if the standard header is present and 59 | useable. See jstypes.h and jsstdint.h. */ 60 | #define JS_HAVE_STDINT_H 1 61 | 62 | /* Define to 1 if the N-byte __intN types are defined by the 63 | compiler. */ 64 | /* #undef JS_HAVE___INTN */ 65 | 66 | /* Define to 1 if #including provides definitions for 67 | intptr_t and uintptr_t. */ 68 | /* #undef JS_STDDEF_H_HAS_INTPTR_T */ 69 | 70 | /* Define to 1 if #including provides definitions for 71 | intptr_t and uintptr_t. */ 72 | /* #undef JS_CRTDEFS_H_HAS_INTPTR_T */ 73 | 74 | /* The configure script defines these if it doesn't #define 75 | JS_HAVE_STDINT_H. */ 76 | /* #undef JS_INT8_TYPE */ 77 | /* #undef JS_INT16_TYPE */ 78 | /* #undef JS_INT32_TYPE */ 79 | /* #undef JS_INT64_TYPE */ 80 | /* #undef JS_INTPTR_TYPE */ 81 | #define JS_BYTES_PER_WORD 4 82 | 83 | /* Some mozilla code uses JS-friend APIs that depend on JS_TRACER being 84 | correct. */ 85 | #define JS_TRACER 1 86 | 87 | #endif /* js_config_h___ */ 88 | -------------------------------------------------------------------------------- /jsautocfg.h: -------------------------------------------------------------------------------- 1 | #ifndef js_cpucfg___ 2 | #define js_cpucfg___ 3 | 4 | /* AUTOMATICALLY GENERATED - DO NOT EDIT */ 5 | 6 | #define IS_LITTLE_ENDIAN 1 7 | #undef IS_BIG_ENDIAN 8 | 9 | #define JS_STACK_GROWTH_DIRECTION (-1) 10 | #endif /* js_cpucfg___ */ 11 | -------------------------------------------------------------------------------- /jsinttypes.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released 16 | * May 28, 2008. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Jim Blandy 20 | * Portions created by the Initial Developer are Copyright (C) 2009 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Alternatively, the contents of this file may be used under the terms of 24 | * either of the GNU General Public License Version 2 or later (the "GPL"), 25 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 26 | * in which case the provisions of the GPL or the LGPL are applicable instead 27 | * of those above. If you wish to allow use of your version of this file only 28 | * under the terms of either the GPL or the LGPL, and not to allow others to 29 | * use your version of this file under the terms of the MPL, indicate your 30 | * decision by deleting the provisions above and replace them with the notice 31 | * and other provisions required by the GPL or the LGPL. If you do not delete 32 | * the provisions above, a recipient may use your version of this file under 33 | * the terms of any one of the MPL, the GPL or the LGPL. 34 | * 35 | * ***** END LICENSE BLOCK ***** */ 36 | 37 | #ifndef jsinttypes_h___ 38 | #define jsinttypes_h___ 39 | 40 | #include "js-config.h" 41 | 42 | /* 43 | * Types: 44 | * JSInt, JSUint (for = 8, 16, 32, and 64) 45 | * JSIntPtr, JSUIntPtr 46 | * 47 | * JSInt and JSUint are signed and unsigned types known to be 48 | * bits long. Note that neither JSInt8 nor JSUInt8 is necessarily 49 | * equivalent to a plain "char". 50 | * 51 | * JSIntPtr and JSUintPtr are signed and unsigned types capable of 52 | * holding an object pointer. 53 | * 54 | * Use these types in public SpiderMonkey header files, not the 55 | * corresponding types from the C standard header. Windows 56 | * doesn't support , and Microsoft says it has no plans to 57 | * do so in the future; this means that projects that embed 58 | * SpiderMonkey often take matters into their own hands and define the 59 | * standard types themselves. If we define them in our public 60 | * headers, our definitions may conflict with embedders' (see bug 61 | * 479258). The JS* types are in our namespace, and can be used 62 | * without troubling anyone. 63 | * 64 | * Internal SpiderMonkey code wishing to use the type names ISO C 65 | * defines in the standard header can #include 66 | * "jsstdint.h", which provides those types regardless of whether 67 | * itself is available. 68 | */ 69 | 70 | #if defined(JS_HAVE_STDINT_H) 71 | 72 | #include 73 | 74 | typedef int8_t JSInt8; 75 | typedef int16_t JSInt16; 76 | typedef int32_t JSInt32; 77 | typedef int64_t JSInt64; 78 | typedef intptr_t JSIntPtr; 79 | 80 | typedef uint8_t JSUint8; 81 | typedef uint16_t JSUint16; 82 | typedef uint32_t JSUint32; 83 | typedef uint64_t JSUint64; 84 | typedef uintptr_t JSUintPtr; 85 | 86 | #else 87 | 88 | #if defined(JS_HAVE___INTN) 89 | 90 | typedef __int8 JSInt8; 91 | typedef __int16 JSInt16; 92 | typedef __int32 JSInt32; 93 | typedef __int64 JSInt64; 94 | 95 | typedef unsigned __int8 JSUint8; 96 | typedef unsigned __int16 JSUint16; 97 | typedef unsigned __int32 JSUint32; 98 | typedef unsigned __int64 JSUint64; 99 | 100 | #elif defined(JS_INT8_TYPE) 101 | 102 | typedef signed JS_INT8_TYPE JSInt8; 103 | typedef signed JS_INT16_TYPE JSInt16; 104 | typedef signed JS_INT32_TYPE JSInt32; 105 | typedef signed JS_INT64_TYPE JSInt64; 106 | 107 | typedef unsigned JS_INT8_TYPE JSUint8; 108 | typedef unsigned JS_INT16_TYPE JSUint16; 109 | typedef unsigned JS_INT32_TYPE JSUint32; 110 | typedef unsigned JS_INT64_TYPE JSUint64; 111 | 112 | #else 113 | #error "couldn't find exact-width integer types" 114 | #endif 115 | 116 | /* Microsoft Visual C/C++ defines intptr_t and uintptr_t in . */ 117 | #if defined(JS_STDDEF_H_HAS_INTPTR_T) 118 | #include 119 | typedef intptr_t JSIntPtr; 120 | typedef uintptr_t JSUintPtr; 121 | 122 | /* Windows Mobile defines intptr_t and uintptr_t in . Why not? */ 123 | #elif defined(JS_CRTDEFS_H_HAS_INTPTR_T) 124 | #include 125 | typedef intptr_t JSIntPtr; 126 | typedef uintptr_t JSUintPtr; 127 | 128 | /* Failing that, the configure script will have found something. */ 129 | #elif defined(JS_INTPTR_TYPE) 130 | typedef signed JS_INTPTR_TYPE JSIntPtr; 131 | typedef unsigned JS_INTPTR_TYPE JSUintPtr; 132 | 133 | #else 134 | #error "couldn't find pointer-sized integer types" 135 | #endif 136 | 137 | #endif /* JS_HAVE_STDINT_H */ 138 | 139 | #endif /* jsinttypes_h___ */ 140 | -------------------------------------------------------------------------------- /jsotypes.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla Communicator client code, released 16 | * March 31, 1998. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Netscape Communications Corporation. 20 | * Portions created by the Initial Developer are Copyright (C) 1998 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either of the GNU General Public License Version 2 or later (the "GPL"), 27 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | /* 40 | * This section typedefs the old 'native' types to the new PRs. 41 | * These definitions are scheduled to be eliminated at the earliest 42 | * possible time. The NSPR API is implemented and documented using 43 | * the new definitions. 44 | */ 45 | 46 | /* 47 | * Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid 48 | * double-definitions of scalar types such as uint32, if NSPR's 49 | * protypes.h is also included. 50 | */ 51 | #ifndef PROTYPES_H 52 | #define PROTYPES_H 53 | 54 | #ifdef XP_BEOS 55 | /* BeOS defines most int types in SupportDefs.h (int8, uint8, int16, 56 | * uint16, int32, uint32, int64, uint64), so in the interest of 57 | * not conflicting with other definitions elsewhere we have to skip the 58 | * #ifdef jungle below, duplicate some definitions, and do our stuff. 59 | */ 60 | #include 61 | 62 | typedef JSUintn uintn; 63 | #ifndef _XP_Core_ 64 | typedef JSIntn intn; 65 | #endif 66 | 67 | #else 68 | 69 | /* SVR4 typedef of uint is commonly found on UNIX machines. */ 70 | #ifdef XP_UNIX 71 | #include 72 | #else 73 | typedef JSUintn uint; 74 | #endif 75 | 76 | typedef JSUintn uintn; 77 | typedef JSUint64 uint64; 78 | #if !defined(_WIN32) && !defined(XP_OS2) 79 | typedef JSUint32 uint32; 80 | #else 81 | typedef unsigned long uint32; 82 | #endif 83 | typedef JSUint16 uint16; 84 | typedef JSUint8 uint8; 85 | 86 | #ifndef _XP_Core_ 87 | typedef JSIntn intn; 88 | #endif 89 | 90 | /* 91 | * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very 92 | * common header file) defines the types int8, int16, int32, and int64. 93 | * So we don't define these four types here to avoid conflicts in case 94 | * the code also includes sys/types.h. 95 | */ 96 | #if defined(AIX) && defined(HAVE_SYS_INTTYPES_H) 97 | #include 98 | #else 99 | typedef JSInt64 int64; 100 | 101 | /* /usr/include/model.h on HP-UX defines int8, int16, and int32 */ 102 | #ifdef HPUX 103 | #include 104 | #else 105 | #if !defined(_WIN32) && !defined(XP_OS2) 106 | typedef JSInt32 int32; 107 | #else 108 | typedef long int32; 109 | #endif 110 | typedef JSInt16 int16; 111 | typedef JSInt8 int8; 112 | #endif /* HPUX */ 113 | #endif /* AIX && HAVE_SYS_INTTYPES_H */ 114 | 115 | #endif /* XP_BEOS */ 116 | 117 | typedef JSFloat64 float64; 118 | 119 | /* Re: jsbit.h */ 120 | #define TEST_BIT JS_TEST_BIT 121 | #define SET_BIT JS_SET_BIT 122 | #define CLEAR_BIT JS_CLEAR_BIT 123 | 124 | /* Re: prarena.h->plarena.h */ 125 | #define PRArena PLArena 126 | #define PRArenaPool PLArenaPool 127 | #define PRArenaStats PLArenaStats 128 | #define PR_ARENA_ALIGN PL_ARENA_ALIGN 129 | #define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL 130 | #define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE 131 | #define PR_ARENA_GROW PL_ARENA_GROW 132 | #define PR_ARENA_MARK PL_ARENA_MARK 133 | #define PR_CLEAR_UNUSED PL_CLEAR_UNUSED 134 | #define PR_CLEAR_ARENA PL_CLEAR_ARENA 135 | #define PR_ARENA_RELEASE PL_ARENA_RELEASE 136 | #define PR_COUNT_ARENA PL_COUNT_ARENA 137 | #define PR_ARENA_DESTROY PL_ARENA_DESTROY 138 | #define PR_InitArenaPool PL_InitArenaPool 139 | #define PR_FreeArenaPool PL_FreeArenaPool 140 | #define PR_FinishArenaPool PL_FinishArenaPool 141 | #define PR_CompactArenaPool PL_CompactArenaPool 142 | #define PR_ArenaFinish PL_ArenaFinish 143 | #define PR_ArenaAllocate PL_ArenaAllocate 144 | #define PR_ArenaGrow PL_ArenaGrow 145 | #define PR_ArenaRelease PL_ArenaRelease 146 | #define PR_ArenaCountAllocation PL_ArenaCountAllocation 147 | #define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth 148 | #define PR_ArenaCountGrowth PL_ArenaCountGrowth 149 | #define PR_ArenaCountRelease PL_ArenaCountRelease 150 | #define PR_ArenaCountRetract PL_ArenaCountRetract 151 | 152 | /* Re: prevent.h->plevent.h */ 153 | #define PREvent PLEvent 154 | #define PREventQueue PLEventQueue 155 | #define PR_CreateEventQueue PL_CreateEventQueue 156 | #define PR_DestroyEventQueue PL_DestroyEventQueue 157 | #define PR_GetEventQueueMonitor PL_GetEventQueueMonitor 158 | #define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR 159 | #define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR 160 | #define PR_PostEvent PL_PostEvent 161 | #define PR_PostSynchronousEvent PL_PostSynchronousEvent 162 | #define PR_GetEvent PL_GetEvent 163 | #define PR_EventAvailable PL_EventAvailable 164 | #define PREventFunProc PLEventFunProc 165 | #define PR_MapEvents PL_MapEvents 166 | #define PR_RevokeEvents PL_RevokeEvents 167 | #define PR_ProcessPendingEvents PL_ProcessPendingEvents 168 | #define PR_WaitForEvent PL_WaitForEvent 169 | #define PR_EventLoop PL_EventLoop 170 | #define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD 171 | #define PRHandleEventProc PLHandleEventProc 172 | #define PRDestroyEventProc PLDestroyEventProc 173 | #define PR_InitEvent PL_InitEvent 174 | #define PR_GetEventOwner PL_GetEventOwner 175 | #define PR_HandleEvent PL_HandleEvent 176 | #define PR_DestroyEvent PL_DestroyEvent 177 | #define PR_DequeueEvent PL_DequeueEvent 178 | #define PR_GetMainEventQueue PL_GetMainEventQueue 179 | 180 | /* Re: prhash.h->plhash.h */ 181 | #define PRHashEntry PLHashEntry 182 | #define PRHashTable PLHashTable 183 | #define PRHashNumber PLHashNumber 184 | #define PRHashFunction PLHashFunction 185 | #define PRHashComparator PLHashComparator 186 | #define PRHashEnumerator PLHashEnumerator 187 | #define PRHashAllocOps PLHashAllocOps 188 | #define PR_NewHashTable PL_NewHashTable 189 | #define PR_HashTableDestroy PL_HashTableDestroy 190 | #define PR_HashTableRawLookup PL_HashTableRawLookup 191 | #define PR_HashTableRawAdd PL_HashTableRawAdd 192 | #define PR_HashTableRawRemove PL_HashTableRawRemove 193 | #define PR_HashTableAdd PL_HashTableAdd 194 | #define PR_HashTableRemove PL_HashTableRemove 195 | #define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries 196 | #define PR_HashTableLookup PL_HashTableLookup 197 | #define PR_HashTableDump PL_HashTableDump 198 | #define PR_HashString PL_HashString 199 | #define PR_CompareStrings PL_CompareStrings 200 | #define PR_CompareValues PL_CompareValues 201 | 202 | #endif /* !defined(PROTYPES_H) */ 203 | -------------------------------------------------------------------------------- /jsstdint.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * vim: set ts=8 sw=4 et tw=78: 3 | * 4 | * ***** BEGIN LICENSE BLOCK ***** 5 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 | * 7 | * The contents of this file are subject to the Mozilla Public License Version 8 | * 1.1 (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * http://www.mozilla.org/MPL/ 11 | * 12 | * Software distributed under the License is distributed on an "AS IS" basis, 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 | * for the specific language governing rights and limitations under the 15 | * License. 16 | * 17 | * The Original Code is mozilla.org code. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Jim Blandy 21 | * Portions created by the Initial Developer are Copyright (C) 2008 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * This header provides definitions for the types we use, 42 | * even on systems that lack . 43 | * 44 | * NOTE: This header should only be included in private SpiderMonkey 45 | * code; public headers should use only the JS{Int,Uint}N types; see 46 | * the comment for them in "jsinttypes.h". 47 | * 48 | * At the moment, these types are not widely used within SpiderMonkey; 49 | * this file is meant to make existing uses portable, and to allow us 50 | * to transition portably to using them more, if desired. 51 | */ 52 | 53 | #ifndef jsstdint_h___ 54 | #define jsstdint_h___ 55 | 56 | #include "jsinttypes.h" 57 | 58 | /* If we have a working stdint.h, then jsinttypes.h has already 59 | defined the standard integer types. Otherwise, define the standard 60 | names in terms of the 'JS' types. */ 61 | #if ! defined(JS_HAVE_STDINT_H) 62 | 63 | typedef JSInt8 int8_t; 64 | typedef JSInt16 int16_t; 65 | typedef JSInt32 int32_t; 66 | typedef JSInt64 int64_t; 67 | 68 | typedef JSUint8 uint8_t; 69 | typedef JSUint16 uint16_t; 70 | typedef JSUint32 uint32_t; 71 | typedef JSUint64 uint64_t; 72 | 73 | /* If JS_STDDEF_H_HAS_INTPTR_T or JS_CRTDEFS_H_HAS_INTPTR_T are 74 | defined, then jsinttypes.h included the given header, which 75 | introduced definitions for intptr_t and uintptr_t. Otherwise, 76 | define the standard names in terms of the 'JS' types. */ 77 | #if !defined(JS_STDDEF_H_HAS_INTPTR_T) && !defined(JS_CRTDEFS_H_HAS_INTPTR_T) 78 | typedef JSIntPtr intptr_t; 79 | typedef JSUintPtr uintptr_t; 80 | #endif 81 | 82 | #endif /* JS_HAVE_STDINT_H */ 83 | 84 | #endif /* jsstdint_h___ */ 85 | -------------------------------------------------------------------------------- /jstypes.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla Communicator client code, released 16 | * March 31, 1998. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Netscape Communications Corporation. 20 | * Portions created by the Initial Developer are Copyright (C) 1998 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * IBM Corp. 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | ** File: jstypes.h 42 | ** Description: Definitions of NSPR's basic types 43 | ** 44 | ** Prototypes and macros used to make up for deficiencies in ANSI environments 45 | ** that we have found. 46 | ** 47 | ** Since we do not wrap and all the other standard headers, authors 48 | ** of portable code will not know in general that they need these definitions. 49 | ** Instead of requiring these authors to find the dependent uses in their code 50 | ** and take the following steps only in those C files, we take steps once here 51 | ** for all C files. 52 | **/ 53 | 54 | #ifndef jstypes_h___ 55 | #define jstypes_h___ 56 | 57 | #include 58 | #include "js-config.h" 59 | 60 | /*********************************************************************** 61 | ** MACROS: JS_EXTERN_API 62 | ** JS_EXPORT_API 63 | ** DESCRIPTION: 64 | ** These are only for externally visible routines and globals. For 65 | ** internal routines, just use "extern" for type checking and that 66 | ** will not export internal cross-file or forward-declared symbols. 67 | ** Define a macro for declaring procedures return types. We use this to 68 | ** deal with windoze specific type hackery for DLL definitions. Use 69 | ** JS_EXTERN_API when the prototype for the method is declared. Use 70 | ** JS_EXPORT_API for the implementation of the method. 71 | ** 72 | ** Example: 73 | ** in dowhim.h 74 | ** JS_EXTERN_API( void ) DoWhatIMean( void ); 75 | ** in dowhim.c 76 | ** JS_EXPORT_API( void ) DoWhatIMean( void ) { return; } 77 | ** 78 | ** 79 | ***********************************************************************/ 80 | #ifdef WIN32 81 | 82 | /* These also work for __MWERKS__ */ 83 | # define JS_EXTERN_API(__type) extern __declspec(dllexport) __type 84 | # define JS_EXPORT_API(__type) __declspec(dllexport) __type 85 | # define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type 86 | # define JS_EXPORT_DATA(__type) __declspec(dllexport) __type 87 | 88 | #elif defined(XP_OS2) && defined(__declspec) 89 | 90 | # define JS_EXTERN_API(__type) extern __declspec(dllexport) __type 91 | # define JS_EXPORT_API(__type) __declspec(dllexport) __type 92 | # define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type 93 | # define JS_EXPORT_DATA(__type) __declspec(dllexport) __type 94 | 95 | #else /* Unix */ 96 | 97 | # ifdef HAVE_VISIBILITY_ATTRIBUTE 98 | # define JS_EXTERNAL_VIS __attribute__((visibility ("default"))) 99 | # elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 100 | # define JS_EXTERNAL_VIS __global 101 | # else 102 | # define JS_EXTERNAL_VIS 103 | # endif 104 | 105 | # define JS_EXTERN_API(__type) extern JS_EXTERNAL_VIS __type 106 | # define JS_EXPORT_API(__type) JS_EXTERNAL_VIS __type 107 | # define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type 108 | # define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type 109 | 110 | #endif 111 | 112 | #ifdef _WIN32 113 | # if defined(__MWERKS__) || defined(__GNUC__) 114 | # define JS_IMPORT_API(__x) __x 115 | # else 116 | # define JS_IMPORT_API(__x) __declspec(dllimport) __x 117 | # endif 118 | #elif defined(XP_OS2) && defined(__declspec) 119 | # define JS_IMPORT_API(__x) __declspec(dllimport) __x 120 | #else 121 | # define JS_IMPORT_API(__x) JS_EXPORT_API (__x) 122 | #endif 123 | 124 | #if defined(_WIN32) && !defined(__MWERKS__) 125 | # define JS_IMPORT_DATA(__x) __declspec(dllimport) __x 126 | #elif defined(XP_OS2) && defined(__declspec) 127 | # define JS_IMPORT_DATA(__x) __declspec(dllimport) __x 128 | #else 129 | # define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x) 130 | #endif 131 | 132 | /* 133 | * The linkage of JS API functions differs depending on whether the file is 134 | * used within the JS library or not. Any source file within the JS 135 | * interpreter should define EXPORT_JS_API whereas any client of the library 136 | * should not. STATIC_JS_API is used to build JS as a static library. 137 | */ 138 | #if defined(STATIC_JS_API) 139 | 140 | # define JS_PUBLIC_API(t) t 141 | # define JS_PUBLIC_DATA(t) t 142 | 143 | #elif defined(EXPORT_JS_API) 144 | 145 | # define JS_PUBLIC_API(t) JS_EXPORT_API(t) 146 | # define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t) 147 | 148 | #else 149 | 150 | # define JS_PUBLIC_API(t) JS_IMPORT_API(t) 151 | # define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t) 152 | 153 | #endif 154 | 155 | #define JS_FRIEND_API(t) JS_PUBLIC_API(t) 156 | #define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t) 157 | 158 | #if defined(_MSC_VER) && defined(_M_IX86) 159 | #define JS_FASTCALL __fastcall 160 | #elif defined(__GNUC__) && defined(__i386__) && \ 161 | ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) 162 | #define JS_FASTCALL __attribute__((fastcall)) 163 | #else 164 | #define JS_FASTCALL 165 | #define JS_NO_FASTCALL 166 | #endif 167 | 168 | #ifndef JS_INLINE 169 | # if defined __cplusplus 170 | # define JS_INLINE inline 171 | # elif defined _MSC_VER 172 | # define JS_INLINE __inline 173 | # elif defined __GNUC__ 174 | # define JS_INLINE __inline__ 175 | # else 176 | # define JS_INLINE inline 177 | # endif 178 | #endif 179 | 180 | #ifndef JS_ALWAYS_INLINE 181 | # if defined DEBUG 182 | # define JS_ALWAYS_INLINE JS_INLINE 183 | # elif defined _MSC_VER 184 | # define JS_ALWAYS_INLINE __forceinline 185 | # elif defined __GNUC__ 186 | # define JS_ALWAYS_INLINE __attribute__((always_inline)) JS_INLINE 187 | # else 188 | # define JS_ALWAYS_INLINE JS_INLINE 189 | # endif 190 | #endif 191 | 192 | #ifdef NS_STATIC_CHECKING 193 | /* 194 | * Attributes for static analysis. Functions declared with JS_REQUIRES_STACK 195 | * always have a valid cx->fp and can access it freely. Other functions can 196 | * access cx->fp only after calling a function that "forces" the stack 197 | * (i.e. lazily instantiates it as needed). 198 | */ 199 | # define JS_REQUIRES_STACK __attribute__((user("JS_REQUIRES_STACK"))) 200 | # define JS_FORCES_STACK __attribute__((user("JS_FORCES_STACK"))) 201 | #else 202 | # define JS_REQUIRES_STACK 203 | # define JS_FORCES_STACK 204 | #endif 205 | 206 | /*********************************************************************** 207 | ** MACROS: JS_BEGIN_MACRO 208 | ** JS_END_MACRO 209 | ** DESCRIPTION: 210 | ** Macro body brackets so that macros with compound statement definitions 211 | ** behave syntactically more like functions when called. 212 | ***********************************************************************/ 213 | #define JS_BEGIN_MACRO do { 214 | 215 | #if defined(_MSC_VER) && _MSC_VER >= 1400 216 | # define JS_END_MACRO \ 217 | } __pragma(warning(push)) __pragma(warning(disable:4127)) \ 218 | while (0) __pragma(warning(pop)) 219 | #else 220 | # define JS_END_MACRO } while (0) 221 | #endif 222 | 223 | /*********************************************************************** 224 | ** MACROS: JS_BEGIN_EXTERN_C 225 | ** JS_END_EXTERN_C 226 | ** DESCRIPTION: 227 | ** Macro shorthands for conditional C++ extern block delimiters. 228 | ***********************************************************************/ 229 | #ifdef __cplusplus 230 | 231 | # define JS_BEGIN_EXTERN_C extern "C" { 232 | # define JS_END_EXTERN_C } 233 | 234 | #else 235 | 236 | # define JS_BEGIN_EXTERN_C 237 | # define JS_END_EXTERN_C 238 | 239 | #endif 240 | 241 | /*********************************************************************** 242 | ** MACROS: JS_BIT 243 | ** JS_BITMASK 244 | ** DESCRIPTION: 245 | ** Bit masking macros. XXX n must be <= 31 to be portable 246 | ***********************************************************************/ 247 | #define JS_BIT(n) ((JSUint32)1 << (n)) 248 | #define JS_BITMASK(n) (JS_BIT(n) - 1) 249 | 250 | /*********************************************************************** 251 | ** MACROS: JS_PTR_TO_INT32 252 | ** JS_PTR_TO_UINT32 253 | ** JS_INT32_TO_PTR 254 | ** JS_UINT32_TO_PTR 255 | ** DESCRIPTION: 256 | ** Integer to pointer and pointer to integer conversion macros. 257 | ***********************************************************************/ 258 | #define JS_PTR_TO_INT32(x) ((jsint)((char *)(x) - (char *)0)) 259 | #define JS_PTR_TO_UINT32(x) ((jsuint)((char *)(x) - (char *)0)) 260 | #define JS_INT32_TO_PTR(x) ((void *)((char *)0 + (jsint)(x))) 261 | #define JS_UINT32_TO_PTR(x) ((void *)((char *)0 + (jsuint)(x))) 262 | 263 | /*********************************************************************** 264 | ** MACROS: JS_HOWMANY 265 | ** JS_ROUNDUP 266 | ** JS_MIN 267 | ** JS_MAX 268 | ** DESCRIPTION: 269 | ** Commonly used macros for operations on compatible types. 270 | ***********************************************************************/ 271 | #define JS_HOWMANY(x,y) (((x)+(y)-1)/(y)) 272 | #define JS_ROUNDUP(x,y) (JS_HOWMANY(x,y)*(y)) 273 | #define JS_MIN(x,y) ((x)<(y)?(x):(y)) 274 | #define JS_MAX(x,y) ((x)>(y)?(x):(y)) 275 | 276 | #ifdef _MSC_VER 277 | # include "jscpucfg.h" /* We can't auto-detect MSVC configuration */ 278 | #else 279 | # include "jsautocfg.h" /* Use auto-detected configuration */ 280 | #endif 281 | 282 | #include "jsinttypes.h" 283 | 284 | JS_BEGIN_EXTERN_C 285 | 286 | /************************************************************************ 287 | ** TYPES: JSUintn 288 | ** JSIntn 289 | ** DESCRIPTION: 290 | ** The JSIntn types are most appropriate for automatic variables. They are 291 | ** guaranteed to be at least 16 bits, though various architectures may 292 | ** define them to be wider (e.g., 32 or even 64 bits). These types are 293 | ** never valid for fields of a structure. 294 | ************************************************************************/ 295 | 296 | typedef int JSIntn; 297 | typedef unsigned int JSUintn; 298 | 299 | /************************************************************************ 300 | ** TYPES: JSFloat64 301 | ** DESCRIPTION: 302 | ** NSPR's floating point type is always 64 bits. 303 | ************************************************************************/ 304 | typedef double JSFloat64; 305 | 306 | /************************************************************************ 307 | ** TYPES: JSSize 308 | ** DESCRIPTION: 309 | ** A type for representing the size of objects. 310 | ************************************************************************/ 311 | typedef size_t JSSize; 312 | 313 | /************************************************************************ 314 | ** TYPES: JSPtrDiff 315 | ** DESCRIPTION: 316 | ** A type for pointer difference. Variables of this type are suitable 317 | ** for storing a pointer or pointer sutraction. 318 | ************************************************************************/ 319 | typedef ptrdiff_t JSPtrdiff; 320 | 321 | /************************************************************************ 322 | ** TYPES: JSUptrdiff 323 | ** DESCRIPTION: 324 | ** A type for pointer difference. Variables of this type are suitable 325 | ** for storing a pointer or pointer sutraction. 326 | ************************************************************************/ 327 | typedef JSUintPtr JSUptrdiff; 328 | 329 | /************************************************************************ 330 | ** TYPES: JSBool 331 | ** DESCRIPTION: 332 | ** Use JSBool for variables and parameter types. Use JS_FALSE and JS_TRUE 333 | ** for clarity of target type in assignments and actual arguments. Use 334 | ** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans 335 | ** just as you would C int-valued conditions. 336 | ************************************************************************/ 337 | typedef JSIntn JSBool; 338 | #define JS_TRUE (JSIntn)1 339 | #define JS_FALSE (JSIntn)0 340 | 341 | /************************************************************************ 342 | ** TYPES: JSPackedBool 343 | ** DESCRIPTION: 344 | ** Use JSPackedBool within structs where bitfields are not desireable 345 | ** but minimum and consistent overhead matters. 346 | ************************************************************************/ 347 | typedef JSUint8 JSPackedBool; 348 | 349 | /* 350 | ** A JSWord is an integer that is the same size as a void* 351 | */ 352 | typedef JSIntPtr JSWord; 353 | typedef JSUintPtr JSUword; 354 | 355 | #include "jsotypes.h" 356 | 357 | /*********************************************************************** 358 | ** MACROS: JS_LIKELY 359 | ** JS_UNLIKELY 360 | ** DESCRIPTION: 361 | ** These macros allow you to give a hint to the compiler about branch 362 | ** probability so that it can better optimize. Use them like this: 363 | ** 364 | ** if (JS_LIKELY(v == 1)) { 365 | ** ... expected code path ... 366 | ** } 367 | ** 368 | ** if (JS_UNLIKELY(v == 0)) { 369 | ** ... non-expected code path ... 370 | ** } 371 | ** 372 | ***********************************************************************/ 373 | #if defined(__GNUC__) && (__GNUC__ > 2) 374 | 375 | # define JS_LIKELY(x) (__builtin_expect((x), 1)) 376 | # define JS_UNLIKELY(x) (__builtin_expect((x), 0)) 377 | 378 | #else 379 | 380 | # define JS_LIKELY(x) (x) 381 | # define JS_UNLIKELY(x) (x) 382 | 383 | #endif 384 | 385 | /*********************************************************************** 386 | ** MACROS: JS_ARRAY_LENGTH 387 | ** JS_ARRAY_END 388 | ** DESCRIPTION: 389 | ** Macros to get the number of elements and the pointer to one past the 390 | ** last element of a C array. Use them like this: 391 | ** 392 | ** jschar buf[10], *s; 393 | ** JSString *str; 394 | ** ... 395 | ** for (s = buf; s != JS_ARRAY_END(buf); ++s) *s = ...; 396 | ** ... 397 | ** str = JS_NewStringCopyN(cx, buf, JS_ARRAY_LENGTH(buf)); 398 | ** ... 399 | ** 400 | ***********************************************************************/ 401 | 402 | #define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0]) 403 | #define JS_ARRAY_END(array) ((array) + JS_ARRAY_LENGTH(array)) 404 | 405 | #define JS_BITS_PER_BYTE 8 406 | #define JS_BITS_PER_BYTE_LOG2 3 407 | 408 | #define JS_BITS_PER_WORD (JS_BITS_PER_BYTE * JS_BYTES_PER_WORD) 409 | #define JS_BITS_PER_DOUBLE (JS_BITS_PER_BYTE * JS_BYTES_PER_DOUBLE) 410 | 411 | /*********************************************************************** 412 | ** MACROS: JS_FUNC_TO_DATA_PTR 413 | ** JS_DATA_TO_FUNC_PTR 414 | ** DESCRIPTION: 415 | ** Macros to convert between function and data pointers assuming that 416 | ** they have the same size. Use them like this: 417 | ** 418 | ** JSPropertyOp nativeGetter; 419 | ** JSObject *scriptedGetter; 420 | ** ... 421 | ** scriptedGetter = JS_FUNC_TO_DATA_PTR(JSObject *, nativeGetter); 422 | ** ... 423 | ** nativeGetter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, scriptedGetter); 424 | ** 425 | ***********************************************************************/ 426 | 427 | #ifdef __GNUC__ 428 | # define JS_FUNC_TO_DATA_PTR(type, fun) (__extension__ (type) (fun)) 429 | # define JS_DATA_TO_FUNC_PTR(type, ptr) (__extension__ (type) (ptr)) 430 | #else 431 | /* Use an extra (void *) cast for MSVC. */ 432 | # define JS_FUNC_TO_DATA_PTR(type, fun) ((type) (void *) (fun)) 433 | # define JS_DATA_TO_FUNC_PTR(type, ptr) ((type) (void *) (ptr)) 434 | #endif 435 | 436 | JS_END_EXTERN_C 437 | 438 | #endif /* jstypes_h___ */ 439 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -include mozilla-config.h 2 | 3 | all: libnanojit.a 4 | 5 | libnanojit.a: Assembler.o Fragmento.o LIR.o Nativei386.o RegAlloc.o avmplus.o 6 | ar r libnanojit.a Assembler.o Fragmento.o LIR.o Nativei386.o RegAlloc.o avmplus.o 7 | 8 | Assembler.o: Assembler.cpp 9 | g++ -c $(CFLAGS) -o Assembler.o Assembler.cpp 10 | 11 | Fragmento.o: Fragmento.cpp 12 | g++ -c $(CFLAGS) -o Fragmento.o Fragmento.cpp 13 | 14 | LIR.o: LIR.cpp 15 | g++ -c $(CFLAGS) -o LIR.o LIR.cpp 16 | 17 | NativeARM.o: NativeARM.cpp 18 | g++ -c $(CFLAGS) -o NativeARM.o NativeARM.cpp 19 | 20 | NativeSparc.o: NativeSparc.cpp 21 | g++ -c $(CFLAGS) -o NativeSparc.o NativeSparc.cpp 22 | 23 | Nativei386.o: Nativei386.cpp 24 | g++ -c $(CFLAGS) -o Nativei386.o Nativei386.cpp 25 | 26 | RegAlloc.o: RegAlloc.cpp 27 | g++ -c $(CFLAGS) -o RegAlloc.o RegAlloc.cpp 28 | 29 | TraceTreeDrawer.o: TraceTreeDrawer.cpp 30 | g++ -c $(CFLAGS) -o TraceTreeDrawer.o TraceTreeDrawer.cpp 31 | 32 | avmplus.o: avmplus.cpp 33 | g++ -c $(CFLAGS) -o avmplus.o avmplus.cpp 34 | 35 | 36 | clean: 37 | rm *.o 38 | rm *.a 39 | -------------------------------------------------------------------------------- /mozilla-config.h: -------------------------------------------------------------------------------- 1 | /* List of defines generated by configure. Included with preprocessor flag, 2 | * -include, to avoid long list of -D defines on the compile command-line. 3 | * Do not edit. 4 | */ 5 | 6 | #ifndef _MOZILLA_CONFIG_H_ 7 | #define _MOZILLA_CONFIG_H_ 8 | 9 | #define AVMPLUS_IA32 1 10 | #define AVMPLUS_LINUX 1 11 | #define AVMPLUS_UNIX 1 12 | #define CPP_THROW_NEW throw() 13 | #define D_INO d_ino 14 | #define EDITLINE 1 15 | #define FEATURE_NANOJIT 1 16 | #define HAVE_CPP_2BYTE_WCHAR_T 1 17 | #define HAVE_CPP_ACCESS_CHANGING_USING 1 18 | #define HAVE_CPP_AMBIGUITY_RESOLVING_USING 1 19 | #define HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR 1 20 | #define HAVE_CPP_EXPLICIT 1 21 | #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX 1 22 | #define HAVE_CPP_NAMESPACE_STD 1 23 | #define HAVE_CPP_NEW_CASTS 1 24 | #define HAVE_CPP_PARTIAL_SPECIALIZATION 1 25 | #define HAVE_CPP_TYPENAME 1 26 | #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL 1 27 | #define HAVE_DIRENT_H 1 28 | #define HAVE_DLADDR 1 29 | #define HAVE_FCHMOD 1 30 | #define HAVE_FLOCKFILE 1 31 | #define HAVE_GETOPT_H 1 32 | #define HAVE_GETPAGESIZE 1 33 | #define HAVE_GNU_GET_LIBC_VERSION 1 34 | #define HAVE_GNU_LIBC_VERSION_H 1 35 | #define HAVE_I18N_LC_MESSAGES 1 36 | #define HAVE_ICONV 1 37 | #define HAVE_INT16_T 1 38 | #define HAVE_INT32_T 1 39 | #define HAVE_INT64_T 1 40 | #define HAVE_LCHOWN 1 41 | #define HAVE_LIBDL 1 42 | #define HAVE_LIBM 1 43 | #define HAVE_LOCALTIME_R 1 44 | #define HAVE_LSTAT64 1 45 | #define HAVE_MALLOC_H 1 46 | #define HAVE_MBRTOWC 1 47 | #define HAVE_MEMMOVE 1 48 | #define HAVE_MEMORY_H 1 49 | #define HAVE_NL_TYPES_H 1 50 | #define HAVE_RANDOM 1 51 | #define HAVE_RES_NINIT 1 52 | #define HAVE_RINT 1 53 | #define HAVE_SETLOCALE 1 54 | #define HAVE_SIGINFO_T 1 55 | #define HAVE_SNPRINTF 1 56 | #define HAVE_STAT64 1 57 | #define HAVE_STATVFS 1 58 | #define HAVE_STATVFS64 1 59 | #define HAVE_STRERROR 1 60 | #define HAVE_STRTOK_R 1 61 | #define HAVE_ST_BLKSIZE 1 62 | #define HAVE_SYS_BITYPES_H 1 63 | #define HAVE_SYS_CDEFS_H 1 64 | #define HAVE_SYS_MOUNT_H 1 65 | #define HAVE_SYS_STATFS_H 1 66 | #define HAVE_SYS_STATVFS_H 1 67 | #define HAVE_SYS_VFS_H 1 68 | #define HAVE_TM_ZONE_TM_GMTOFF 1 69 | #define HAVE_TRUNCATE64 1 70 | #define HAVE_UINT 1 71 | #define HAVE_UNAME_DOMAINNAME_FIELD 1 72 | #define HAVE_UNISTD_H 1 73 | #define HAVE_VA_COPY 1 74 | #define HAVE_VISIBILITY_ATTRIBUTE 1 75 | #define HAVE_VISIBILITY_HIDDEN_ATTRIBUTE 1 76 | #define HAVE_WCRTOMB 1 77 | #define HAVE_X11_XKBLIB_H 1 78 | #define HAVE__UNWIND_BACKTRACE 1 79 | #define HAVE___CXA_DEMANGLE 1 80 | #define JS_ALIGN_OF_POINTER 4 81 | #define JS_BITS_PER_WORD_LOG2 5 82 | #define JS_BYTES_PER_DOUBLE 8 83 | #define JS_BYTES_PER_WORD 4 84 | #define JS_HAVE_STDINT_H 1 85 | #define JS_THREADSAFE 1 86 | #define JS_TRACER 1 87 | #define MOZ_DEMANGLE_SYMBOLS 1 88 | #define MOZ_DLL_SUFFIX ".so" 89 | #define MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS 1 90 | #define MOZ_MEMORY 1 91 | #define MOZ_MEMORY_DEBUG 1 92 | #define MOZ_MEMORY_LINUX 1 93 | #define MOZ_MEMORY_SIZEOF_PTR_2POW 2 94 | #define MOZ_REFLOW_PERF 1 95 | #define MOZ_REFLOW_PERF_DSP 1 96 | #define NEED_CPP_UNUSED_IMPLEMENTATIONS 1 97 | #define NEW_H 98 | #define SIZEOF_INT_P 4 99 | #define STDC_HEADERS 1 100 | #define UNIX_ASYNC_DNS 1 101 | #define VA_COPY va_copy 102 | #define XP_UNIX 1 103 | #define _REENTRANT 1 104 | 105 | #endif /* _MOZILLA_CONFIG_H_ */ 106 | 107 | -------------------------------------------------------------------------------- /nanojit.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is [Open Source Virtual Machine]. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Adobe System Incorporated. 19 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Adobe AS3 Team 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #ifndef __nanojit_h__ 40 | #define __nanojit_h__ 41 | 42 | #include 43 | #include "avmplus.h" 44 | 45 | #ifdef FEATURE_NANOJIT 46 | 47 | #ifdef AVMPLUS_IA32 48 | #define NANOJIT_IA32 49 | #elif AVMPLUS_ARM 50 | #define NANOJIT_ARM 51 | #elif AVMPLUS_PPC 52 | #define NANOJIT_PPC 53 | #elif AVMPLUS_SPARC 54 | #define NANOJIT_SPARC 55 | #elif AVMPLUS_AMD64 56 | #define NANOJIT_AMD64 57 | #define NANOJIT_64BIT 58 | #else 59 | #error "unknown nanojit architecture" 60 | #endif 61 | 62 | /* 63 | If we're using MMGC, using operator delete on a GCFinalizedObject is problematic: 64 | in particular, calling it from inside a dtor is risky because the dtor for the sub-object 65 | might already have been called, wrecking its vtable and ending up in the wrong version 66 | of operator delete (the global version rather than the class-specific one). Calling GC::Free 67 | directly is fine (since it ignores the vtable), so we macro-ize to make the distinction. 68 | 69 | macro-ization of operator new isn't strictly necessary, but is done to bottleneck both 70 | sides of the new/delete pair to forestall future needs. 71 | */ 72 | #ifdef MMGC_API 73 | 74 | // separate overloads because GCObject and GCFinalizedObjects have different dtors 75 | // (GCFinalizedObject's is virtual, GCObject's is not) 76 | inline void mmgc_delete(GCObject* o) 77 | { 78 | GC* g = GC::GetGC(o); 79 | if (g->Collecting()) 80 | g->Free(o); 81 | else 82 | delete o; 83 | } 84 | 85 | inline void mmgc_delete(GCFinalizedObject* o) 86 | { 87 | GC* g = GC::GetGC(o); 88 | if (g->Collecting()) 89 | g->Free(o); 90 | else 91 | delete o; 92 | } 93 | 94 | #define NJ_NEW(gc, cls) new (gc) cls 95 | #define NJ_DELETE(obj) do { mmgc_delete(obj); } while (0) 96 | #else 97 | #define NJ_NEW(gc, cls) new (gc) cls 98 | #define NJ_DELETE(obj) do { delete obj; } while (0) 99 | #endif 100 | 101 | // Embed no-op macros that let Valgrind work with the JIT. 102 | #ifdef MOZ_VALGRIND 103 | # define JS_VALGRIND 104 | #endif 105 | #ifdef JS_VALGRIND 106 | # include 107 | #else 108 | # define VALGRIND_DISCARD_TRANSLATIONS(addr, szB) 109 | #endif 110 | 111 | namespace nanojit 112 | { 113 | /** 114 | * ------------------------------------------- 115 | * START AVM bridging definitions 116 | * ------------------------------------------- 117 | */ 118 | class Fragment; 119 | class LIns; 120 | struct SideExit; 121 | class RegAlloc; 122 | struct Page; 123 | typedef avmplus::AvmCore AvmCore; 124 | typedef avmplus::OSDep OSDep; 125 | typedef avmplus::GCSortedMap FragmentMap; 126 | typedef avmplus::SortedMap RegAllocMap; 127 | typedef avmplus::List InsList; 128 | typedef avmplus::List StringList; 129 | typedef avmplus::List PageList; 130 | 131 | const uint32_t MAXARGS = 8; 132 | 133 | #if defined(_MSC_VER) && _MSC_VER < 1400 134 | static void NanoAssertMsgf(bool a,const char *f,...) {} 135 | static void NanoAssertMsg(bool a,const char *m) {} 136 | static void NanoAssert(bool a) {} 137 | #elif defined(_DEBUG) 138 | 139 | #define __NanoAssertMsgf(a, file_, line_, f, ...) \ 140 | if (!(a)) { \ 141 | fprintf(stderr, "Assertion failed: " f "%s (%s:%d)\n", __VA_ARGS__, #a, file_, line_); \ 142 | NanoAssertFail(); \ 143 | } 144 | 145 | #define _NanoAssertMsgf(a, file_, line_, f, ...) __NanoAssertMsgf(a, file_, line_, f, __VA_ARGS__) 146 | 147 | #define NanoAssertMsgf(a,f,...) do { __NanoAssertMsgf(a, __FILE__, __LINE__, f ": ", __VA_ARGS__); } while (0) 148 | #define NanoAssertMsg(a,m) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "\"%s\": ", m); } while (0) 149 | #define NanoAssert(a) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "%s", ""); } while (0) 150 | #else 151 | #define NanoAssertMsgf(a,f,...) do { } while (0) /* no semi */ 152 | #define NanoAssertMsg(a,m) do { } while (0) /* no semi */ 153 | #define NanoAssert(a) do { } while (0) /* no semi */ 154 | #endif 155 | 156 | /* 157 | * Sun Studio C++ compiler has a bug 158 | * "sizeof expression not accepted as size of array parameter" 159 | * The bug number is 6688515. It is not public yet. 160 | * Turn off this assert for Sun Studio until this bug is fixed. 161 | */ 162 | #ifdef __SUNPRO_CC 163 | #define NanoStaticAssert(condition) 164 | #else 165 | #define NanoStaticAssert(condition) \ 166 | extern void nano_static_assert(int arg[(condition) ? 1 : -1]) 167 | #endif 168 | 169 | 170 | /** 171 | * ------------------------------------------- 172 | * END AVM bridging definitions 173 | * ------------------------------------------- 174 | */ 175 | } 176 | 177 | #ifdef AVMPLUS_VERBOSE 178 | #define NJ_VERBOSE 1 179 | #define NJ_PROFILE 1 180 | #endif 181 | 182 | #if defined(_MSC_VER) && _MSC_VER < 1400 183 | #include 184 | #define verbose_output if (verbose_enabled()) Assembler::output 185 | #define verbose_outputf if (verbose_enabled()) Assembler::outputf 186 | #define verbose_enabled() (_verbose) 187 | #define verbose_only(x) x 188 | #elif defined(NJ_VERBOSE) 189 | #include 190 | #define verbose_output if (verbose_enabled()) Assembler::output 191 | #define verbose_outputf if (verbose_enabled()) Assembler::outputf 192 | #define verbose_enabled() (_verbose) 193 | #define verbose_only(...) __VA_ARGS__ 194 | #else 195 | #define verbose_output 196 | #define verbose_outputf 197 | #define verbose_enabled() 198 | #define verbose_only(...) 199 | #endif /*NJ_VERBOSE*/ 200 | 201 | #ifdef _DEBUG 202 | #define debug_only(x) x 203 | #else 204 | #define debug_only(x) 205 | #endif /* DEBUG */ 206 | 207 | #ifdef NJ_PROFILE 208 | #define counter_struct_begin() struct { 209 | #define counter_struct_end() } _stats; 210 | #define counter_define(x) int32_t x 211 | #define counter_value(x) _stats.x 212 | #define counter_set(x,v) (counter_value(x)=(v)) 213 | #define counter_adjust(x,i) (counter_value(x)+=(int32_t)(i)) 214 | #define counter_reset(x) counter_set(x,0) 215 | #define counter_increment(x) counter_adjust(x,1) 216 | #define counter_decrement(x) counter_adjust(x,-1) 217 | #define profile_only(x) x 218 | #else 219 | #define counter_struct_begin() 220 | #define counter_struct_end() 221 | #define counter_define(x) 222 | #define counter_value(x) 223 | #define counter_set(x,v) 224 | #define counter_adjust(x,i) 225 | #define counter_reset(x) 226 | #define counter_increment(x) 227 | #define counter_decrement(x) 228 | #define profile_only(x) 229 | #endif /* NJ_PROFILE */ 230 | 231 | #define isS8(i) ( int32_t(i) == int8_t(i) ) 232 | #define isU8(i) ( int32_t(i) == uint8_t(i) ) 233 | #define isS16(i) ( int32_t(i) == int16_t(i) ) 234 | #define isU16(i) ( int32_t(i) == uint16_t(i) ) 235 | #define isS24(i) ( ((int32_t(i)<<8)>>8) == (i) ) 236 | 237 | #define alignTo(x,s) ((((uintptr_t)(x)))&~(((uintptr_t)s)-1)) 238 | #define alignUp(x,s) ((((uintptr_t)(x))+(((uintptr_t)s)-1))&~(((uintptr_t)s)-1)) 239 | 240 | #define pageTop(x) ( alignTo(x,NJ_PAGE_SIZE) ) 241 | #define pageDataStart(x) ( alignTo(x,NJ_PAGE_SIZE) + sizeof(PageHeader) ) 242 | #define pageBottom(x) ( alignTo(x,NJ_PAGE_SIZE) + NJ_PAGE_SIZE - 1 ) 243 | #define samepage(x,y) ( pageTop(x) == pageTop(y) ) 244 | 245 | 246 | /* Debug printing stuff. All Nanojit debug printing should be routed 247 | through this function. Don't use ad-hoc calls to printf, 248 | fprintf(stderr, ...) etc. */ 249 | 250 | #if defined(NJ_VERBOSE) 251 | 252 | # if defined(__GNUC__) 253 | # define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y))) 254 | # else 255 | # define PRINTF_CHECK(x, y) 256 | # endif 257 | 258 | /* is in LIR.cpp */ 259 | void nj_dprintf( const char* format, ... ) PRINTF_CHECK(1,2); 260 | 261 | #endif /* NJ_VERBOSE */ 262 | 263 | 264 | 265 | #include "Native.h" 266 | #include "LIR.h" 267 | #include "RegAlloc.h" 268 | #include "Fragmento.h" 269 | #include "Assembler.h" 270 | #include "TraceTreeDrawer.h" 271 | 272 | #endif // FEATURE_NANOJIT 273 | #endif // __nanojit_h__ 274 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | cp $1/js/src/nanojit/Assembler.cpp . 2 | cp $1/js/src/nanojit/Assembler.h . 3 | cp $1/js/src/nanojit/Fragmento.cpp . 4 | cp $1/js/src/nanojit/Fragmento.h . 5 | cp $1/js/src/nanojit/LIR.cpp . 6 | cp $1/js/src/nanojit/LIR.h . 7 | cp $1/js/src/nanojit/Native.h . 8 | cp $1/js/src/nanojit/NativeARM.cpp . 9 | cp $1/js/src/nanojit/NativeARM.h . 10 | cp $1/js/src/nanojit/NativeSparc.cpp . 11 | cp $1/js/src/nanojit/NativeSparc.h . 12 | cp $1/js/src/nanojit/Nativei386.cpp . 13 | cp $1/js/src/nanojit/Nativei386.h . 14 | cp $1/js/src/nanojit/RegAlloc.cpp . 15 | cp $1/js/src/nanojit/RegAlloc.h . 16 | cp $1/js/src/nanojit/TraceTreeDrawer.cpp . 17 | cp $1/js/src/nanojit/TraceTreeDrawer.h . 18 | cp $1/js/src/nanojit/avmplus.cpp . 19 | cp $1/js/src/nanojit/avmplus.h . 20 | cp $1/js/src/nanojit/LIRopcode.tbl . 21 | #js-config.h 22 | #jsapi.h 23 | #jsautocfg.h 24 | #jsinttypes.h 25 | #jsotypes.h 26 | #jsstdint.h 27 | #jstypes.h 28 | #mozilla-config.h 29 | cp $1/js/src/nanojit/nanojit.h . 30 | --------------------------------------------------------------------------------