js/public/Utility.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/public/Utility.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,539 @@
     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 +#ifndef js_Utility_h
    1.11 +#define js_Utility_h
    1.12 +
    1.13 +#include "mozilla/Assertions.h"
    1.14 +#include "mozilla/Attributes.h"
    1.15 +#include "mozilla/Compiler.h"
    1.16 +#include "mozilla/Move.h"
    1.17 +#include "mozilla/NullPtr.h"
    1.18 +#include "mozilla/Scoped.h"
    1.19 +#include "mozilla/TemplateLib.h"
    1.20 +
    1.21 +#include <stdlib.h>
    1.22 +#include <string.h>
    1.23 +
    1.24 +#ifdef JS_OOM_DO_BACKTRACES
    1.25 +#include <execinfo.h>
    1.26 +#include <stdio.h>
    1.27 +#endif
    1.28 +
    1.29 +#include "jstypes.h"
    1.30 +
    1.31 +/* The public JS engine namespace. */
    1.32 +namespace JS {}
    1.33 +
    1.34 +/* The mozilla-shared reusable template/utility namespace. */
    1.35 +namespace mozilla {}
    1.36 +
    1.37 +/* The private JS engine namespace. */
    1.38 +namespace js {}
    1.39 +
    1.40 +/*
    1.41 + * Patterns used by SpiderMonkey to overwrite unused memory. If you are
    1.42 + * accessing an object with one of these pattern, you probably have a dangling
    1.43 + * pointer.
    1.44 + */
    1.45 +#define JS_FRESH_NURSERY_PATTERN 0x2F
    1.46 +#define JS_SWEPT_NURSERY_PATTERN 0x2B
    1.47 +#define JS_ALLOCATED_NURSERY_PATTERN 0x2D
    1.48 +#define JS_FRESH_TENURED_PATTERN 0x4F
    1.49 +#define JS_SWEPT_TENURED_PATTERN 0x4B
    1.50 +#define JS_ALLOCATED_TENURED_PATTERN 0x4D
    1.51 +#define JS_SWEPT_CODE_PATTERN 0x3b
    1.52 +#define JS_SWEPT_FRAME_PATTERN 0x5b
    1.53 +
    1.54 +#define JS_ASSERT(expr)           MOZ_ASSERT(expr)
    1.55 +#define JS_ASSERT_IF(cond, expr)  MOZ_ASSERT_IF(cond, expr)
    1.56 +
    1.57 +#define JS_STATIC_ASSERT(cond)           static_assert(cond, "JS_STATIC_ASSERT")
    1.58 +#define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
    1.59 +
    1.60 +extern MOZ_NORETURN JS_PUBLIC_API(void)
    1.61 +JS_Assert(const char *s, const char *file, int ln);
    1.62 +
    1.63 +/*
    1.64 + * Abort the process in a non-graceful manner. This will cause a core file,
    1.65 + * call to the debugger or other moral equivalent as well as causing the
    1.66 + * entire process to stop.
    1.67 + */
    1.68 +extern JS_PUBLIC_API(void) JS_Abort(void);
    1.69 +
    1.70 +/*
    1.71 + * Custom allocator support for SpiderMonkey
    1.72 + */
    1.73 +#if defined JS_USE_CUSTOM_ALLOCATOR
    1.74 +# include "jscustomallocator.h"
    1.75 +#else
    1.76 +# if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
    1.77 +/*
    1.78 + * In order to test OOM conditions, when the testing function
    1.79 + * oomAfterAllocations COUNT is passed, we fail continuously after the NUM'th
    1.80 + * allocation from now.
    1.81 + */
    1.82 +extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set in builtin/TestingFunctions.cpp */
    1.83 +extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
    1.84 +
    1.85 +#ifdef JS_OOM_BREAKPOINT
    1.86 +static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
    1.87 +#define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
    1.88 +#else
    1.89 +#define JS_OOM_CALL_BP_FUNC() do {} while(0)
    1.90 +#endif
    1.91 +
    1.92 +#  define JS_OOM_POSSIBLY_FAIL() \
    1.93 +    do \
    1.94 +    { \
    1.95 +        if (++OOM_counter > OOM_maxAllocations) { \
    1.96 +            JS_OOM_CALL_BP_FUNC();\
    1.97 +            return nullptr; \
    1.98 +        } \
    1.99 +    } while (0)
   1.100 +
   1.101 +# else
   1.102 +#  define JS_OOM_POSSIBLY_FAIL() do {} while(0)
   1.103 +# endif /* DEBUG || JS_OOM_BREAKPOINT */
   1.104 +
   1.105 +static inline void* js_malloc(size_t bytes)
   1.106 +{
   1.107 +    JS_OOM_POSSIBLY_FAIL();
   1.108 +    return malloc(bytes);
   1.109 +}
   1.110 +
   1.111 +static inline void* js_calloc(size_t bytes)
   1.112 +{
   1.113 +    JS_OOM_POSSIBLY_FAIL();
   1.114 +    return calloc(bytes, 1);
   1.115 +}
   1.116 +
   1.117 +static inline void* js_calloc(size_t nmemb, size_t size)
   1.118 +{
   1.119 +    JS_OOM_POSSIBLY_FAIL();
   1.120 +    return calloc(nmemb, size);
   1.121 +}
   1.122 +
   1.123 +static inline void* js_realloc(void* p, size_t bytes)
   1.124 +{
   1.125 +    JS_OOM_POSSIBLY_FAIL();
   1.126 +    return realloc(p, bytes);
   1.127 +}
   1.128 +
   1.129 +static inline void js_free(void* p)
   1.130 +{
   1.131 +    free(p);
   1.132 +}
   1.133 +#endif/* JS_USE_CUSTOM_ALLOCATOR */
   1.134 +
   1.135 +#include <new>
   1.136 +
   1.137 +/*
   1.138 + * Low-level memory management in SpiderMonkey:
   1.139 + *
   1.140 + *  ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
   1.141 + *     to be redefined (via JS_USE_CUSTOM_ALLOCATOR) and Gecko even #define's
   1.142 + *     these symbols.
   1.143 + *
   1.144 + *  ** Do not use the builtin C++ operator new and delete: these throw on
   1.145 + *     error and we cannot override them not to.
   1.146 + *
   1.147 + * Allocation:
   1.148 + *
   1.149 + * - If the lifetime of the allocation is tied to the lifetime of a GC-thing
   1.150 + *   (that is, finalizing the GC-thing will free the allocation), call one of
   1.151 + *   the following functions:
   1.152 + *
   1.153 + *     JSContext::{malloc_,realloc_,calloc_,new_}
   1.154 + *     JSRuntime::{malloc_,realloc_,calloc_,new_}
   1.155 + *
   1.156 + *   These functions accumulate the number of bytes allocated which is used as
   1.157 + *   part of the GC-triggering heuristic.
   1.158 + *
   1.159 + *   The difference between the JSContext and JSRuntime versions is that the
   1.160 + *   cx version reports an out-of-memory error on OOM. (This follows from the
   1.161 + *   general SpiderMonkey idiom that a JSContext-taking function reports its
   1.162 + *   own errors.)
   1.163 + *
   1.164 + * - Otherwise, use js_malloc/js_realloc/js_calloc/js_free/js_new
   1.165 + *
   1.166 + * Deallocation:
   1.167 + *
   1.168 + * - Ordinarily, use js_free/js_delete.
   1.169 + *
   1.170 + * - For deallocations during GC finalization, use one of the following
   1.171 + *   operations on the FreeOp provided to the finalizer:
   1.172 + *
   1.173 + *     FreeOp::{free_,delete_}
   1.174 + *
   1.175 + *   The advantage of these operations is that the memory is batched and freed
   1.176 + *   on another thread.
   1.177 + */
   1.178 +
   1.179 +#define JS_NEW_BODY(allocator, t, parms)                                       \
   1.180 +    void *memory = allocator(sizeof(t));                                       \
   1.181 +    return memory ? new(memory) t parms : nullptr;
   1.182 +
   1.183 +/*
   1.184 + * Given a class which should provide 'new' methods, add
   1.185 + * JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
   1.186 + * adds news with up to 12 parameters. Add more versions of new below if
   1.187 + * you need more than 12 parameters.
   1.188 + *
   1.189 + * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
   1.190 + * or the build will break.
   1.191 + */
   1.192 +#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
   1.193 +    template <class T>\
   1.194 +    QUALIFIERS T *NEWNAME() MOZ_HEAP_ALLOCATOR {\
   1.195 +        JS_NEW_BODY(ALLOCATOR, T, ())\
   1.196 +    }\
   1.197 +\
   1.198 +    template <class T, class P1>\
   1.199 +    QUALIFIERS T *NEWNAME(P1 &&p1) MOZ_HEAP_ALLOCATOR {\
   1.200 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.201 +                    (mozilla::Forward<P1>(p1)))\
   1.202 +    }\
   1.203 +\
   1.204 +    template <class T, class P1, class P2>\
   1.205 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2) MOZ_HEAP_ALLOCATOR {\
   1.206 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.207 +                    (mozilla::Forward<P1>(p1),\
   1.208 +                     mozilla::Forward<P2>(p2)))\
   1.209 +    }\
   1.210 +\
   1.211 +    template <class T, class P1, class P2, class P3>\
   1.212 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3) MOZ_HEAP_ALLOCATOR {\
   1.213 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.214 +                    (mozilla::Forward<P1>(p1),\
   1.215 +                     mozilla::Forward<P2>(p2),\
   1.216 +                     mozilla::Forward<P3>(p3)))\
   1.217 +    }\
   1.218 +\
   1.219 +    template <class T, class P1, class P2, class P3, class P4>\
   1.220 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4) MOZ_HEAP_ALLOCATOR {\
   1.221 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.222 +                    (mozilla::Forward<P1>(p1),\
   1.223 +                     mozilla::Forward<P2>(p2),\
   1.224 +                     mozilla::Forward<P3>(p3),\
   1.225 +                     mozilla::Forward<P4>(p4)))\
   1.226 +    }\
   1.227 +\
   1.228 +    template <class T, class P1, class P2, class P3, class P4, class P5>\
   1.229 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5) MOZ_HEAP_ALLOCATOR {\
   1.230 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.231 +                    (mozilla::Forward<P1>(p1),\
   1.232 +                     mozilla::Forward<P2>(p2),\
   1.233 +                     mozilla::Forward<P3>(p3),\
   1.234 +                     mozilla::Forward<P4>(p4),\
   1.235 +                     mozilla::Forward<P5>(p5)))\
   1.236 +    }\
   1.237 +\
   1.238 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
   1.239 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6) MOZ_HEAP_ALLOCATOR {\
   1.240 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.241 +                    (mozilla::Forward<P1>(p1),\
   1.242 +                     mozilla::Forward<P2>(p2),\
   1.243 +                     mozilla::Forward<P3>(p3),\
   1.244 +                     mozilla::Forward<P4>(p4),\
   1.245 +                     mozilla::Forward<P5>(p5),\
   1.246 +                     mozilla::Forward<P6>(p6)))\
   1.247 +    }\
   1.248 +\
   1.249 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
   1.250 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7) MOZ_HEAP_ALLOCATOR {\
   1.251 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.252 +                    (mozilla::Forward<P1>(p1),\
   1.253 +                     mozilla::Forward<P2>(p2),\
   1.254 +                     mozilla::Forward<P3>(p3),\
   1.255 +                     mozilla::Forward<P4>(p4),\
   1.256 +                     mozilla::Forward<P5>(p5),\
   1.257 +                     mozilla::Forward<P6>(p6),\
   1.258 +                     mozilla::Forward<P7>(p7)))\
   1.259 +    }\
   1.260 +\
   1.261 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
   1.262 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8) MOZ_HEAP_ALLOCATOR {\
   1.263 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.264 +                    (mozilla::Forward<P1>(p1),\
   1.265 +                     mozilla::Forward<P2>(p2),\
   1.266 +                     mozilla::Forward<P3>(p3),\
   1.267 +                     mozilla::Forward<P4>(p4),\
   1.268 +                     mozilla::Forward<P5>(p5),\
   1.269 +                     mozilla::Forward<P6>(p6),\
   1.270 +                     mozilla::Forward<P7>(p7),\
   1.271 +                     mozilla::Forward<P8>(p8)))\
   1.272 +    }\
   1.273 +\
   1.274 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
   1.275 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9) MOZ_HEAP_ALLOCATOR {\
   1.276 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.277 +                    (mozilla::Forward<P1>(p1),\
   1.278 +                     mozilla::Forward<P2>(p2),\
   1.279 +                     mozilla::Forward<P3>(p3),\
   1.280 +                     mozilla::Forward<P4>(p4),\
   1.281 +                     mozilla::Forward<P5>(p5),\
   1.282 +                     mozilla::Forward<P6>(p6),\
   1.283 +                     mozilla::Forward<P7>(p7),\
   1.284 +                     mozilla::Forward<P8>(p8),\
   1.285 +                     mozilla::Forward<P9>(p9)))\
   1.286 +    }\
   1.287 +\
   1.288 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
   1.289 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10) MOZ_HEAP_ALLOCATOR {\
   1.290 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.291 +                    (mozilla::Forward<P1>(p1),\
   1.292 +                     mozilla::Forward<P2>(p2),\
   1.293 +                     mozilla::Forward<P3>(p3),\
   1.294 +                     mozilla::Forward<P4>(p4),\
   1.295 +                     mozilla::Forward<P5>(p5),\
   1.296 +                     mozilla::Forward<P6>(p6),\
   1.297 +                     mozilla::Forward<P7>(p7),\
   1.298 +                     mozilla::Forward<P8>(p8),\
   1.299 +                     mozilla::Forward<P9>(p9),\
   1.300 +                     mozilla::Forward<P10>(p10)))\
   1.301 +    }\
   1.302 +\
   1.303 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
   1.304 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11) MOZ_HEAP_ALLOCATOR {\
   1.305 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.306 +                    (mozilla::Forward<P1>(p1),\
   1.307 +                     mozilla::Forward<P2>(p2),\
   1.308 +                     mozilla::Forward<P3>(p3),\
   1.309 +                     mozilla::Forward<P4>(p4),\
   1.310 +                     mozilla::Forward<P5>(p5),\
   1.311 +                     mozilla::Forward<P6>(p6),\
   1.312 +                     mozilla::Forward<P7>(p7),\
   1.313 +                     mozilla::Forward<P8>(p8),\
   1.314 +                     mozilla::Forward<P9>(p9),\
   1.315 +                     mozilla::Forward<P10>(p10),\
   1.316 +                     mozilla::Forward<P11>(p11)))\
   1.317 +    }\
   1.318 +\
   1.319 +    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
   1.320 +    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11, P12 &&p12) MOZ_HEAP_ALLOCATOR {\
   1.321 +        JS_NEW_BODY(ALLOCATOR, T,\
   1.322 +                    (mozilla::Forward<P1>(p1),\
   1.323 +                     mozilla::Forward<P2>(p2),\
   1.324 +                     mozilla::Forward<P3>(p3),\
   1.325 +                     mozilla::Forward<P4>(p4),\
   1.326 +                     mozilla::Forward<P5>(p5),\
   1.327 +                     mozilla::Forward<P6>(p6),\
   1.328 +                     mozilla::Forward<P7>(p7),\
   1.329 +                     mozilla::Forward<P8>(p8),\
   1.330 +                     mozilla::Forward<P9>(p9),\
   1.331 +                     mozilla::Forward<P10>(p10),\
   1.332 +                     mozilla::Forward<P11>(p11),\
   1.333 +                     mozilla::Forward<P12>(p12)))\
   1.334 +    }\
   1.335 +
   1.336 +JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE)
   1.337 +
   1.338 +template <class T>
   1.339 +static MOZ_ALWAYS_INLINE void
   1.340 +js_delete(T *p)
   1.341 +{
   1.342 +    if (p) {
   1.343 +        p->~T();
   1.344 +        js_free(p);
   1.345 +    }
   1.346 +}
   1.347 +
   1.348 +template<class T>
   1.349 +static MOZ_ALWAYS_INLINE void
   1.350 +js_delete_poison(T *p)
   1.351 +{
   1.352 +    if (p) {
   1.353 +        p->~T();
   1.354 +        memset(p, 0x3B, sizeof(T));
   1.355 +        js_free(p);
   1.356 +    }
   1.357 +}
   1.358 +
   1.359 +template <class T>
   1.360 +static MOZ_ALWAYS_INLINE T *
   1.361 +js_pod_malloc()
   1.362 +{
   1.363 +    return (T *)js_malloc(sizeof(T));
   1.364 +}
   1.365 +
   1.366 +template <class T>
   1.367 +static MOZ_ALWAYS_INLINE T *
   1.368 +js_pod_calloc()
   1.369 +{
   1.370 +    return (T *)js_calloc(sizeof(T));
   1.371 +}
   1.372 +
   1.373 +template <class T>
   1.374 +static MOZ_ALWAYS_INLINE T *
   1.375 +js_pod_malloc(size_t numElems)
   1.376 +{
   1.377 +    if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
   1.378 +        return nullptr;
   1.379 +    return (T *)js_malloc(numElems * sizeof(T));
   1.380 +}
   1.381 +
   1.382 +template <class T>
   1.383 +static MOZ_ALWAYS_INLINE T *
   1.384 +js_pod_calloc(size_t numElems)
   1.385 +{
   1.386 +    if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
   1.387 +        return nullptr;
   1.388 +    return (T *)js_calloc(numElems * sizeof(T));
   1.389 +}
   1.390 +
   1.391 +namespace js {
   1.392 +
   1.393 +template<typename T>
   1.394 +struct ScopedFreePtrTraits
   1.395 +{
   1.396 +    typedef T* type;
   1.397 +    static T* empty() { return nullptr; }
   1.398 +    static void release(T* ptr) { js_free(ptr); }
   1.399 +};
   1.400 +SCOPED_TEMPLATE(ScopedJSFreePtr, ScopedFreePtrTraits)
   1.401 +
   1.402 +template <typename T>
   1.403 +struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
   1.404 +{
   1.405 +    static void release(T *ptr) { js_delete(ptr); }
   1.406 +};
   1.407 +SCOPED_TEMPLATE(ScopedJSDeletePtr, ScopedDeletePtrTraits)
   1.408 +
   1.409 +template <typename T>
   1.410 +struct ScopedReleasePtrTraits : public ScopedFreePtrTraits<T>
   1.411 +{
   1.412 +    static void release(T *ptr) { if (ptr) ptr->release(); }
   1.413 +};
   1.414 +SCOPED_TEMPLATE(ScopedReleasePtr, ScopedReleasePtrTraits)
   1.415 +
   1.416 +} /* namespace js */
   1.417 +
   1.418 +namespace js {
   1.419 +
   1.420 +/* Integral types for all hash functions. */
   1.421 +typedef uint32_t HashNumber;
   1.422 +const unsigned HashNumberSizeBits = 32;
   1.423 +
   1.424 +namespace detail {
   1.425 +
   1.426 +/*
   1.427 + * Given a raw hash code, h, return a number that can be used to select a hash
   1.428 + * bucket.
   1.429 + *
   1.430 + * This function aims to produce as uniform an output distribution as possible,
   1.431 + * especially in the most significant (leftmost) bits, even though the input
   1.432 + * distribution may be highly nonrandom, given the constraints that this must
   1.433 + * be deterministic and quick to compute.
   1.434 + *
   1.435 + * Since the leftmost bits of the result are best, the hash bucket index is
   1.436 + * computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
   1.437 + * right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
   1.438 + *
   1.439 + * FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
   1.440 + */
   1.441 +inline HashNumber
   1.442 +ScrambleHashCode(HashNumber h)
   1.443 +{
   1.444 +    /*
   1.445 +     * Simply returning h would not cause any hash tables to produce wrong
   1.446 +     * answers. But it can produce pathologically bad performance: The caller
   1.447 +     * right-shifts the result, keeping only the highest bits. The high bits of
   1.448 +     * hash codes are very often completely entropy-free. (So are the lowest
   1.449 +     * bits.)
   1.450 +     *
   1.451 +     * So we use Fibonacci hashing, as described in Knuth, The Art of Computer
   1.452 +     * Programming, 6.4. This mixes all the bits of the input hash code h.
   1.453 +     * 
   1.454 +     * The value of goldenRatio is taken from the hex
   1.455 +     * expansion of the golden ratio, which starts 1.9E3779B9....
   1.456 +     * This value is especially good if values with consecutive hash codes
   1.457 +     * are stored in a hash table; see Knuth for details.
   1.458 +     */
   1.459 +    static const HashNumber goldenRatio = 0x9E3779B9U;
   1.460 +    return h * goldenRatio;
   1.461 +}
   1.462 +
   1.463 +} /* namespace detail */
   1.464 +
   1.465 +} /* namespace js */
   1.466 +
   1.467 +namespace JS {
   1.468 +
   1.469 +/*
   1.470 + * Methods for poisoning GC heap pointer words and checking for poisoned words.
   1.471 + * These are in this file for use in Value methods and so forth.
   1.472 + *
   1.473 + * If the moving GC hazard analysis is in use and detects a non-rooted stack
   1.474 + * pointer to a GC thing, one byte of that pointer is poisoned to refer to an
   1.475 + * invalid location. For both 32 bit and 64 bit systems, the fourth byte of the
   1.476 + * pointer is overwritten, to reduce the likelihood of accidentally changing
   1.477 + * a live integer value.
   1.478 + */
   1.479 +
   1.480 +inline void PoisonPtr(void *v)
   1.481 +{
   1.482 +#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
   1.483 +    uint8_t *ptr = (uint8_t *) v + 3;
   1.484 +    *ptr = JS_FREE_PATTERN;
   1.485 +#endif
   1.486 +}
   1.487 +
   1.488 +template <typename T>
   1.489 +inline bool IsPoisonedPtr(T *v)
   1.490 +{
   1.491 +#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
   1.492 +    uint32_t mask = uintptr_t(v) & 0xff000000;
   1.493 +    return mask == uint32_t(JS_FREE_PATTERN << 24);
   1.494 +#else
   1.495 +    return false;
   1.496 +#endif
   1.497 +}
   1.498 +
   1.499 +}
   1.500 +
   1.501 +/* sixgill annotation defines */
   1.502 +#ifndef HAVE_STATIC_ANNOTATIONS
   1.503 +# define HAVE_STATIC_ANNOTATIONS
   1.504 +# ifdef XGILL_PLUGIN
   1.505 +#  define STATIC_PRECONDITION(COND)         __attribute__((precondition(#COND)))
   1.506 +#  define STATIC_PRECONDITION_ASSUME(COND)  __attribute__((precondition_assume(#COND)))
   1.507 +#  define STATIC_POSTCONDITION(COND)        __attribute__((postcondition(#COND)))
   1.508 +#  define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
   1.509 +#  define STATIC_INVARIANT(COND)            __attribute__((invariant(#COND)))
   1.510 +#  define STATIC_INVARIANT_ASSUME(COND)     __attribute__((invariant_assume(#COND)))
   1.511 +#  define STATIC_PASTE2(X,Y) X ## Y
   1.512 +#  define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
   1.513 +#  define STATIC_ASSERT(COND)                        \
   1.514 +  JS_BEGIN_MACRO                                     \
   1.515 +    __attribute__((assert_static(#COND), unused))    \
   1.516 +    int STATIC_PASTE1(assert_static_, __COUNTER__);  \
   1.517 +  JS_END_MACRO
   1.518 +#  define STATIC_ASSUME(COND)                        \
   1.519 +  JS_BEGIN_MACRO                                     \
   1.520 +    __attribute__((assume_static(#COND), unused))    \
   1.521 +    int STATIC_PASTE1(assume_static_, __COUNTER__);  \
   1.522 +  JS_END_MACRO
   1.523 +#  define STATIC_ASSERT_RUNTIME(COND)                       \
   1.524 +  JS_BEGIN_MACRO                                            \
   1.525 +    __attribute__((assert_static_runtime(#COND), unused))   \
   1.526 +    int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
   1.527 +  JS_END_MACRO
   1.528 +# else /* XGILL_PLUGIN */
   1.529 +#  define STATIC_PRECONDITION(COND)          /* nothing */
   1.530 +#  define STATIC_PRECONDITION_ASSUME(COND)   /* nothing */
   1.531 +#  define STATIC_POSTCONDITION(COND)         /* nothing */
   1.532 +#  define STATIC_POSTCONDITION_ASSUME(COND)  /* nothing */
   1.533 +#  define STATIC_INVARIANT(COND)             /* nothing */
   1.534 +#  define STATIC_INVARIANT_ASSUME(COND)      /* nothing */
   1.535 +#  define STATIC_ASSERT(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   1.536 +#  define STATIC_ASSUME(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   1.537 +#  define STATIC_ASSERT_RUNTIME(COND)  JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   1.538 +# endif /* XGILL_PLUGIN */
   1.539 +# define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
   1.540 +#endif /* HAVE_STATIC_ANNOTATIONS */
   1.541 +
   1.542 +#endif /* js_Utility_h */

mercurial