LCOV - code coverage report
Current view: top level - js/public - Utility.h (source / functions) Hit Total Coverage
Test: output.info Lines: 70 102 68.6 %
Date: 2017-07-14 16:53:18 Functions: 490 1411 34.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #ifndef js_Utility_h
       8             : #define js_Utility_h
       9             : 
      10             : #include "mozilla/Assertions.h"
      11             : #include "mozilla/Atomics.h"
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/Compiler.h"
      14             : #include "mozilla/Move.h"
      15             : #include "mozilla/Scoped.h"
      16             : #include "mozilla/TemplateLib.h"
      17             : #include "mozilla/UniquePtr.h"
      18             : 
      19             : #include <stdlib.h>
      20             : #include <string.h>
      21             : 
      22             : #ifdef JS_OOM_DO_BACKTRACES
      23             : #include <execinfo.h>
      24             : #include <stdio.h>
      25             : #endif
      26             : 
      27             : #include "jstypes.h"
      28             : 
      29             : /* The public JS engine namespace. */
      30             : namespace JS {}
      31             : 
      32             : /* The mozilla-shared reusable template/utility namespace. */
      33             : namespace mozilla {}
      34             : 
      35             : /* The private JS engine namespace. */
      36             : namespace js {}
      37             : 
      38             : #define JS_STATIC_ASSERT(cond)           static_assert(cond, "JS_STATIC_ASSERT")
      39             : #define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
      40             : 
      41             : extern MOZ_NORETURN MOZ_COLD JS_PUBLIC_API(void)
      42             : JS_Assert(const char* s, const char* file, int ln);
      43             : 
      44             : /*
      45             :  * Custom allocator support for SpiderMonkey
      46             :  */
      47             : #if defined JS_USE_CUSTOM_ALLOCATOR
      48             : # include "jscustomallocator.h"
      49             : #else
      50             : 
      51             : namespace js {
      52             : namespace oom {
      53             : 
      54             : /*
      55             :  * To make testing OOM in certain helper threads more effective,
      56             :  * allow restricting the OOM testing to a certain helper thread
      57             :  * type. This allows us to fail e.g. in off-thread script parsing
      58             :  * without causing an OOM in the active thread first.
      59             :  */
      60             : enum ThreadType {
      61             :     THREAD_TYPE_NONE = 0,       // 0
      62             :     THREAD_TYPE_COOPERATING,    // 1
      63             :     THREAD_TYPE_WASM,           // 2
      64             :     THREAD_TYPE_ION,            // 3
      65             :     THREAD_TYPE_PARSE,          // 4
      66             :     THREAD_TYPE_COMPRESS,       // 5
      67             :     THREAD_TYPE_GCHELPER,       // 6
      68             :     THREAD_TYPE_GCPARALLEL,     // 7
      69             :     THREAD_TYPE_PROMISE_TASK,   // 8
      70             :     THREAD_TYPE_ION_FREE,       // 9
      71             :     THREAD_TYPE_MAX             // Used to check shell function arguments
      72             : };
      73             : 
      74             : /*
      75             :  * Getter/Setter functions to encapsulate mozilla::ThreadLocal,
      76             :  * implementation is in jsutil.cpp.
      77             :  */
      78             : # if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
      79             : extern bool InitThreadType(void);
      80             : extern void SetThreadType(ThreadType);
      81             : extern JS_FRIEND_API(uint32_t) GetThreadType(void);
      82             : # else
      83             : inline bool InitThreadType(void) { return true; }
      84             : inline void SetThreadType(ThreadType t) {};
      85             : inline uint32_t GetThreadType(void) { return 0; }
      86             : # endif
      87             : 
      88             : } /* namespace oom */
      89             : } /* namespace js */
      90             : 
      91             : # if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
      92             : 
      93             : #ifdef JS_OOM_BREAKPOINT
      94             : static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
      95             : #define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
      96             : #else
      97             : #define JS_OOM_CALL_BP_FUNC() do {} while(0)
      98             : #endif
      99             : 
     100             : namespace js {
     101             : namespace oom {
     102             : 
     103             : /*
     104             :  * Out of memory testing support.  We provide various testing functions to
     105             :  * simulate OOM conditions and so we can test that they are handled correctly.
     106             :  */
     107             : 
     108             : extern JS_PUBLIC_DATA(uint32_t) targetThread;
     109             : extern JS_PUBLIC_DATA(uint64_t) maxAllocations;
     110             : extern JS_PUBLIC_DATA(uint64_t) counter;
     111             : extern JS_PUBLIC_DATA(bool) failAlways;
     112             : 
     113             : extern void
     114             : SimulateOOMAfter(uint64_t allocations, uint32_t thread, bool always);
     115             : 
     116             : extern void
     117             : ResetSimulatedOOM();
     118             : 
     119             : inline bool
     120     3865459 : IsThreadSimulatingOOM()
     121             : {
     122     3865459 :     return js::oom::targetThread && js::oom::targetThread == js::oom::GetThreadType();
     123             : }
     124             : 
     125             : inline bool
     126           0 : IsSimulatedOOMAllocation()
     127             : {
     128           0 :     return IsThreadSimulatingOOM() &&
     129           0 :            (counter == maxAllocations || (counter > maxAllocations && failAlways));
     130             : }
     131             : 
     132             : inline bool
     133     3045421 : ShouldFailWithOOM()
     134             : {
     135     3045421 :     if (!IsThreadSimulatingOOM())
     136     3045410 :         return false;
     137             : 
     138           0 :     counter++;
     139           0 :     if (IsSimulatedOOMAllocation()) {
     140             :         JS_OOM_CALL_BP_FUNC();
     141           0 :         return true;
     142             :     }
     143           0 :     return false;
     144             : }
     145             : 
     146             : inline bool
     147       59747 : HadSimulatedOOM() {
     148       59747 :     return counter >= maxAllocations;
     149             : }
     150             : 
     151             : } /* namespace oom */
     152             : } /* namespace js */
     153             : 
     154             : #  define JS_OOM_POSSIBLY_FAIL()                                              \
     155             :     do {                                                                      \
     156             :         if (js::oom::ShouldFailWithOOM())                                     \
     157             :             return nullptr;                                                   \
     158             :     } while (0)
     159             : 
     160             : #  define JS_OOM_POSSIBLY_FAIL_BOOL()                                         \
     161             :     do {                                                                      \
     162             :         if (js::oom::ShouldFailWithOOM())                                     \
     163             :             return false;                                                     \
     164             :     } while (0)
     165             : 
     166             : # else
     167             : 
     168             : #  define JS_OOM_POSSIBLY_FAIL() do {} while(0)
     169             : #  define JS_OOM_POSSIBLY_FAIL_BOOL() do {} while(0)
     170             : namespace js {
     171             : namespace oom {
     172             : static inline bool IsSimulatedOOMAllocation() { return false; }
     173             : static inline bool ShouldFailWithOOM() { return false; }
     174             : } /* namespace oom */
     175             : } /* namespace js */
     176             : 
     177             : # endif /* DEBUG || JS_OOM_BREAKPOINT */
     178             : 
     179             : namespace js {
     180             : 
     181             : /* Disable OOM testing in sections which are not OOM safe. */
     182             : struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
     183             : {
     184             :     MOZ_NORETURN MOZ_COLD void crash(const char* reason);
     185             :     MOZ_NORETURN MOZ_COLD void crash(size_t size, const char* reason);
     186             : 
     187             :     using AnnotateOOMAllocationSizeCallback = void(*)(size_t);
     188             :     static AnnotateOOMAllocationSizeCallback annotateOOMSizeCallback;
     189           4 :     static void setAnnotateOOMAllocationSizeCallback(AnnotateOOMAllocationSizeCallback callback) {
     190           4 :         annotateOOMSizeCallback = callback;
     191           4 :     }
     192             : 
     193             : #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     194      809902 :     AutoEnterOOMUnsafeRegion()
     195      809902 :       : oomEnabled_(oom::IsThreadSimulatingOOM() && oom::maxAllocations != UINT64_MAX),
     196      809890 :         oomAfter_(0)
     197             :     {
     198      809890 :         if (oomEnabled_) {
     199           0 :             MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this));
     200           0 :             oomAfter_ = int64_t(oom::maxAllocations) - int64_t(oom::counter);
     201           0 :             oom::maxAllocations = UINT64_MAX;
     202             :         }
     203      809890 :     }
     204             : 
     205     1619754 :     ~AutoEnterOOMUnsafeRegion() {
     206      809877 :         if (oomEnabled_) {
     207           0 :             MOZ_ASSERT(oom::maxAllocations == UINT64_MAX);
     208           0 :             int64_t maxAllocations = int64_t(oom::counter) + oomAfter_;
     209           0 :             MOZ_ASSERT(maxAllocations >= 0,
     210             :                        "alloc count + oom limit exceeds range, your oom limit is probably too large");
     211           0 :             oom::maxAllocations = uint64_t(maxAllocations);
     212           0 :             MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr));
     213             :         }
     214      809877 :     }
     215             : 
     216             :   private:
     217             :     // Used to catch concurrent use from other threads.
     218             :     static mozilla::Atomic<AutoEnterOOMUnsafeRegion*> owner_;
     219             : 
     220             :     bool oomEnabled_;
     221             :     int64_t oomAfter_;
     222             : #endif
     223             : };
     224             : 
     225             : } /* namespace js */
     226             : 
     227      190229 : static inline void* js_malloc(size_t bytes)
     228             : {
     229      190229 :     JS_OOM_POSSIBLY_FAIL();
     230      190230 :     return malloc(bytes);
     231             : }
     232             : 
     233       66266 : static inline void* js_calloc(size_t bytes)
     234             : {
     235       66266 :     JS_OOM_POSSIBLY_FAIL();
     236       66267 :     return calloc(bytes, 1);
     237             : }
     238             : 
     239           5 : static inline void* js_calloc(size_t nmemb, size_t size)
     240             : {
     241           5 :     JS_OOM_POSSIBLY_FAIL();
     242           5 :     return calloc(nmemb, size);
     243             : }
     244             : 
     245       33734 : static inline void* js_realloc(void* p, size_t bytes)
     246             : {
     247             :     // realloc() with zero size is not portable, as some implementations may
     248             :     // return nullptr on success and free |p| for this.  We assume nullptr
     249             :     // indicates failure and that |p| is still valid.
     250       33734 :     MOZ_ASSERT(bytes != 0);
     251             : 
     252       33734 :     JS_OOM_POSSIBLY_FAIL();
     253       33734 :     return realloc(p, bytes);
     254             : }
     255             : 
     256      166476 : static inline void js_free(void* p)
     257             : {
     258      166476 :     free(p);
     259      166476 : }
     260             : 
     261           0 : static inline char* js_strdup(const char* s)
     262             : {
     263           0 :     JS_OOM_POSSIBLY_FAIL();
     264           0 :     return strdup(s);
     265             : }
     266             : #endif/* JS_USE_CUSTOM_ALLOCATOR */
     267             : 
     268             : #include <new>
     269             : 
     270             : /*
     271             :  * Low-level memory management in SpiderMonkey:
     272             :  *
     273             :  *  ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
     274             :  *     to be redefined (via JS_USE_CUSTOM_ALLOCATOR) and Gecko even #define's
     275             :  *     these symbols.
     276             :  *
     277             :  *  ** Do not use the builtin C++ operator new and delete: these throw on
     278             :  *     error and we cannot override them not to.
     279             :  *
     280             :  * Allocation:
     281             :  *
     282             :  * - If the lifetime of the allocation is tied to the lifetime of a GC-thing
     283             :  *   (that is, finalizing the GC-thing will free the allocation), call one of
     284             :  *   the following functions:
     285             :  *
     286             :  *     JSContext::{malloc_,realloc_,calloc_,new_}
     287             :  *     JSRuntime::{malloc_,realloc_,calloc_,new_}
     288             :  *
     289             :  *   These functions accumulate the number of bytes allocated which is used as
     290             :  *   part of the GC-triggering heuristic.
     291             :  *
     292             :  *   The difference between the JSContext and JSRuntime versions is that the
     293             :  *   cx version reports an out-of-memory error on OOM. (This follows from the
     294             :  *   general SpiderMonkey idiom that a JSContext-taking function reports its
     295             :  *   own errors.)
     296             :  *
     297             :  * - Otherwise, use js_malloc/js_realloc/js_calloc/js_new
     298             :  *
     299             :  * Deallocation:
     300             :  *
     301             :  * - Ordinarily, use js_free/js_delete.
     302             :  *
     303             :  * - For deallocations during GC finalization, use one of the following
     304             :  *   operations on the FreeOp provided to the finalizer:
     305             :  *
     306             :  *     FreeOp::{free_,delete_}
     307             :  *
     308             :  *   The advantage of these operations is that the memory is batched and freed
     309             :  *   on another thread.
     310             :  */
     311             : 
     312             : /*
     313             :  * Given a class which should provide a 'new' method, add
     314             :  * JS_DECLARE_NEW_METHODS (see js::MallocProvider for an example).
     315             :  *
     316             :  * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
     317             :  * or the build will break.
     318             :  */
     319             : #define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \
     320             :     template <class T, typename... Args> \
     321             :     QUALIFIERS T * \
     322             :     NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
     323             :         void* memory = ALLOCATOR(sizeof(T)); \
     324             :         return MOZ_LIKELY(memory) \
     325             :             ? new(memory) T(mozilla::Forward<Args>(args)...) \
     326             :             : nullptr; \
     327             :     }
     328             : 
     329             : /*
     330             :  * Given a class which should provide 'make' methods, add
     331             :  * JS_DECLARE_MAKE_METHODS (see js::MallocProvider for an example).  This
     332             :  * method is functionally the same as JS_DECLARE_NEW_METHODS: it just declares
     333             :  * methods that return mozilla::UniquePtr instances that will singly-manage
     334             :  * ownership of the created object.
     335             :  *
     336             :  * Note: Do not add a ; at the end of a use of JS_DECLARE_MAKE_METHODS,
     337             :  * or the build will break.
     338             :  */
     339             : #define JS_DECLARE_MAKE_METHODS(MAKENAME, NEWNAME, QUALIFIERS)\
     340             :     template <class T, typename... Args> \
     341             :     QUALIFIERS mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
     342             :     MAKENAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
     343             :         T* ptr = NEWNAME<T>(mozilla::Forward<Args>(args)...); \
     344             :         return mozilla::UniquePtr<T, JS::DeletePolicy<T>>(ptr); \
     345             :     }
     346             : 
     347        4668 : JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE)
     348             : 
     349             : namespace js {
     350             : 
     351             : /*
     352             :  * Calculate the number of bytes needed to allocate |numElems| contiguous
     353             :  * instances of type |T|.  Return false if the calculation overflowed.
     354             :  */
     355             : template <typename T>
     356             : MOZ_MUST_USE inline bool
     357      315526 : CalculateAllocSize(size_t numElems, size_t* bytesOut)
     358             : {
     359      315526 :     *bytesOut = numElems * sizeof(T);
     360      315526 :     return (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) == 0;
     361             : }
     362             : 
     363             : /*
     364             :  * Calculate the number of bytes needed to allocate a single instance of type
     365             :  * |T| followed by |numExtra| contiguous instances of type |Extra|.  Return
     366             :  * false if the calculation overflowed.
     367             :  */
     368             : template <typename T, typename Extra>
     369             : MOZ_MUST_USE inline bool
     370         723 : CalculateAllocSizeWithExtra(size_t numExtra, size_t* bytesOut)
     371             : {
     372         723 :     *bytesOut = sizeof(T) + numExtra * sizeof(Extra);
     373         182 :     return (numExtra & mozilla::tl::MulOverflowMask<sizeof(Extra)>::value) == 0 &&
     374         814 :            *bytesOut >= sizeof(T);
     375             : }
     376             : 
     377             : } /* namespace js */
     378             : 
     379             : template <class T>
     380             : static MOZ_ALWAYS_INLINE void
     381       12032 : js_delete(const T* p)
     382             : {
     383       12032 :     if (p) {
     384        1141 :         p->~T();
     385        1150 :         js_free(const_cast<T*>(p));
     386             :     }
     387       12032 : }
     388             : 
     389             : template<class T>
     390             : static MOZ_ALWAYS_INLINE void
     391           0 : js_delete_poison(const T* p)
     392             : {
     393           0 :     if (p) {
     394           0 :         p->~T();
     395           0 :         memset(const_cast<T*>(p), 0x3B, sizeof(T));
     396           0 :         js_free(const_cast<T*>(p));
     397             :     }
     398           0 : }
     399             : 
     400             : template <class T>
     401             : static MOZ_ALWAYS_INLINE T*
     402         315 : js_pod_malloc()
     403             : {
     404         315 :     return static_cast<T*>(js_malloc(sizeof(T)));
     405             : }
     406             : 
     407             : template <class T>
     408             : static MOZ_ALWAYS_INLINE T*
     409             : js_pod_calloc()
     410             : {
     411             :     return static_cast<T*>(js_calloc(sizeof(T)));
     412             : }
     413             : 
     414             : template <class T>
     415             : static MOZ_ALWAYS_INLINE T*
     416      180382 : js_pod_malloc(size_t numElems)
     417             : {
     418             :     size_t bytes;
     419      180382 :     if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(numElems, &bytes)))
     420           0 :         return nullptr;
     421      180383 :     return static_cast<T*>(js_malloc(bytes));
     422             : }
     423             : 
     424             : template <class T>
     425             : static MOZ_ALWAYS_INLINE T*
     426       66265 : js_pod_calloc(size_t numElems)
     427             : {
     428             :     size_t bytes;
     429       66265 :     if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(numElems, &bytes)))
     430           0 :         return nullptr;
     431       66265 :     return static_cast<T*>(js_calloc(bytes));
     432             : }
     433             : 
     434             : template <class T>
     435             : static MOZ_ALWAYS_INLINE T*
     436       33729 : js_pod_realloc(T* prior, size_t oldSize, size_t newSize)
     437             : {
     438        9489 :     MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
     439             :     size_t bytes;
     440       33729 :     if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(newSize, &bytes)))
     441           0 :         return nullptr;
     442       33729 :     return static_cast<T*>(js_realloc(prior, bytes));
     443             : }
     444             : 
     445             : namespace js {
     446             : 
     447             : template<typename T>
     448             : struct ScopedFreePtrTraits
     449             : {
     450             :     typedef T* type;
     451       38833 :     static T* empty() { return nullptr; }
     452       37052 :     static void release(T* ptr) { js_free(ptr); }
     453             : };
     454       74097 : SCOPED_TEMPLATE(ScopedJSFreePtr, ScopedFreePtrTraits)
     455             : 
     456             : template <typename T>
     457             : struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
     458             : {
     459        1283 :     static void release(T* ptr) { js_delete(ptr); }
     460             : };
     461        2470 : SCOPED_TEMPLATE(ScopedJSDeletePtr, ScopedDeletePtrTraits)
     462             : 
     463             : template <typename T>
     464             : struct ScopedReleasePtrTraits : public ScopedFreePtrTraits<T>
     465             : {
     466             :     static void release(T* ptr) { if (ptr) ptr->release(); }
     467             : };
     468             : SCOPED_TEMPLATE(ScopedReleasePtr, ScopedReleasePtrTraits)
     469             : 
     470             : } /* namespace js */
     471             : 
     472             : namespace JS {
     473             : 
     474             : template<typename T>
     475             : struct DeletePolicy
     476             : {
     477       29534 :     constexpr DeletePolicy() {}
     478             : 
     479             :     template<typename U>
     480           0 :     MOZ_IMPLICIT DeletePolicy(DeletePolicy<U> other,
     481             :                               typename mozilla::EnableIf<mozilla::IsConvertible<U*, T*>::value,
     482             :                                                          int>::Type dummy = 0)
     483           0 :     {}
     484             : 
     485           0 :     void operator()(const T* ptr) {
     486           0 :         js_delete(const_cast<T*>(ptr));
     487           0 :     }
     488             : };
     489             : 
     490             : struct FreePolicy
     491             : {
     492        5631 :     void operator()(const void* ptr) {
     493        5631 :         js_free(const_cast<void*>(ptr));
     494        5631 :     }
     495             : };
     496             : 
     497             : typedef mozilla::UniquePtr<char[], JS::FreePolicy> UniqueChars;
     498             : typedef mozilla::UniquePtr<char16_t[], JS::FreePolicy> UniqueTwoByteChars;
     499             : 
     500             : } // namespace JS
     501             : 
     502             : namespace js {
     503             : 
     504             : /* Integral types for all hash functions. */
     505             : typedef uint32_t HashNumber;
     506             : const unsigned HashNumberSizeBits = 32;
     507             : 
     508             : namespace detail {
     509             : 
     510             : /*
     511             :  * Given a raw hash code, h, return a number that can be used to select a hash
     512             :  * bucket.
     513             :  *
     514             :  * This function aims to produce as uniform an output distribution as possible,
     515             :  * especially in the most significant (leftmost) bits, even though the input
     516             :  * distribution may be highly nonrandom, given the constraints that this must
     517             :  * be deterministic and quick to compute.
     518             :  *
     519             :  * Since the leftmost bits of the result are best, the hash bucket index is
     520             :  * computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
     521             :  * right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
     522             :  *
     523             :  * FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
     524             :  */
     525             : inline HashNumber
     526     3811548 : ScrambleHashCode(HashNumber h)
     527             : {
     528             :     /*
     529             :      * Simply returning h would not cause any hash tables to produce wrong
     530             :      * answers. But it can produce pathologically bad performance: The caller
     531             :      * right-shifts the result, keeping only the highest bits. The high bits of
     532             :      * hash codes are very often completely entropy-free. (So are the lowest
     533             :      * bits.)
     534             :      *
     535             :      * So we use Fibonacci hashing, as described in Knuth, The Art of Computer
     536             :      * Programming, 6.4. This mixes all the bits of the input hash code h.
     537             :      *
     538             :      * The value of goldenRatio is taken from the hex
     539             :      * expansion of the golden ratio, which starts 1.9E3779B9....
     540             :      * This value is especially good if values with consecutive hash codes
     541             :      * are stored in a hash table; see Knuth for details.
     542             :      */
     543             :     static const HashNumber goldenRatio = 0x9E3779B9U;
     544     3811548 :     return h * goldenRatio;
     545             : }
     546             : 
     547             : } /* namespace detail */
     548             : 
     549             : } /* namespace js */
     550             : 
     551             : /* sixgill annotation defines */
     552             : #ifndef HAVE_STATIC_ANNOTATIONS
     553             : # define HAVE_STATIC_ANNOTATIONS
     554             : # ifdef XGILL_PLUGIN
     555             : #  define STATIC_PRECONDITION(COND)         __attribute__((precondition(#COND)))
     556             : #  define STATIC_PRECONDITION_ASSUME(COND)  __attribute__((precondition_assume(#COND)))
     557             : #  define STATIC_POSTCONDITION(COND)        __attribute__((postcondition(#COND)))
     558             : #  define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
     559             : #  define STATIC_INVARIANT(COND)            __attribute__((invariant(#COND)))
     560             : #  define STATIC_INVARIANT_ASSUME(COND)     __attribute__((invariant_assume(#COND)))
     561             : #  define STATIC_ASSUME(COND)                        \
     562             :   JS_BEGIN_MACRO                                     \
     563             :     __attribute__((assume_static(#COND), unused))    \
     564             :     int STATIC_PASTE1(assume_static_, __COUNTER__);  \
     565             :   JS_END_MACRO
     566             : # else /* XGILL_PLUGIN */
     567             : #  define STATIC_PRECONDITION(COND)          /* nothing */
     568             : #  define STATIC_PRECONDITION_ASSUME(COND)   /* nothing */
     569             : #  define STATIC_POSTCONDITION(COND)         /* nothing */
     570             : #  define STATIC_POSTCONDITION_ASSUME(COND)  /* nothing */
     571             : #  define STATIC_INVARIANT(COND)             /* nothing */
     572             : #  define STATIC_INVARIANT_ASSUME(COND)      /* nothing */
     573             : #  define STATIC_ASSUME(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
     574             : # endif /* XGILL_PLUGIN */
     575             : # define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
     576             : #endif /* HAVE_STATIC_ANNOTATIONS */
     577             : 
     578             : #endif /* js_Utility_h */

Generated by: LCOV version 1.13