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 /* 8 * JS allocation policies. 9 * 10 * The allocators here are for system memory with lifetimes which are not 11 * managed by the GC. See the comment at the top of vm/MallocProvider.h. 12 */ 13 14 #ifndef jsalloc_h 15 #define jsalloc_h 16 17 #include "js/TypeDecls.h" 18 #include "js/Utility.h" 19 20 namespace js { 21 22 enum class AllocFunction { 23 Malloc, 24 Calloc, 25 Realloc 26 }; 27 28 struct ContextFriendFields; 29 30 /* Policy for using system memory functions and doing no error reporting. */ 31 class SystemAllocPolicy 32 { 33 public: maybe_pod_malloc(size_t numElems)34 template <typename T> T* maybe_pod_malloc(size_t numElems) { return js_pod_malloc<T>(numElems); } maybe_pod_calloc(size_t numElems)35 template <typename T> T* maybe_pod_calloc(size_t numElems) { return js_pod_calloc<T>(numElems); } maybe_pod_realloc(T * p,size_t oldSize,size_t newSize)36 template <typename T> T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) { 37 return js_pod_realloc<T>(p, oldSize, newSize); 38 } pod_malloc(size_t numElems)39 template <typename T> T* pod_malloc(size_t numElems) { return maybe_pod_malloc<T>(numElems); } pod_calloc(size_t numElems)40 template <typename T> T* pod_calloc(size_t numElems) { return maybe_pod_calloc<T>(numElems); } pod_realloc(T * p,size_t oldSize,size_t newSize)41 template <typename T> T* pod_realloc(T* p, size_t oldSize, size_t newSize) { 42 return maybe_pod_realloc<T>(p, oldSize, newSize); 43 } free_(void * p)44 void free_(void* p) { js_free(p); } reportAllocOverflow()45 void reportAllocOverflow() const {} checkSimulatedOOM()46 bool checkSimulatedOOM() const { 47 return !js::oom::ShouldFailWithOOM(); 48 } 49 }; 50 51 class ExclusiveContext; 52 void ReportOutOfMemory(ExclusiveContext* cxArg); 53 54 /* 55 * Allocation policy that calls the system memory functions and reports errors 56 * to the context. Since the JSContext given on construction is stored for 57 * the lifetime of the container, this policy may only be used for containers 58 * whose lifetime is a shorter than the given JSContext. 59 * 60 * FIXME bug 647103 - rewrite this in terms of temporary allocation functions, 61 * not the system ones. 62 */ 63 class TempAllocPolicy 64 { 65 ContextFriendFields* const cx_; 66 67 /* 68 * Non-inline helper to call JSRuntime::onOutOfMemory with minimal 69 * code bloat. 70 */ 71 JS_FRIEND_API(void*) onOutOfMemory(AllocFunction allocFunc, size_t nbytes, 72 void* reallocPtr = nullptr); 73 74 template <typename T> 75 T* onOutOfMemoryTyped(AllocFunction allocFunc, size_t numElems, void* reallocPtr = nullptr) { 76 size_t bytes; 77 if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes))) 78 return nullptr; 79 return static_cast<T*>(onOutOfMemory(allocFunc, bytes, reallocPtr)); 80 } 81 82 public: TempAllocPolicy(JSContext * cx)83 MOZ_IMPLICIT TempAllocPolicy(JSContext* cx) : cx_((ContextFriendFields*) cx) {} // :( TempAllocPolicy(ContextFriendFields * cx)84 MOZ_IMPLICIT TempAllocPolicy(ContextFriendFields* cx) : cx_(cx) {} 85 86 template <typename T> maybe_pod_malloc(size_t numElems)87 T* maybe_pod_malloc(size_t numElems) { 88 return js_pod_malloc<T>(numElems); 89 } 90 91 template <typename T> maybe_pod_calloc(size_t numElems)92 T* maybe_pod_calloc(size_t numElems) { 93 return js_pod_calloc<T>(numElems); 94 } 95 96 template <typename T> maybe_pod_realloc(T * prior,size_t oldSize,size_t newSize)97 T* maybe_pod_realloc(T* prior, size_t oldSize, size_t newSize) { 98 return js_pod_realloc<T>(prior, oldSize, newSize); 99 } 100 101 template <typename T> pod_malloc(size_t numElems)102 T* pod_malloc(size_t numElems) { 103 T* p = maybe_pod_malloc<T>(numElems); 104 if (MOZ_UNLIKELY(!p)) 105 p = onOutOfMemoryTyped<T>(AllocFunction::Malloc, numElems); 106 return p; 107 } 108 109 template <typename T> pod_calloc(size_t numElems)110 T* pod_calloc(size_t numElems) { 111 T* p = maybe_pod_calloc<T>(numElems); 112 if (MOZ_UNLIKELY(!p)) 113 p = onOutOfMemoryTyped<T>(AllocFunction::Calloc, numElems); 114 return p; 115 } 116 117 template <typename T> pod_realloc(T * prior,size_t oldSize,size_t newSize)118 T* pod_realloc(T* prior, size_t oldSize, size_t newSize) { 119 T* p2 = maybe_pod_realloc<T>(prior, oldSize, newSize); 120 if (MOZ_UNLIKELY(!p2)) 121 p2 = onOutOfMemoryTyped<T>(AllocFunction::Realloc, newSize, prior); 122 return p2; 123 } 124 free_(void * p)125 void free_(void* p) { 126 js_free(p); 127 } 128 129 JS_FRIEND_API(void) reportAllocOverflow() const; 130 checkSimulatedOOM()131 bool checkSimulatedOOM() const { 132 if (js::oom::ShouldFailWithOOM()) { 133 js::ReportOutOfMemory(reinterpret_cast<ExclusiveContext*>(cx_)); 134 return false; 135 } 136 137 return true; 138 } 139 }; 140 141 } /* namespace js */ 142 143 #endif /* jsalloc_h */ 144