src/Utility.h
author David Anderson <danderson@mozilla.com>
Wed Jul 25 00:48:08 2012 -0700 (2012-07-25)
changeset 91 5f4402180204
parent 86 32ad0523b309
child 92 e3974e7360e9
permissions -rw-r--r--
Added clang support. A lot of the motion here is introducing a new offsetof because clang's seems broken?
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jitcraft_utility_h_
    20 #define _include_jitcraft_utility_h_
    21 
    22 #include <assert.h>
    23 #include <stdint.h>
    24 #ifdef _MSC_VER
    25 # include <intrin.h>
    26 #endif
    27 
    28 #ifdef _MSC_VER
    29 # pragma warning(disable:4355)
    30 #endif
    31 
    32 namespace ke {
    33 
    34 static const size_t kMallocAlignment = sizeof(void *) * 2;
    35 
    36 typedef uint8_t uint8;
    37 typedef int32_t int32;
    38 typedef uint32_t uint32;
    39 
    40 typedef uint8 * Address;
    41 
    42 static const size_t kKB = 1024;
    43 static const size_t kMB = 1024 * kKB;
    44 static const size_t kGB = 1024 * kMB;
    45 
    46 template <typename T>
    47 class AutoVec
    48 {
    49     T *t_;
    50 
    51   public:
    52     AutoVec()
    53       : t_(NULL)
    54     {
    55     }
    56     AutoVec(T *t)
    57       : t_(t)
    58     {
    59     }
    60     ~AutoVec() {
    61         delete [] t_;
    62     }
    63     operator T *() {
    64         return t_;
    65     }
    66     void operator =(T *t) {
    67         if (t_)
    68             delete [] t_;
    69         t_ = t;
    70     }
    71 };
    72 
    73 // Bob Jenkin's one-at-a-time hash function[1].
    74 //
    75 // [1] http://burtleburtle.net/bob/hash/doobs.html
    76 class CharacterStreamHasher
    77 {
    78     uint32 hash;
    79 
    80   public:
    81     CharacterStreamHasher()
    82       : hash(0)
    83     { }
    84 
    85     void add(char c) {
    86         hash += c;
    87         hash += (hash << 10);
    88         hash ^= (hash >> 6);
    89     }
    90 
    91     void add(const char *s, size_t length) {
    92         for (size_t i = 0; i < length; i++)
    93             add(s[i]);
    94     }
    95 
    96     uint32 result() {
    97         hash += (hash << 3);
    98         hash ^= (hash >> 11);
    99         hash += (hash << 15);
   100         return hash;
   101     }
   102 };
   103 
   104 static inline uint32
   105 HashCharSequence(const char *s, size_t length)
   106 {
   107     CharacterStreamHasher hasher;
   108     hasher.add(s, length);
   109     return hasher.result();
   110 }
   111 
   112 static inline size_t
   113 Log2(size_t number)
   114 {
   115     assert(number != 0);
   116 
   117 #ifdef _MSC_VER
   118     unsigned long rval;
   119 # ifdef _M_IX86
   120     _BitScanReverse(&rval, number);
   121 # elif _M_X64
   122     _BitScanReverse64(&rval, number);
   123 # endif
   124     return rval;
   125 #else
   126 	size_t bit;
   127 	asm("bsr %1, %0\n"
   128 		: "=r" (bit)
   129 		: "rm" (number));
   130 	return bit;
   131 #endif
   132 }
   133 
   134 static inline size_t
   135 FindRightmostBit(size_t number)
   136 {
   137     assert(number != 0);
   138 
   139 #ifdef _MSC_VER
   140     unsigned long rval;
   141 # ifdef _M_IX86
   142     _BitScanForward(&rval, number);
   143 # elif _M_X64
   144     _BitScanForward64(&rval, number);
   145 # endif
   146     return rval;
   147 #else
   148 	size_t bit;
   149 	asm("bsf %1, %0\n"
   150 		: "=r" (bit)
   151 		: "rm" (number));
   152 	return bit;
   153 #endif
   154 }
   155 
   156 static inline bool
   157 IsPowerOfTwo(size_t value)
   158 {
   159     if (value == 0)
   160         return false;
   161     return !(value & (value - 1));
   162 }
   163 
   164 static inline size_t
   165 Align(size_t count, size_t alignment)
   166 {
   167     assert(IsPowerOfTwo(alignment));
   168     return count + (alignment - (count % alignment)) % alignment;
   169 }
   170 
   171 static inline bool
   172 IsUint32AddSafe(unsigned a, unsigned b)
   173 {
   174     if (!a || !b)
   175         return true;
   176     size_t log2_a = Log2(a);
   177     size_t log2_b = Log2(b);
   178     return (log2_a < sizeof(unsigned) * 8) &&
   179            (log2_b < sizeof(unsigned) * 8);
   180 }
   181 
   182 static inline bool
   183 IsUintPtrAddSafe(size_t a, size_t b)
   184 {
   185     if (!a || !b)
   186         return true;
   187     size_t log2_a = Log2(a);
   188     size_t log2_b = Log2(b);
   189     return (log2_a < sizeof(size_t) * 8) &&
   190            (log2_b < sizeof(size_t) * 8);
   191 }
   192 
   193 static inline bool
   194 IsUint32MultiplySafe(unsigned a, unsigned b)
   195 {
   196     if (a <= 1 || b <= 1)
   197         return true;
   198 
   199     size_t log2_a = Log2(a);
   200     size_t log2_b = Log2(b);
   201     return log2_a + log2_b <= sizeof(unsigned) * 8;
   202 }
   203 
   204 static inline bool
   205 IsUintPtrMultiplySafe(size_t a, size_t b)
   206 {
   207     if (a <= 1 || b <= 1)
   208         return true;
   209 
   210     size_t log2_a = Log2(a);
   211     size_t log2_b = Log2(b);
   212     return log2_a + log2_b <= sizeof(size_t) * 8;
   213 }
   214 
   215 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
   216 #define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
   217 
   218 #define IS_ALIGNED(addr, alignment)	(!(uintptr_t(addr) & ((alignment) - 1)))
   219 
   220 template <typename T>
   221 static inline bool
   222 IsAligned(T addr, size_t alignment)
   223 {
   224     assert(IsPowerOfTwo(alignment));
   225     return !(uintptr_t(addr) & (alignment - 1));
   226 }
   227 
   228 static inline Address
   229 AlignedBase(Address addr, size_t alignment)
   230 {
   231     assert(IsPowerOfTwo(alignment));
   232     return Address(uintptr_t(addr) & ~(alignment - 1));
   233 }
   234 
   235 template <typename T> static inline T
   236 Min(const T &t1, const T &t2)
   237 {
   238     return t1 < t2 ? t1 : t2;
   239 }
   240 
   241 #define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
   242 
   243 }
   244 
   245 #endif // _include_jitcraft_utility_h_