1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsutil.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,362 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * PR assertion checker. 1.12 + */ 1.13 + 1.14 +#ifndef jsutil_h 1.15 +#define jsutil_h 1.16 + 1.17 +#include "mozilla/Assertions.h" 1.18 +#include "mozilla/Compiler.h" 1.19 +#include "mozilla/GuardObjects.h" 1.20 + 1.21 +#include <limits.h> 1.22 + 1.23 +#include "js/Utility.h" 1.24 + 1.25 +#define JS_ALWAYS_TRUE(expr) MOZ_ALWAYS_TRUE(expr) 1.26 +#define JS_ALWAYS_FALSE(expr) MOZ_ALWAYS_FALSE(expr) 1.27 + 1.28 +#if defined(JS_DEBUG) 1.29 +# define JS_DIAGNOSTICS_ASSERT(expr) MOZ_ASSERT(expr) 1.30 +#elif defined(JS_CRASH_DIAGNOSTICS) 1.31 +# define JS_DIAGNOSTICS_ASSERT(expr) do { if (MOZ_UNLIKELY(!(expr))) MOZ_CRASH(); } while(0) 1.32 +#else 1.33 +# define JS_DIAGNOSTICS_ASSERT(expr) ((void) 0) 1.34 +#endif 1.35 + 1.36 +static MOZ_ALWAYS_INLINE void * 1.37 +js_memcpy(void *dst_, const void *src_, size_t len) 1.38 +{ 1.39 + char *dst = (char *) dst_; 1.40 + const char *src = (const char *) src_; 1.41 + JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len); 1.42 + JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len); 1.43 + 1.44 + return memcpy(dst, src, len); 1.45 +} 1.46 + 1.47 +namespace js { 1.48 + 1.49 +template <class T> 1.50 +struct AlignmentTestStruct 1.51 +{ 1.52 + char c; 1.53 + T t; 1.54 +}; 1.55 + 1.56 +/* This macro determines the alignment requirements of a type. */ 1.57 +#define JS_ALIGNMENT_OF(t_) \ 1.58 + (sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_)) 1.59 + 1.60 +template <class T> 1.61 +class AlignedPtrAndFlag 1.62 +{ 1.63 + uintptr_t bits; 1.64 + 1.65 + public: 1.66 + AlignedPtrAndFlag(T *t, bool aFlag) { 1.67 + JS_ASSERT((uintptr_t(t) & 1) == 0); 1.68 + bits = uintptr_t(t) | uintptr_t(aFlag); 1.69 + } 1.70 + 1.71 + T *ptr() const { 1.72 + return (T *)(bits & ~uintptr_t(1)); 1.73 + } 1.74 + 1.75 + bool flag() const { 1.76 + return (bits & 1) != 0; 1.77 + } 1.78 + 1.79 + void setPtr(T *t) { 1.80 + JS_ASSERT((uintptr_t(t) & 1) == 0); 1.81 + bits = uintptr_t(t) | uintptr_t(flag()); 1.82 + } 1.83 + 1.84 + void setFlag() { 1.85 + bits |= 1; 1.86 + } 1.87 + 1.88 + void unsetFlag() { 1.89 + bits &= ~uintptr_t(1); 1.90 + } 1.91 + 1.92 + void set(T *t, bool aFlag) { 1.93 + JS_ASSERT((uintptr_t(t) & 1) == 0); 1.94 + bits = uintptr_t(t) | aFlag; 1.95 + } 1.96 +}; 1.97 + 1.98 +template <class T> 1.99 +static inline void 1.100 +Reverse(T *beg, T *end) 1.101 +{ 1.102 + while (beg != end) { 1.103 + if (--end == beg) 1.104 + return; 1.105 + T tmp = *beg; 1.106 + *beg = *end; 1.107 + *end = tmp; 1.108 + ++beg; 1.109 + } 1.110 +} 1.111 + 1.112 +template <class T> 1.113 +static inline T * 1.114 +Find(T *beg, T *end, const T &v) 1.115 +{ 1.116 + for (T *p = beg; p != end; ++p) { 1.117 + if (*p == v) 1.118 + return p; 1.119 + } 1.120 + return end; 1.121 +} 1.122 + 1.123 +template <class Container> 1.124 +static inline typename Container::ElementType * 1.125 +Find(Container &c, const typename Container::ElementType &v) 1.126 +{ 1.127 + return Find(c.begin(), c.end(), v); 1.128 +} 1.129 + 1.130 +template <typename InputIterT, typename CallableT> 1.131 +void 1.132 +ForEach(InputIterT begin, InputIterT end, CallableT f) 1.133 +{ 1.134 + for (; begin != end; ++begin) 1.135 + f(*begin); 1.136 +} 1.137 + 1.138 +template <class T> 1.139 +static inline T 1.140 +Min(T t1, T t2) 1.141 +{ 1.142 + return t1 < t2 ? t1 : t2; 1.143 +} 1.144 + 1.145 +template <class T> 1.146 +static inline T 1.147 +Max(T t1, T t2) 1.148 +{ 1.149 + return t1 > t2 ? t1 : t2; 1.150 +} 1.151 + 1.152 +/* Allows a const variable to be initialized after its declaration. */ 1.153 +template <class T> 1.154 +static T& 1.155 +InitConst(const T &t) 1.156 +{ 1.157 + return const_cast<T &>(t); 1.158 +} 1.159 + 1.160 +template <class T, class U> 1.161 +MOZ_ALWAYS_INLINE T & 1.162 +ImplicitCast(U &u) 1.163 +{ 1.164 + T &t = u; 1.165 + return t; 1.166 +} 1.167 + 1.168 +template<typename T> 1.169 +class AutoScopedAssign 1.170 +{ 1.171 + public: 1.172 + AutoScopedAssign(T *addr, const T &value 1.173 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.174 + : addr_(addr), old(*addr_) 1.175 + { 1.176 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.177 + *addr_ = value; 1.178 + } 1.179 + 1.180 + ~AutoScopedAssign() { *addr_ = old; } 1.181 + 1.182 + private: 1.183 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.184 + T *addr_; 1.185 + T old; 1.186 +}; 1.187 + 1.188 +template <typename T> 1.189 +static inline bool 1.190 +IsPowerOfTwo(T t) 1.191 +{ 1.192 + return t && !(t & (t - 1)); 1.193 +} 1.194 + 1.195 +template <typename T, typename U> 1.196 +static inline U 1.197 +ComputeByteAlignment(T bytes, U alignment) 1.198 +{ 1.199 + JS_ASSERT(IsPowerOfTwo(alignment)); 1.200 + return (alignment - (bytes % alignment)) % alignment; 1.201 +} 1.202 + 1.203 +template <typename T, typename U> 1.204 +static inline T 1.205 +AlignBytes(T bytes, U alignment) 1.206 +{ 1.207 + return bytes + ComputeByteAlignment(bytes, alignment); 1.208 +} 1.209 + 1.210 +static MOZ_ALWAYS_INLINE size_t 1.211 +UnsignedPtrDiff(const void *bigger, const void *smaller) 1.212 +{ 1.213 + return size_t(bigger) - size_t(smaller); 1.214 +} 1.215 + 1.216 +/*****************************************************************************/ 1.217 + 1.218 +/* A bit array is an array of bits represented by an array of words (size_t). */ 1.219 + 1.220 +static const size_t BitArrayElementBits = sizeof(size_t) * CHAR_BIT; 1.221 + 1.222 +static inline unsigned 1.223 +NumWordsForBitArrayOfLength(size_t length) 1.224 +{ 1.225 + return (length + (BitArrayElementBits - 1)) / BitArrayElementBits; 1.226 +} 1.227 + 1.228 +static inline unsigned 1.229 +BitArrayIndexToWordIndex(size_t length, size_t bitIndex) 1.230 +{ 1.231 + unsigned wordIndex = bitIndex / BitArrayElementBits; 1.232 + JS_ASSERT(wordIndex < length); 1.233 + return wordIndex; 1.234 +} 1.235 + 1.236 +static inline size_t 1.237 +BitArrayIndexToWordMask(size_t i) 1.238 +{ 1.239 + return size_t(1) << (i % BitArrayElementBits); 1.240 +} 1.241 + 1.242 +static inline bool 1.243 +IsBitArrayElementSet(size_t *array, size_t length, size_t i) 1.244 +{ 1.245 + return array[BitArrayIndexToWordIndex(length, i)] & BitArrayIndexToWordMask(i); 1.246 +} 1.247 + 1.248 +static inline bool 1.249 +IsAnyBitArrayElementSet(size_t *array, size_t length) 1.250 +{ 1.251 + unsigned numWords = NumWordsForBitArrayOfLength(length); 1.252 + for (unsigned i = 0; i < numWords; ++i) { 1.253 + if (array[i]) 1.254 + return true; 1.255 + } 1.256 + return false; 1.257 +} 1.258 + 1.259 +static inline void 1.260 +SetBitArrayElement(size_t *array, size_t length, size_t i) 1.261 +{ 1.262 + array[BitArrayIndexToWordIndex(length, i)] |= BitArrayIndexToWordMask(i); 1.263 +} 1.264 + 1.265 +static inline void 1.266 +ClearBitArrayElement(size_t *array, size_t length, size_t i) 1.267 +{ 1.268 + array[BitArrayIndexToWordIndex(length, i)] &= ~BitArrayIndexToWordMask(i); 1.269 +} 1.270 + 1.271 +static inline void 1.272 +ClearAllBitArrayElements(size_t *array, size_t length) 1.273 +{ 1.274 + for (unsigned i = 0; i < length; ++i) 1.275 + array[i] = 0; 1.276 +} 1.277 + 1.278 +} /* namespace js */ 1.279 + 1.280 +/* Crash diagnostics */ 1.281 +#ifdef DEBUG 1.282 +# define JS_CRASH_DIAGNOSTICS 1 1.283 +#endif 1.284 +#if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL) 1.285 +# define JS_POISON(p, val, size) memset((p), (val), (size)) 1.286 +#else 1.287 +# define JS_POISON(p, val, size) ((void) 0) 1.288 +#endif 1.289 + 1.290 +/* Bug 984101: Disable labeled poisoning until we have poison checking. */ 1.291 +#define JS_EXTRA_POISON(p, val, size) ((void) 0) 1.292 + 1.293 +/* Basic stats */ 1.294 +#ifdef DEBUG 1.295 +# define JS_BASIC_STATS 1 1.296 +#endif 1.297 +#ifdef JS_BASIC_STATS 1.298 +# include <stdio.h> 1.299 +typedef struct JSBasicStats { 1.300 + uint32_t num; 1.301 + uint32_t max; 1.302 + double sum; 1.303 + double sqsum; 1.304 + uint32_t logscale; /* logarithmic scale: 0 (linear), 2, 10 */ 1.305 + uint32_t hist[11]; 1.306 +} JSBasicStats; 1.307 +# define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}} 1.308 +# define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats)) 1.309 +# define JS_BASIC_STATS_ACCUM(bs,val) \ 1.310 + JS_BasicStatsAccum(bs, val) 1.311 +# define JS_MeanAndStdDevBS(bs,sigma) \ 1.312 + JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma) 1.313 +extern void 1.314 +JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val); 1.315 +extern double 1.316 +JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma); 1.317 +extern void 1.318 +JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp); 1.319 +extern void 1.320 +JS_DumpHistogram(JSBasicStats *bs, FILE *fp); 1.321 +#else 1.322 +# define JS_BASIC_STATS_ACCUM(bs,val) 1.323 +#endif 1.324 + 1.325 +/* A jsbitmap_t is a long integer that can be used for bitmaps. */ 1.326 +typedef size_t jsbitmap; 1.327 +#define JS_BITMAP_NBITS (sizeof(jsbitmap) * CHAR_BIT) 1.328 +#define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] & \ 1.329 + (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS))) 1.330 +#define JS_SET_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] |= \ 1.331 + (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS))) 1.332 +#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] &= \ 1.333 + ~(jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS))) 1.334 + 1.335 +/* Wrapper for various macros to stop warnings coming from their expansions. */ 1.336 +#if defined(__clang__) 1.337 +# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \ 1.338 + JS_BEGIN_MACRO \ 1.339 + _Pragma("clang diagnostic push") \ 1.340 + /* If these _Pragmas cause warnings for you, try disabling ccache. */ \ 1.341 + _Pragma("clang diagnostic ignored \"-Wunused-value\"") \ 1.342 + { expr; } \ 1.343 + _Pragma("clang diagnostic pop") \ 1.344 + JS_END_MACRO 1.345 +#elif MOZ_IS_GCC 1.346 + 1.347 +#if MOZ_GCC_VERSION_AT_LEAST(4, 6, 0) 1.348 +# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \ 1.349 + JS_BEGIN_MACRO \ 1.350 + _Pragma("GCC diagnostic push") \ 1.351 + _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \ 1.352 + expr; \ 1.353 + _Pragma("GCC diagnostic pop") \ 1.354 + JS_END_MACRO 1.355 +#endif 1.356 +#endif 1.357 + 1.358 +#if !defined(JS_SILENCE_UNUSED_VALUE_IN_EXPR) 1.359 +# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \ 1.360 + JS_BEGIN_MACRO \ 1.361 + expr; \ 1.362 + JS_END_MACRO 1.363 +#endif 1.364 + 1.365 +#endif /* jsutil_h */