diff --git a/js/src/nanojit/Fragmento.cpp b/js/src/nanojit/Fragmento.cpp index bc9f06a12e0..47bd08ab92d 100644 --- a/js/src/nanojit/Fragmento.cpp +++ b/js/src/nanojit/Fragmento.cpp @@ -54,6 +54,22 @@ namespace nanojit return in; } +#ifdef _DEBUG + bool Fragmento::_firstFragmentoCreated = false; + + static void makeRuntimeStaticAssertions() + { + /* Opcodes must be strictly increasing without holes. */ + uint32_t count = 0; +#define OPDEF(op, number, operands) \ + NanoAssertMsg(LIR_##op == count++, "misnumbered opcode"); +#define OPDEF64(op, number, operands) OPDEF(op, number, operands) +#include "LIRopcode.tbl" +#undef OPDEF +#undef OPDEF64 + } +#endif + /** * This is the main control center for creating and managing fragments. */ @@ -62,6 +78,14 @@ namespace nanojit _max_pages(1 << (calcSaneCacheSize(cacheSizeLog2) - NJ_LOG2_PAGE_SIZE)), _pagesGrowth(1) { +#ifdef _DEBUG + if (!_firstFragmentoCreated) + { + makeRuntimeStaticAssertions(); + _firstFragmentoCreated = true; + } +#endif + #ifdef MEMORY_INFO _allocList.set_meminfo_name("Fragmento._allocList"); #endif diff --git a/js/src/nanojit/Fragmento.h b/js/src/nanojit/Fragmento.h index 8157b25765b..7cdaacf3f26 100644 --- a/js/src/nanojit/Fragmento.h +++ b/js/src/nanojit/Fragmento.h @@ -159,6 +159,10 @@ namespace nanojit const uint32_t _max_pages; uint32_t _pagesGrowth; + + #ifdef _DEBUG + static bool _firstFragmentoCreated; + #endif }; enum TraceKind { diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index 7d33c4541c3..c535436bb92 100755 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -50,43 +50,28 @@ namespace nanojit #ifdef FEATURE_NANOJIT const uint8_t operandCount[] = { - /* 0 */ /*trace*/0, /*nearskip*/0, /*skip*/0, /*neartramp*/0, /*tramp*/0, 2, 2, 2, 2, /*addp*/2, - /* 10 */ /*param*/0, 2, 2, /*alloc*/0, 2, /*ret*/1, /*live*/1, /*calli*/0, /*call*/0, /*loop*/0, - /* 20 */ /*x*/0, 0, 1, 1, /*label*/0, 2, 2, 2, 2, 2, - /* 30 */ 2, 2, /*short*/0, /*int*/0, 2, 2, /*neg*/1, 2, 2, 2, -#if defined NANOJIT_64BIT - /* 40 */ /*callh*/0, 2, 2, 2, /*not*/1, 2, 2, 2, /*xt*/1, /*xf*/1, -#else - /* 40 */ /*callh*/1, 2, 2, 2, /*not*/1, 2, 2, 2, /*xt*/1, /*xf*/1, -#endif - /* 50 */ /*qlo*/1, /*qhi*/1, 2, /*ov*/1, /*cs*/1, 2, 2, 2, 2, 2, - /* 60 */ 2, 2, 2, 2, 2, /*file*/1, /*line*/1, 2, 2, 2, - /* 70 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, /*fret*/1, - /* 80 */ 2, /*fcalli*/0, /*fcall*/0, 2, 2, 2, 2, 2, 2, 2, - /* 90 */ 2, 2, 2, 2, 2, 2, 2, /*quad*/0, 2, 2, - /* 100 */ /*fneg*/1, 2, 2, 2, 2, 2, /*i2f*/1, /*u2f*/1, 2, 2, - /* 110 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - /* 120 */ 2, 2, 2, 2, 2, 2, 2, 2, +#define OPDEF(op, number, operands) \ + operands, +#define OPDEF64(op, number, operands) \ + operands, +#include "LIRopcode.tbl" +#undef OPDEF +#undef OPDEF64 + 0 }; // LIR verbose specific #ifdef NJ_VERBOSE const char* lirNames[] = { - /* 0-9 */ "start","nearskip","skip","neartramp","tramp","5","6","7","8","addp", - /* 10-19 */ "param","st","ld","alloc","sti","ret","live","calli","call","loop", - /* 20-29 */ "x","j","jt","jf","label","ldcs","feq","flt","fgt","fle", - /* 30-39 */ "fge","cmov","short","int","ldc","","neg","add","sub","mul", - /* 40-49 */ "callh","and","or","xor","not","lsh","rsh","ush","xt","xf", - /* 50-59 */ "qlo","qhi","ldcb","ov","cs","eq","lt","gt","le","ge", - /* 60-63 */ "ult","ugt","ule","uge", - /* 64-69 */ "LIR64","file","line","67","68","69", - /* 70-79 */ "70","71","72","73","74","stq","ldq","77","stqi","fret", - /* 80-89 */ "80","fcalli","fcall","83","84","85","86","87","88","89", - /* 90-99 */ "90","91","92","93","94","95","96","quad","ldqc","99", - /* 100-109 */ "fneg","fadd","fsub","fmul","fdiv","qjoin","i2f","u2f","qior","qilsh", - /* 110-119 */ "110","111","112","113","114","115","116","117","118","119", - /* 120-127 */ "120","121","122","123","124","125","126","127" +#define OPDEF(op, number, operands) \ + #op, +#define OPDEF64(op, number, operands) \ + #op, +#include "LIRopcode.tbl" +#undef OPDEF +#undef OPDEF64 + NULL }; #endif /* NANOJIT_VEBROSE */ diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index 43a69004a30..a13061f6a6d 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -60,124 +60,14 @@ namespace nanojit // flags; upper bits reserved LIR64 = 0x40, // result is double or quad - // special operations (must be 0..N) - LIR_start = 0, - LIR_nearskip = 1, // must be LIR_skip-1 and lsb=1 - LIR_skip = 2, - LIR_neartramp = 3, // must be LIR_tramp-1 and lsb=1 - LIR_tramp = 4, - - // non-pure operations - LIR_addp = 9, - LIR_param = 10, - LIR_st = 11, // 32-bit store - LIR_ld = 12, // 32-bit load - LIR_alloc = 13, // alloca some stack space - LIR_sti = 14, - LIR_ret = 15, - LIR_live = 16, // extend live range of reference - LIR_calli = 17, // indirect call - LIR_call = 18, // subroutine call returning a 32-bit value - - // guards - LIR_loop = 19, // loop fragment - LIR_x = 20, // exit always - - // branches - LIR_j = 21, // jump always - LIR_jt = 22, // jump true - LIR_jf = 23, // jump false - LIR_label = 24, // a jump target - LIR_ji = 25, // jump indirect - // operators - - LIR_ldcs = 25, // non-volatile 16-bit load - - // LIR_feq though LIR_fge must only be used on float arguments. They - // return integers. - LIR_feq = 26, // floating-point equality [2 float inputs] - LIR_flt = 27, // floating-point less than: arg1 < arg2 - LIR_fgt = 28, // floating-point greater than: arg1 > arg2 - LIR_fle = 29, // arg1 <= arg2, both floating-point - LIR_fge = 30, // arg1 >= arg2, both floating-point - - LIR_cmov = 31, // conditional move (op1=cond, op2=cond(iftrue,iffalse)) - LIR_short = 32, // constant 16-bit integer - LIR_int = 33, // constant 32-bit integer - LIR_ldc = 34, // non-volatile load - LIR_2 = 35, // wraps a pair of refs - - // LIR_neg through LIR_ush are all integer operations - LIR_neg = 36, // numeric negation [ 1 integer input / integer output ] - LIR_add = 37, // integer addition [ 2 operand integer intputs / integer output ] - LIR_sub = 38, // integer subtraction - LIR_mul = 39, // integer multiplication - LIR_callh = 40, - LIR_and = 41, - LIR_or = 42, - LIR_xor = 43, - LIR_not = 44, - LIR_lsh = 45, - LIR_rsh = 46, // >> - LIR_ush = 47, // >>> - - // conditional guards, op^1 to complement. Only things that are - // isCond() can be passed to these. - LIR_xt = 48, // exit if true 0x30 0011 0000 - LIR_xf = 49, // exit if false 0x31 0011 0001 - - // qlo and qhi take a single quad argument and return its low and high - // 32 bits respectively as 32-bit integers. - LIR_qlo = 50, - LIR_qhi = 51, - - LIR_ldcb = 52, // non-volatile 8-bit load - - LIR_ov = 53, - LIR_cs = 54, - LIR_eq = 55, // integer equality - // integer (all sizes) relational operators. op^1 to swap left/right, - // op^3 to complement. - LIR_lt = 56, // 0x38 0011 1000 - LIR_gt = 57, // 0x39 0011 1001 - LIR_le = 58, // 0x3A 0011 1010 - LIR_ge = 59, // 0x3B 0011 1011 - // and the unsigned integer versions - LIR_ult = 60, // 0x3C 0011 1100 - LIR_ugt = 61, // 0x3D 0011 1101 - LIR_ule = 62, // 0x3E 0011 1110 - LIR_uge = 63, // 0x3F 0011 1111 - - // non-64bit ops, but we're out of code space below 64 - LIR_file = 1 | LIR64, - LIR_line = 2 | LIR64, - - /** - * 64bit operations - */ - LIR_stq = LIR_st | LIR64, // quad store - LIR_stqi = LIR_sti | LIR64, - LIR_fret = LIR_ret | LIR64, - LIR_quad = LIR_int | LIR64, // quad constant value - LIR_ldq = LIR_ld | LIR64, // quad load - LIR_ldqc = LIR_ldc | LIR64, - LIR_qiand = 24 | LIR64, - LIR_qiadd = 25 | LIR64, - LIR_qilsh = LIR_lsh | LIR64, - - LIR_fcall = LIR_call | LIR64, // subroutine call returning quad - LIR_fcalli = LIR_calli | LIR64, - LIR_fneg = LIR_neg | LIR64, // floating-point numeric negation - LIR_fadd = LIR_add | LIR64, // floating-point addition - LIR_fsub = LIR_sub | LIR64, // floating-point subtraction - LIR_fmul = LIR_mul | LIR64, // floating-point multiplication - LIR_fdiv = 40 | LIR64, // floating-point division - LIR_qcmov = LIR_cmov | LIR64, - - LIR_qjoin = 41 | LIR64, - LIR_i2f = 42 | LIR64, // convert an integer to a float - LIR_u2f = 43 | LIR64, // convert an unsigned integer to a float - LIR_qior = 44 | LIR64 +#define OPDEF(op, number, args) \ + LIR_##op = (number), +#define OPDEF64(op, number, args) \ + LIR_##op = ((number) | LIR64), +#include "LIRopcode.tbl" + LIR_sentinel +#undef OPDEF +#undef OPDEF64 }; #if defined NANOJIT_64BIT diff --git a/js/src/nanojit/LIRopcode.tbl b/js/src/nanojit/LIRopcode.tbl new file mode 100644 index 00000000000..5d7383c8dcd --- /dev/null +++ b/js/src/nanojit/LIRopcode.tbl @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=0 ft=C: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is SpiderMonkey nanojit. + * + * The Initial Developer of the Original Code is + * the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jeff Walden + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Definitions of LIR opcodes. If you need to allocate an opcode, look + * for a name of the form unused* and claim it. + * + * Includers must define OPDEF and OPDEF64 macros of the following forms: + * + * #define OPDEF(op,val,operands) ... + * #define OPDEF64(op,val,operands) ... + * + * Selected arguments can then be used within the macro expansions. + * + * Field Description + * op Bytecode name, token-pasted after "LIR_" to form an LOpcode + * val Bytecode value, which is the LOpcode enumerator value + * operands Number of operands for this instruction + * + * This file is best viewed with 128 columns: +12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 + */ + +/* op val name operands */ + +/* special operations (must be 0..N) */ +OPDEF(start, 0, 0) +OPDEF(nearskip, 1, 0) // must be skip-1 and lsb=1 +OPDEF(skip, 2, 0) +OPDEF(neartramp, 3, 0) // must be tramp-1 and lsb=1 +OPDEF(tramp, 4, 0) + +OPDEF(unused1, 5, 2) +OPDEF(unused2, 6, 2) +OPDEF(unused3, 7, 2) +OPDEF(unused4, 8, 2) + +/* non-pure operations */ +OPDEF(addp, 9, 2) +OPDEF(param, 10, 0) +OPDEF(st, 11, 2) // 32-bit store +OPDEF(ld, 12, 2) // 32-bit load +OPDEF(alloc, 13, 0) // alloca some stack space +OPDEF(sti, 14, 2) +OPDEF(ret, 15, 1) +OPDEF(live, 16, 1) // extend live range of reference +OPDEF(calli, 17, 0) // indirect call +OPDEF(call, 18, 0) // subroutine call returning a 32-bit value + +/* guards */ +OPDEF(loop, 19, 0) // loop fragment +OPDEF(x, 20, 0) // exit always + +/* branches */ +OPDEF(j, 21, 0) // jump always +OPDEF(jt, 22, 1) // jump true +OPDEF(jf, 23, 1) // jump false +OPDEF(label, 24, 0) // a jump target +OPDEF(ji, 25, 2) // jump indirect +/* operators */ + +OPDEF(ldcs, 26, 2) // non-volatile 16-bit load + +/* + * feq though fge must only be used on float arguments. They + * return integers. + */ +OPDEF(feq, 27, 2) // floating-point equality [2 float inputs] +OPDEF(flt, 28, 2) // floating-point less than: arg1 < arg2 +OPDEF(fgt, 29, 2) // floating-point greater than: arg1 > arg2 +OPDEF(fle, 30, 2) // arg1 <= arg2, both floating-point +OPDEF(fge, 31, 2) // arg1 >= arg2, both floating-point + +OPDEF(cmov, 32, 2) // conditional move (op1=cond, op2=cond(iftrue,iffalse)) +OPDEF(short, 33, 0) // constant 16-bit integer +OPDEF(int, 34, 0) // constant 32-bit integer +OPDEF(ldc, 35, 2) // non-volatile load +OPDEF(2, 36, 2) // wraps a pair of refs + +// neg through ush are all integer operations +OPDEF(neg, 37, 1) // numeric negation [ 1 integer input / integer output ] +OPDEF(add, 38, 2) // integer addition [ 2 operand integer intputs / integer output ] +OPDEF(sub, 39, 2) // integer subtraction +OPDEF(mul, 40, 2) // integer multiplication +#if defined(NANOJIT_64BIT) +OPDEF(callh, 41, 0) +#else +OPDEF(callh, 41, 1) +#endif +OPDEF(and, 42, 2) +OPDEF(or, 43, 2) +OPDEF(xor, 44, 2) +OPDEF(not, 45, 1) +OPDEF(lsh, 46, 2) +OPDEF(rsh, 47, 2) // >> +OPDEF(ush, 48, 2) // >>> + +// conditional guards, op^1 to complement. Only things that are +// isCond() can be passed to these. +OPDEF(xt, 49, 1) // exit if true 0x30 0011 0000 +OPDEF(xf, 50, 1) // exit if false 0x31 0011 0001 + +// qlo and qhi take a single quad argument and return its low and high +// 32 bits respectively as 32-bit integers. +OPDEF(qlo, 51, 1) +OPDEF(qhi, 52, 1) + +OPDEF(ldcb, 53, 2) // non-volatile 8-bit load + +OPDEF(ov, 54, 1) +OPDEF(cs, 55, 1) + +// integer (all sizes) relational operators. op^1 to swap left/right, +// op^3 to complement. +OPDEF(eq, 56, 2) // integer equality +OPDEF(lt, 57, 2) // 0x38 0011 1000 +OPDEF(gt, 58, 2) // 0x39 0011 1001 +OPDEF(le, 59, 2) // 0x3A 0011 1010 +OPDEF(ge, 60, 2) // 0x3B 0011 1011 + +// and the unsigned integer versions +OPDEF(ult, 61, 2) // 0x3C 0011 1100 +OPDEF(ugt, 62, 2) // 0x3D 0011 1101 +OPDEF(ule, 63, 2) // 0x3E 0011 1110 + +/** + * 64bit operations + */ + +/* non-64bit ops, but we're out of code space below 64 */ +OPDEF64(unused0_64, 0, 2) +OPDEF64(uge, 1, 2) // 0x3F 0011 1111 +OPDEF64(file, 2, 2) +OPDEF64(line, 3, 2) + +OPDEF64(unused4_64, 4, 2) +OPDEF64(unused5_64, 5, 2) +OPDEF64(unused6_64, 6, 2) +OPDEF64(unused7_64, 7, 2) +OPDEF64(unused8_64, 8, 2) +OPDEF64(unused9_64, 9, 2) +OPDEF64(unused10_64, 10, 2) + +OPDEF64(stq, LIR_st, 2) // quad store +OPDEF64(ldq, LIR_ld, 2) // quad load + +OPDEF64(unused13_64, 13, 2) + +OPDEF64(stqi, LIR_sti, 2) +OPDEF64(fret, LIR_ret, 1) + +OPDEF64(unused16_64, 16, 2) + +OPDEF64(fcalli, LIR_calli, 0) +OPDEF64(fcall, LIR_call, 0) // subroutine call returning quad + +OPDEF64(unused19_64, 19, 2) +OPDEF64(unused20_64, 20, 2) +OPDEF64(unused21_64, 21, 2) +OPDEF64(unused22_64, 22, 2) +OPDEF64(unused23_64, 23, 2) +OPDEF64(qiand, 24, 2) +OPDEF64(qiadd, 25, 2) +OPDEF64(unused26_64, 26, 2) +OPDEF64(unused27_64, 27, 2) +OPDEF64(unused28_64, 28, 2) +OPDEF64(unused29_64, 29, 2) +OPDEF64(unused30_64, 30, 2) +OPDEF64(unused31_64, 31, 2) + +OPDEF64(qcmov, LIR_cmov, 2) + +OPDEF64(unused33_64, 33, 2) + +OPDEF64(quad, LIR_int, 0) // quad constant value +OPDEF64(ldqc, LIR_ldc, 2) + +OPDEF64(unused36_64, 36, 2) + +/* floating-point arithmetic operations */ +OPDEF64(fneg, LIR_neg, 1) +OPDEF64(fadd, LIR_add, 2) +OPDEF64(fsub, LIR_sub, 2) +OPDEF64(fmul, LIR_mul, 2) +OPDEF64(fdiv, 41, 2) + +OPDEF64(qjoin, 42, 2) +OPDEF64(i2f, 43, 1) // convert an integer to a float +OPDEF64(u2f, 44, 1) // convert an unsigned integer to a float +OPDEF64(qior, 45, 2) +OPDEF64(qilsh, LIR_lsh, 2) + +OPDEF64(unused47_64, 47, 2) +OPDEF64(unused48_64, 48, 2) +OPDEF64(unused49_64, 49, 2) +OPDEF64(unused50_64, 50, 2) +OPDEF64(unused51_64, 51, 2) +OPDEF64(unused52_64, 52, 2) +OPDEF64(unused53_64, 53, 2) +OPDEF64(unused54_64, 54, 2) +OPDEF64(unused55_64, 55, 2) +OPDEF64(unused56_64, 56, 2) +OPDEF64(unused57_64, 57, 2) +OPDEF64(unused58_64, 58, 2) +OPDEF64(unused59_64, 59, 2) +OPDEF64(unused60_64, 60, 2) +OPDEF64(unused61_64, 61, 2) +OPDEF64(unused62_64, 62, 2) +OPDEF64(unused63_64, 63, 2)