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