js/public/Utility.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef js_Utility_h
     8 #define js_Utility_h
    10 #include "mozilla/Assertions.h"
    11 #include "mozilla/Attributes.h"
    12 #include "mozilla/Compiler.h"
    13 #include "mozilla/Move.h"
    14 #include "mozilla/NullPtr.h"
    15 #include "mozilla/Scoped.h"
    16 #include "mozilla/TemplateLib.h"
    18 #include <stdlib.h>
    19 #include <string.h>
    21 #ifdef JS_OOM_DO_BACKTRACES
    22 #include <execinfo.h>
    23 #include <stdio.h>
    24 #endif
    26 #include "jstypes.h"
    28 /* The public JS engine namespace. */
    29 namespace JS {}
    31 /* The mozilla-shared reusable template/utility namespace. */
    32 namespace mozilla {}
    34 /* The private JS engine namespace. */
    35 namespace js {}
    37 /*
    38  * Patterns used by SpiderMonkey to overwrite unused memory. If you are
    39  * accessing an object with one of these pattern, you probably have a dangling
    40  * pointer.
    41  */
    42 #define JS_FRESH_NURSERY_PATTERN 0x2F
    43 #define JS_SWEPT_NURSERY_PATTERN 0x2B
    44 #define JS_ALLOCATED_NURSERY_PATTERN 0x2D
    45 #define JS_FRESH_TENURED_PATTERN 0x4F
    46 #define JS_SWEPT_TENURED_PATTERN 0x4B
    47 #define JS_ALLOCATED_TENURED_PATTERN 0x4D
    48 #define JS_SWEPT_CODE_PATTERN 0x3b
    49 #define JS_SWEPT_FRAME_PATTERN 0x5b
    51 #define JS_ASSERT(expr)           MOZ_ASSERT(expr)
    52 #define JS_ASSERT_IF(cond, expr)  MOZ_ASSERT_IF(cond, expr)
    54 #define JS_STATIC_ASSERT(cond)           static_assert(cond, "JS_STATIC_ASSERT")
    55 #define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
    57 extern MOZ_NORETURN JS_PUBLIC_API(void)
    58 JS_Assert(const char *s, const char *file, int ln);
    60 /*
    61  * Abort the process in a non-graceful manner. This will cause a core file,
    62  * call to the debugger or other moral equivalent as well as causing the
    63  * entire process to stop.
    64  */
    65 extern JS_PUBLIC_API(void) JS_Abort(void);
    67 /*
    68  * Custom allocator support for SpiderMonkey
    69  */
    70 #if defined JS_USE_CUSTOM_ALLOCATOR
    71 # include "jscustomallocator.h"
    72 #else
    73 # if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
    74 /*
    75  * In order to test OOM conditions, when the testing function
    76  * oomAfterAllocations COUNT is passed, we fail continuously after the NUM'th
    77  * allocation from now.
    78  */
    79 extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set in builtin/TestingFunctions.cpp */
    80 extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
    82 #ifdef JS_OOM_BREAKPOINT
    83 static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
    84 #define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
    85 #else
    86 #define JS_OOM_CALL_BP_FUNC() do {} while(0)
    87 #endif
    89 #  define JS_OOM_POSSIBLY_FAIL() \
    90     do \
    91     { \
    92         if (++OOM_counter > OOM_maxAllocations) { \
    93             JS_OOM_CALL_BP_FUNC();\
    94             return nullptr; \
    95         } \
    96     } while (0)
    98 # else
    99 #  define JS_OOM_POSSIBLY_FAIL() do {} while(0)
   100 # endif /* DEBUG || JS_OOM_BREAKPOINT */
   102 static inline void* js_malloc(size_t bytes)
   103 {
   104     JS_OOM_POSSIBLY_FAIL();
   105     return malloc(bytes);
   106 }
   108 static inline void* js_calloc(size_t bytes)
   109 {
   110     JS_OOM_POSSIBLY_FAIL();
   111     return calloc(bytes, 1);
   112 }
   114 static inline void* js_calloc(size_t nmemb, size_t size)
   115 {
   116     JS_OOM_POSSIBLY_FAIL();
   117     return calloc(nmemb, size);
   118 }
   120 static inline void* js_realloc(void* p, size_t bytes)
   121 {
   122     JS_OOM_POSSIBLY_FAIL();
   123     return realloc(p, bytes);
   124 }
   126 static inline void js_free(void* p)
   127 {
   128     free(p);
   129 }
   130 #endif/* JS_USE_CUSTOM_ALLOCATOR */
   132 #include <new>
   134 /*
   135  * Low-level memory management in SpiderMonkey:
   136  *
   137  *  ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
   138  *     to be redefined (via JS_USE_CUSTOM_ALLOCATOR) and Gecko even #define's
   139  *     these symbols.
   140  *
   141  *  ** Do not use the builtin C++ operator new and delete: these throw on
   142  *     error and we cannot override them not to.
   143  *
   144  * Allocation:
   145  *
   146  * - If the lifetime of the allocation is tied to the lifetime of a GC-thing
   147  *   (that is, finalizing the GC-thing will free the allocation), call one of
   148  *   the following functions:
   149  *
   150  *     JSContext::{malloc_,realloc_,calloc_,new_}
   151  *     JSRuntime::{malloc_,realloc_,calloc_,new_}
   152  *
   153  *   These functions accumulate the number of bytes allocated which is used as
   154  *   part of the GC-triggering heuristic.
   155  *
   156  *   The difference between the JSContext and JSRuntime versions is that the
   157  *   cx version reports an out-of-memory error on OOM. (This follows from the
   158  *   general SpiderMonkey idiom that a JSContext-taking function reports its
   159  *   own errors.)
   160  *
   161  * - Otherwise, use js_malloc/js_realloc/js_calloc/js_free/js_new
   162  *
   163  * Deallocation:
   164  *
   165  * - Ordinarily, use js_free/js_delete.
   166  *
   167  * - For deallocations during GC finalization, use one of the following
   168  *   operations on the FreeOp provided to the finalizer:
   169  *
   170  *     FreeOp::{free_,delete_}
   171  *
   172  *   The advantage of these operations is that the memory is batched and freed
   173  *   on another thread.
   174  */
   176 #define JS_NEW_BODY(allocator, t, parms)                                       \
   177     void *memory = allocator(sizeof(t));                                       \
   178     return memory ? new(memory) t parms : nullptr;
   180 /*
   181  * Given a class which should provide 'new' methods, add
   182  * JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
   183  * adds news with up to 12 parameters. Add more versions of new below if
   184  * you need more than 12 parameters.
   185  *
   186  * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
   187  * or the build will break.
   188  */
   189 #define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
   190     template <class T>\
   191     QUALIFIERS T *NEWNAME() MOZ_HEAP_ALLOCATOR {\
   192         JS_NEW_BODY(ALLOCATOR, T, ())\
   193     }\
   194 \
   195     template <class T, class P1>\
   196     QUALIFIERS T *NEWNAME(P1 &&p1) MOZ_HEAP_ALLOCATOR {\
   197         JS_NEW_BODY(ALLOCATOR, T,\
   198                     (mozilla::Forward<P1>(p1)))\
   199     }\
   200 \
   201     template <class T, class P1, class P2>\
   202     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2) MOZ_HEAP_ALLOCATOR {\
   203         JS_NEW_BODY(ALLOCATOR, T,\
   204                     (mozilla::Forward<P1>(p1),\
   205                      mozilla::Forward<P2>(p2)))\
   206     }\
   207 \
   208     template <class T, class P1, class P2, class P3>\
   209     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3) MOZ_HEAP_ALLOCATOR {\
   210         JS_NEW_BODY(ALLOCATOR, T,\
   211                     (mozilla::Forward<P1>(p1),\
   212                      mozilla::Forward<P2>(p2),\
   213                      mozilla::Forward<P3>(p3)))\
   214     }\
   215 \
   216     template <class T, class P1, class P2, class P3, class P4>\
   217     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4) MOZ_HEAP_ALLOCATOR {\
   218         JS_NEW_BODY(ALLOCATOR, T,\
   219                     (mozilla::Forward<P1>(p1),\
   220                      mozilla::Forward<P2>(p2),\
   221                      mozilla::Forward<P3>(p3),\
   222                      mozilla::Forward<P4>(p4)))\
   223     }\
   224 \
   225     template <class T, class P1, class P2, class P3, class P4, class P5>\
   226     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5) MOZ_HEAP_ALLOCATOR {\
   227         JS_NEW_BODY(ALLOCATOR, T,\
   228                     (mozilla::Forward<P1>(p1),\
   229                      mozilla::Forward<P2>(p2),\
   230                      mozilla::Forward<P3>(p3),\
   231                      mozilla::Forward<P4>(p4),\
   232                      mozilla::Forward<P5>(p5)))\
   233     }\
   234 \
   235     template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
   236     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6) MOZ_HEAP_ALLOCATOR {\
   237         JS_NEW_BODY(ALLOCATOR, T,\
   238                     (mozilla::Forward<P1>(p1),\
   239                      mozilla::Forward<P2>(p2),\
   240                      mozilla::Forward<P3>(p3),\
   241                      mozilla::Forward<P4>(p4),\
   242                      mozilla::Forward<P5>(p5),\
   243                      mozilla::Forward<P6>(p6)))\
   244     }\
   245 \
   246     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
   247     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7) MOZ_HEAP_ALLOCATOR {\
   248         JS_NEW_BODY(ALLOCATOR, T,\
   249                     (mozilla::Forward<P1>(p1),\
   250                      mozilla::Forward<P2>(p2),\
   251                      mozilla::Forward<P3>(p3),\
   252                      mozilla::Forward<P4>(p4),\
   253                      mozilla::Forward<P5>(p5),\
   254                      mozilla::Forward<P6>(p6),\
   255                      mozilla::Forward<P7>(p7)))\
   256     }\
   257 \
   258     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
   259     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8) MOZ_HEAP_ALLOCATOR {\
   260         JS_NEW_BODY(ALLOCATOR, T,\
   261                     (mozilla::Forward<P1>(p1),\
   262                      mozilla::Forward<P2>(p2),\
   263                      mozilla::Forward<P3>(p3),\
   264                      mozilla::Forward<P4>(p4),\
   265                      mozilla::Forward<P5>(p5),\
   266                      mozilla::Forward<P6>(p6),\
   267                      mozilla::Forward<P7>(p7),\
   268                      mozilla::Forward<P8>(p8)))\
   269     }\
   270 \
   271     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
   272     QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9) MOZ_HEAP_ALLOCATOR {\
   273         JS_NEW_BODY(ALLOCATOR, T,\
   274                     (mozilla::Forward<P1>(p1),\
   275                      mozilla::Forward<P2>(p2),\
   276                      mozilla::Forward<P3>(p3),\
   277                      mozilla::Forward<P4>(p4),\
   278                      mozilla::Forward<P5>(p5),\
   279                      mozilla::Forward<P6>(p6),\
   280                      mozilla::Forward<P7>(p7),\
   281                      mozilla::Forward<P8>(p8),\
   282                      mozilla::Forward<P9>(p9)))\
   283     }\
   284 \
   285     template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
   286     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 {\
   287         JS_NEW_BODY(ALLOCATOR, T,\
   288                     (mozilla::Forward<P1>(p1),\
   289                      mozilla::Forward<P2>(p2),\
   290                      mozilla::Forward<P3>(p3),\
   291                      mozilla::Forward<P4>(p4),\
   292                      mozilla::Forward<P5>(p5),\
   293                      mozilla::Forward<P6>(p6),\
   294                      mozilla::Forward<P7>(p7),\
   295                      mozilla::Forward<P8>(p8),\
   296                      mozilla::Forward<P9>(p9),\
   297                      mozilla::Forward<P10>(p10)))\
   298     }\
   299 \
   300     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>\
   301     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 {\
   302         JS_NEW_BODY(ALLOCATOR, T,\
   303                     (mozilla::Forward<P1>(p1),\
   304                      mozilla::Forward<P2>(p2),\
   305                      mozilla::Forward<P3>(p3),\
   306                      mozilla::Forward<P4>(p4),\
   307                      mozilla::Forward<P5>(p5),\
   308                      mozilla::Forward<P6>(p6),\
   309                      mozilla::Forward<P7>(p7),\
   310                      mozilla::Forward<P8>(p8),\
   311                      mozilla::Forward<P9>(p9),\
   312                      mozilla::Forward<P10>(p10),\
   313                      mozilla::Forward<P11>(p11)))\
   314     }\
   315 \
   316     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>\
   317     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 {\
   318         JS_NEW_BODY(ALLOCATOR, T,\
   319                     (mozilla::Forward<P1>(p1),\
   320                      mozilla::Forward<P2>(p2),\
   321                      mozilla::Forward<P3>(p3),\
   322                      mozilla::Forward<P4>(p4),\
   323                      mozilla::Forward<P5>(p5),\
   324                      mozilla::Forward<P6>(p6),\
   325                      mozilla::Forward<P7>(p7),\
   326                      mozilla::Forward<P8>(p8),\
   327                      mozilla::Forward<P9>(p9),\
   328                      mozilla::Forward<P10>(p10),\
   329                      mozilla::Forward<P11>(p11),\
   330                      mozilla::Forward<P12>(p12)))\
   331     }\
   333 JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE)
   335 template <class T>
   336 static MOZ_ALWAYS_INLINE void
   337 js_delete(T *p)
   338 {
   339     if (p) {
   340         p->~T();
   341         js_free(p);
   342     }
   343 }
   345 template<class T>
   346 static MOZ_ALWAYS_INLINE void
   347 js_delete_poison(T *p)
   348 {
   349     if (p) {
   350         p->~T();
   351         memset(p, 0x3B, sizeof(T));
   352         js_free(p);
   353     }
   354 }
   356 template <class T>
   357 static MOZ_ALWAYS_INLINE T *
   358 js_pod_malloc()
   359 {
   360     return (T *)js_malloc(sizeof(T));
   361 }
   363 template <class T>
   364 static MOZ_ALWAYS_INLINE T *
   365 js_pod_calloc()
   366 {
   367     return (T *)js_calloc(sizeof(T));
   368 }
   370 template <class T>
   371 static MOZ_ALWAYS_INLINE T *
   372 js_pod_malloc(size_t numElems)
   373 {
   374     if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
   375         return nullptr;
   376     return (T *)js_malloc(numElems * sizeof(T));
   377 }
   379 template <class T>
   380 static MOZ_ALWAYS_INLINE T *
   381 js_pod_calloc(size_t numElems)
   382 {
   383     if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
   384         return nullptr;
   385     return (T *)js_calloc(numElems * sizeof(T));
   386 }
   388 namespace js {
   390 template<typename T>
   391 struct ScopedFreePtrTraits
   392 {
   393     typedef T* type;
   394     static T* empty() { return nullptr; }
   395     static void release(T* ptr) { js_free(ptr); }
   396 };
   397 SCOPED_TEMPLATE(ScopedJSFreePtr, ScopedFreePtrTraits)
   399 template <typename T>
   400 struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
   401 {
   402     static void release(T *ptr) { js_delete(ptr); }
   403 };
   404 SCOPED_TEMPLATE(ScopedJSDeletePtr, ScopedDeletePtrTraits)
   406 template <typename T>
   407 struct ScopedReleasePtrTraits : public ScopedFreePtrTraits<T>
   408 {
   409     static void release(T *ptr) { if (ptr) ptr->release(); }
   410 };
   411 SCOPED_TEMPLATE(ScopedReleasePtr, ScopedReleasePtrTraits)
   413 } /* namespace js */
   415 namespace js {
   417 /* Integral types for all hash functions. */
   418 typedef uint32_t HashNumber;
   419 const unsigned HashNumberSizeBits = 32;
   421 namespace detail {
   423 /*
   424  * Given a raw hash code, h, return a number that can be used to select a hash
   425  * bucket.
   426  *
   427  * This function aims to produce as uniform an output distribution as possible,
   428  * especially in the most significant (leftmost) bits, even though the input
   429  * distribution may be highly nonrandom, given the constraints that this must
   430  * be deterministic and quick to compute.
   431  *
   432  * Since the leftmost bits of the result are best, the hash bucket index is
   433  * computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
   434  * right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
   435  *
   436  * FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
   437  */
   438 inline HashNumber
   439 ScrambleHashCode(HashNumber h)
   440 {
   441     /*
   442      * Simply returning h would not cause any hash tables to produce wrong
   443      * answers. But it can produce pathologically bad performance: The caller
   444      * right-shifts the result, keeping only the highest bits. The high bits of
   445      * hash codes are very often completely entropy-free. (So are the lowest
   446      * bits.)
   447      *
   448      * So we use Fibonacci hashing, as described in Knuth, The Art of Computer
   449      * Programming, 6.4. This mixes all the bits of the input hash code h.
   450      * 
   451      * The value of goldenRatio is taken from the hex
   452      * expansion of the golden ratio, which starts 1.9E3779B9....
   453      * This value is especially good if values with consecutive hash codes
   454      * are stored in a hash table; see Knuth for details.
   455      */
   456     static const HashNumber goldenRatio = 0x9E3779B9U;
   457     return h * goldenRatio;
   458 }
   460 } /* namespace detail */
   462 } /* namespace js */
   464 namespace JS {
   466 /*
   467  * Methods for poisoning GC heap pointer words and checking for poisoned words.
   468  * These are in this file for use in Value methods and so forth.
   469  *
   470  * If the moving GC hazard analysis is in use and detects a non-rooted stack
   471  * pointer to a GC thing, one byte of that pointer is poisoned to refer to an
   472  * invalid location. For both 32 bit and 64 bit systems, the fourth byte of the
   473  * pointer is overwritten, to reduce the likelihood of accidentally changing
   474  * a live integer value.
   475  */
   477 inline void PoisonPtr(void *v)
   478 {
   479 #if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
   480     uint8_t *ptr = (uint8_t *) v + 3;
   481     *ptr = JS_FREE_PATTERN;
   482 #endif
   483 }
   485 template <typename T>
   486 inline bool IsPoisonedPtr(T *v)
   487 {
   488 #if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
   489     uint32_t mask = uintptr_t(v) & 0xff000000;
   490     return mask == uint32_t(JS_FREE_PATTERN << 24);
   491 #else
   492     return false;
   493 #endif
   494 }
   496 }
   498 /* sixgill annotation defines */
   499 #ifndef HAVE_STATIC_ANNOTATIONS
   500 # define HAVE_STATIC_ANNOTATIONS
   501 # ifdef XGILL_PLUGIN
   502 #  define STATIC_PRECONDITION(COND)         __attribute__((precondition(#COND)))
   503 #  define STATIC_PRECONDITION_ASSUME(COND)  __attribute__((precondition_assume(#COND)))
   504 #  define STATIC_POSTCONDITION(COND)        __attribute__((postcondition(#COND)))
   505 #  define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
   506 #  define STATIC_INVARIANT(COND)            __attribute__((invariant(#COND)))
   507 #  define STATIC_INVARIANT_ASSUME(COND)     __attribute__((invariant_assume(#COND)))
   508 #  define STATIC_PASTE2(X,Y) X ## Y
   509 #  define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
   510 #  define STATIC_ASSERT(COND)                        \
   511   JS_BEGIN_MACRO                                     \
   512     __attribute__((assert_static(#COND), unused))    \
   513     int STATIC_PASTE1(assert_static_, __COUNTER__);  \
   514   JS_END_MACRO
   515 #  define STATIC_ASSUME(COND)                        \
   516   JS_BEGIN_MACRO                                     \
   517     __attribute__((assume_static(#COND), unused))    \
   518     int STATIC_PASTE1(assume_static_, __COUNTER__);  \
   519   JS_END_MACRO
   520 #  define STATIC_ASSERT_RUNTIME(COND)                       \
   521   JS_BEGIN_MACRO                                            \
   522     __attribute__((assert_static_runtime(#COND), unused))   \
   523     int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
   524   JS_END_MACRO
   525 # else /* XGILL_PLUGIN */
   526 #  define STATIC_PRECONDITION(COND)          /* nothing */
   527 #  define STATIC_PRECONDITION_ASSUME(COND)   /* nothing */
   528 #  define STATIC_POSTCONDITION(COND)         /* nothing */
   529 #  define STATIC_POSTCONDITION_ASSUME(COND)  /* nothing */
   530 #  define STATIC_INVARIANT(COND)             /* nothing */
   531 #  define STATIC_INVARIANT_ASSUME(COND)      /* nothing */
   532 #  define STATIC_ASSERT(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   533 #  define STATIC_ASSUME(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   534 #  define STATIC_ASSERT_RUNTIME(COND)  JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
   535 # endif /* XGILL_PLUGIN */
   536 # define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
   537 #endif /* HAVE_STATIC_ANNOTATIONS */
   539 #endif /* js_Utility_h */

mercurial