From be9801c9c5b9eacbab6e08a3041979f0e4251b50 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 4 Jul 2010 19:39:09 -0700 Subject: [PATCH] Bug 553962 - nanojit: finish adding get/set methods for CallInfo::_typesig. r=edwsmith. --HG-- extra : convert_revision : cfbed237877f0939423d9c1ac591c0a7edb5b0c0 --- js/src/lirasm/lirasm.cpp | 101 ++++++++++----------------------------- js/src/nanojit/LIR.cpp | 26 +++++----- js/src/nanojit/LIR.h | 54 ++++++++++++++++++--- 3 files changed, 86 insertions(+), 95 deletions(-) diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index cd405b18fad9..dd2663a31d70 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -337,24 +337,6 @@ private: void endFragment(); }; -// Meaning: arg 'm' of 'n' has type 'ty'. -static int argMask(int ty, int m, int n) -{ - // Order examples, from MSB to LSB: - // - 3 args: 000 | 000 | 000 | 000 | 000 | arg1| arg2| arg3| ret - // - 8 args: arg1| arg2| arg3| arg4| arg5| arg6| arg7| arg8| ret - // If the mask encoding reversed the arg order the 'n' parameter wouldn't - // be necessary, as argN would always be in the same place in the - // bitfield. - return ty << ((1 + n - m) * ARGTYPE_SHIFT); -} - -// Return value has type 'ty'. -static int retMask(int ty) -{ - return ty; -} - // 'sin' is overloaded on some platforms, so taking its address // doesn't quite work. Provide a do-nothing function here // that's not overloaded. @@ -364,10 +346,10 @@ double sinFn(double d) { #define sin sinFn Function functions[] = { - FN(puts, argMask(ARGTYPE_P, 1, 1) | retMask(ARGTYPE_I)), - FN(sin, argMask(ARGTYPE_D, 1, 1) | retMask(ARGTYPE_D)), - FN(malloc, argMask(ARGTYPE_P, 1, 1) | retMask(ARGTYPE_P)), - FN(free, argMask(ARGTYPE_P, 1, 1) | retMask(ARGTYPE_V)) + FN(puts, CallInfo::typeSig1(ARGTYPE_I, ARGTYPE_P)), + FN(sin, CallInfo::typeSig1(ARGTYPE_D, ARGTYPE_D)), + FN(malloc, CallInfo::typeSig1(ARGTYPE_P, ARGTYPE_P)), + FN(free, CallInfo::typeSig1(ARGTYPE_V, ARGTYPE_P)), }; template out @@ -687,32 +669,28 @@ FragmentAssembler::assemble_call(const string &op) } else { // User-defined function: infer CallInfo details (ABI, arg types, ret // type) from the call site. - int ty; - ci->_abi = _abi; - - ci->_typesig = 0; size_t argc = mTokens.size(); + ArgType argTypes[MAXARGS]; for (size_t i = 0; i < argc; ++i) { + NanoAssert(i < MAXARGS); // should give a useful error msg if this fails args[i] = ref(mTokens[mTokens.size() - (i+1)]); - if (args[i]->isD()) ty = ARGTYPE_D; + if (args[i]->isD()) argTypes[i] = ARGTYPE_D; #ifdef NANOJIT_64BIT - else if (args[i]->isQ()) ty = ARGTYPE_Q; + else if (args[i]->isQ()) argTypes[i] = ARGTYPE_Q; #endif - else ty = ARGTYPE_I; - // Nb: i+1 because argMask() uses 1-based arg counting. - ci->_typesig |= argMask(ty, i+1, argc); + else argTypes[i] = ARGTYPE_I; } // Select return type from opcode. - ty = 0; - if (mOpcode == LIR_calli) ty = ARGTYPE_I; - else if (mOpcode == LIR_calld) ty = ARGTYPE_D; + ArgType retType = ARGTYPE_V; + if (mOpcode == LIR_calli) retType = ARGTYPE_I; + else if (mOpcode == LIR_calld) retType = ARGTYPE_D; #ifdef NANOJIT_64BIT - else if (mOpcode == LIR_callq) ty = ARGTYPE_Q; + else if (mOpcode == LIR_callq) retType = ARGTYPE_Q; #endif else nyi("callh"); - ci->_typesig |= retMask(ty); + ci->_typesig = CallInfo::typeSigN(retType, argc, argTypes); } return mLir->insCall(ci, args); @@ -1283,52 +1261,23 @@ static void f_V_IQF(int32_t, uint64_t, double) } #endif -const CallInfo ci_I_I1 = CI(f_I_I1, argMask(ARGTYPE_I, 1, 1) | - retMask(ARGTYPE_I)); - -const CallInfo ci_I_I6 = CI(f_I_I6, argMask(ARGTYPE_I, 1, 6) | - argMask(ARGTYPE_I, 2, 6) | - argMask(ARGTYPE_I, 3, 6) | - argMask(ARGTYPE_I, 4, 6) | - argMask(ARGTYPE_I, 5, 6) | - argMask(ARGTYPE_I, 6, 6) | - retMask(ARGTYPE_I)); +const CallInfo ci_I_I1 = CI(f_I_I1, CallInfo::typeSig1(ARGTYPE_I, ARGTYPE_I)); +const CallInfo ci_I_I6 = CI(f_I_I6, CallInfo::typeSig6(ARGTYPE_I, ARGTYPE_I, ARGTYPE_I, ARGTYPE_I, + ARGTYPE_I, ARGTYPE_I, ARGTYPE_I)); #ifdef NANOJIT_64BIT -const CallInfo ci_Q_Q2 = CI(f_Q_Q2, argMask(ARGTYPE_Q, 1, 2) | - argMask(ARGTYPE_Q, 2, 2) | - retMask(ARGTYPE_Q)); - -const CallInfo ci_Q_Q7 = CI(f_Q_Q7, argMask(ARGTYPE_Q, 1, 7) | - argMask(ARGTYPE_Q, 2, 7) | - argMask(ARGTYPE_Q, 3, 7) | - argMask(ARGTYPE_Q, 4, 7) | - argMask(ARGTYPE_Q, 5, 7) | - argMask(ARGTYPE_Q, 6, 7) | - argMask(ARGTYPE_Q, 7, 7) | - retMask(ARGTYPE_Q)); +const CallInfo ci_Q_Q2 = CI(f_Q_Q2, CallInfo::typeSig2(ARGTYPE_Q, ARGTYPE_Q, ARGTYPE_Q)); +const CallInfo ci_Q_Q7 = CI(f_Q_Q7, CallInfo::typeSig7(ARGTYPE_Q, ARGTYPE_Q, ARGTYPE_Q, ARGTYPE_Q, + ARGTYPE_Q, ARGTYPE_Q, ARGTYPE_Q, ARGTYPE_Q)); #endif -const CallInfo ci_F_F3 = CI(f_F_F3, argMask(ARGTYPE_D, 1, 3) | - argMask(ARGTYPE_D, 2, 3) | - argMask(ARGTYPE_D, 3, 3) | - retMask(ARGTYPE_D)); - -const CallInfo ci_F_F8 = CI(f_F_F8, argMask(ARGTYPE_D, 1, 8) | - argMask(ARGTYPE_D, 2, 8) | - argMask(ARGTYPE_D, 3, 8) | - argMask(ARGTYPE_D, 4, 8) | - argMask(ARGTYPE_D, 5, 8) | - argMask(ARGTYPE_D, 6, 8) | - argMask(ARGTYPE_D, 7, 8) | - argMask(ARGTYPE_D, 8, 8) | - retMask(ARGTYPE_D)); +const CallInfo ci_F_F3 = CI(f_F_F3, CallInfo::typeSig3(ARGTYPE_D, ARGTYPE_D, ARGTYPE_D, ARGTYPE_D)); +const CallInfo ci_F_F8 = CI(f_F_F8, CallInfo::typeSig8(ARGTYPE_D, ARGTYPE_D, ARGTYPE_D, ARGTYPE_D, + ARGTYPE_D, ARGTYPE_D, ARGTYPE_D, ARGTYPE_D, + ARGTYPE_D)); #ifdef NANOJIT_64BIT -const CallInfo ci_V_IQF = CI(f_V_IQF, argMask(ARGTYPE_I, 1, 3) | - argMask(ARGTYPE_Q, 2, 3) | - argMask(ARGTYPE_D, 3, 3) | - retMask(ARGTYPE_V)); +const CallInfo ci_V_IQF = CI(f_V_IQF, CallInfo::typeSig3(ARGTYPE_V, ARGTYPE_I, ARGTYPE_Q, ARGTYPE_D)); #endif // Generate a random block containing nIns instructions, plus a few more diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index 9505fc3bca6e..da94fb87156c 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -85,10 +85,10 @@ namespace nanojit { uint32_t argc = 0; uint32_t argt = _typesig; - argt >>= ARGTYPE_SHIFT; // remove retType + argt >>= TYPESIG_FIELDSZB; // remove retType while (argt) { argc++; - argt >>= ARGTYPE_SHIFT; + argt >>= TYPESIG_FIELDSZB; } return argc; } @@ -97,12 +97,12 @@ namespace nanojit { uint32_t argc = 0; uint32_t argt = _typesig; - argt >>= ARGTYPE_SHIFT; // remove retType + argt >>= TYPESIG_FIELDSZB; // remove retType while (argt) { - ArgType a = ArgType(argt & ARGTYPE_MASK); + ArgType a = ArgType(argt & TYPESIG_FIELDMASK); if (a == ARGTYPE_I || a == ARGTYPE_UI) argc++; - argt >>= ARGTYPE_SHIFT; + argt >>= TYPESIG_FIELDSZB; } return argc; } @@ -111,12 +111,12 @@ namespace nanojit { uint32_t argc = 0; uint32_t argt = _typesig; - argt >>= ARGTYPE_SHIFT; // remove retType + argt >>= TYPESIG_FIELDSZB; // remove retType while (argt) { - ArgType a = ArgType(argt & ARGTYPE_MASK); + ArgType a = ArgType(argt & TYPESIG_FIELDMASK); argTypes[argc] = a; argc++; - argt >>= ARGTYPE_SHIFT; + argt >>= TYPESIG_FIELDSZB; } return argc; } @@ -2512,11 +2512,11 @@ namespace nanojit static int32_t FASTCALL led(double a, double b) { return a <= b; } static int32_t FASTCALL ged(double a, double b) { return a >= b; } - #define SIG_D_I (ARGTYPE_D | ARGTYPE_I << ARGTYPE_SHIFT*1) - #define SIG_D_UI (ARGTYPE_D | ARGTYPE_UI << ARGTYPE_SHIFT*1) - #define SIG_D_D (ARGTYPE_D | ARGTYPE_D << ARGTYPE_SHIFT*1) - #define SIG_D_DD (ARGTYPE_D | ARGTYPE_D << ARGTYPE_SHIFT*1 | ARGTYPE_D << ARGTYPE_SHIFT*2) - #define SIG_B_DD (ARGTYPE_B | ARGTYPE_D << ARGTYPE_SHIFT*1 | ARGTYPE_D << ARGTYPE_SHIFT*2) + #define SIG_D_I typeSig1(ARGTYPE_D, ARGTYPE_I) + #define SIG_D_UI typeSig1(ARGTYPE_D, ARGTYPE_UI) + #define SIG_D_D typeSig1(ARGTYPE_D, ARGTYPE_D) + #define SIG_D_DD typeSig2(ARGTYPE_D, ARGTYPE_D, ARGTYPE_D) + #define SIG_B_DD typeSig2(ARGTYPE_B, ARGTYPE_D, ARGTYPE_D) #define SF_CALLINFO(name, typesig) \ static const CallInfo name##_ci = \ diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index 30a0c900c21c..cc6ff89dbf21 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -173,13 +173,9 @@ namespace nanojit // aliases ARGTYPE_P = PTR_SIZE(ARGTYPE_I, ARGTYPE_Q), // pointer - ARGTYPE_B = ARGTYPE_I // bool + ARGTYPE_B = ARGTYPE_I // bool }; - // In _typesig, each entry is three bits. - static const int ARGTYPE_SHIFT = 3; - static const int ARGTYPE_MASK = 0x7; - enum IndirectCall { CALL_INDIRECT = 0 }; @@ -315,9 +311,13 @@ namespace nanojit static const AccSet ACC_LOAD_ANY = ACC_ALL; // synonym static const AccSet ACC_STORE_ANY = ACC_ALL_STORABLE; // synonym + struct CallInfo { private: + // In CallInfo::_typesig, each entry is three bits. + static const int TYPESIG_FIELDSZB = 3; + static const int TYPESIG_FIELDMASK = 7; public: uintptr_t _address; @@ -327,13 +327,55 @@ namespace nanojit AccSet _storeAccSet; // access regions stored by the function verbose_only ( const char* _name; ) + // The following encode 'r func()' through to 'r func(a1, a2, a3, a4, a5, a6, a7, a8)'. + static inline uint32_t typeSig0(ArgType r) { + return r; + } + static inline uint32_t typeSig1(ArgType r, ArgType a1) { + return a1 << TYPESIG_FIELDSZB*1 | typeSig0(r); + } + static inline uint32_t typeSig2(ArgType r, ArgType a1, ArgType a2) { + return a1 << TYPESIG_FIELDSZB*2 | typeSig1(r, a2); + } + static inline uint32_t typeSig3(ArgType r, ArgType a1, ArgType a2, ArgType a3) { + return a1 << TYPESIG_FIELDSZB*3 | typeSig2(r, a2, a3); + } + static inline uint32_t typeSig4(ArgType r, ArgType a1, ArgType a2, ArgType a3, ArgType a4) { + return a1 << TYPESIG_FIELDSZB*4 | typeSig3(r, a2, a3, a4); + } + static inline uint32_t typeSig5(ArgType r, ArgType a1, ArgType a2, ArgType a3, + ArgType a4, ArgType a5) { + return a1 << TYPESIG_FIELDSZB*5 | typeSig4(r, a2, a3, a4, a5); + } + static inline uint32_t typeSig6(ArgType r, ArgType a1, ArgType a2, ArgType a3, + ArgType a4, ArgType a5, ArgType a6) { + return a1 << TYPESIG_FIELDSZB*6 | typeSig5(r, a2, a3, a4, a5, a6); + } + static inline uint32_t typeSig7(ArgType r, ArgType a1, ArgType a2, ArgType a3, + ArgType a4, ArgType a5, ArgType a6, ArgType a7) { + return a1 << TYPESIG_FIELDSZB*7 | typeSig6(r, a2, a3, a4, a5, a6, a7); + } + static inline uint32_t typeSig8(ArgType r, ArgType a1, ArgType a2, ArgType a3, ArgType a4, + ArgType a5, ArgType a6, ArgType a7, ArgType a8) { + return a1 << TYPESIG_FIELDSZB*8 | typeSig7(r, a2, a3, a4, a5, a6, a7, a8); + } + // Encode 'r func(a1, ..., aN))' + static inline uint32_t typeSigN(ArgType r, int N, ArgType a[]) { + uint32_t typesig = r; + for (int i = 0; i < N; i++) { + typesig |= a[i] << TYPESIG_FIELDSZB*(N-i); + } + return typesig; + } + uint32_t count_args() const; uint32_t count_int32_args() const; // Nb: uses right-to-left order, eg. sizes[0] is the size of the right-most arg. + // XXX: See bug 525815 for fixing this. uint32_t getArgTypes(ArgType* types) const; inline ArgType returnType() const { - return ArgType(_typesig & ARGTYPE_MASK); + return ArgType(_typesig & TYPESIG_FIELDMASK); } inline bool isIndirect() const {