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 */