1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/IonAllocPolicy.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,222 @@ 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 jit_IonAllocPolicy_h 1.11 +#define jit_IonAllocPolicy_h 1.12 + 1.13 +#include "mozilla/GuardObjects.h" 1.14 +#include "mozilla/TypeTraits.h" 1.15 + 1.16 +#include "jscntxt.h" 1.17 + 1.18 +#include "ds/LifoAlloc.h" 1.19 +#include "jit/InlineList.h" 1.20 +#include "jit/Ion.h" 1.21 + 1.22 +namespace js { 1.23 +namespace jit { 1.24 + 1.25 +class TempAllocator 1.26 +{ 1.27 + LifoAllocScope lifoScope_; 1.28 + 1.29 + // Linked list of GCThings rooted by this allocator. 1.30 + CompilerRootNode *rootList_; 1.31 + 1.32 + public: 1.33 + TempAllocator(LifoAlloc *lifoAlloc) 1.34 + : lifoScope_(lifoAlloc), 1.35 + rootList_(nullptr) 1.36 + { } 1.37 + 1.38 + void *allocateOrCrash(size_t bytes) 1.39 + { 1.40 + void *p = lifoScope_.alloc().alloc(bytes); 1.41 + if (!p) 1.42 + js::CrashAtUnhandlableOOM("LifoAlloc::allocOrCrash"); 1.43 + return p; 1.44 + } 1.45 + 1.46 + void *allocate(size_t bytes) 1.47 + { 1.48 + void *p = lifoScope_.alloc().alloc(bytes); 1.49 + if (!ensureBallast()) 1.50 + return nullptr; 1.51 + return p; 1.52 + } 1.53 + 1.54 + template <size_t ElemSize> 1.55 + void *allocateArray(size_t n) 1.56 + { 1.57 + if (n & mozilla::tl::MulOverflowMask<ElemSize>::value) 1.58 + return nullptr; 1.59 + void *p = lifoScope_.alloc().alloc(n * ElemSize); 1.60 + if (!ensureBallast()) 1.61 + return nullptr; 1.62 + return p; 1.63 + } 1.64 + 1.65 + LifoAlloc *lifoAlloc() 1.66 + { 1.67 + return &lifoScope_.alloc(); 1.68 + } 1.69 + 1.70 + CompilerRootNode *&rootList() 1.71 + { 1.72 + return rootList_; 1.73 + } 1.74 + 1.75 + bool ensureBallast() { 1.76 + // Most infallible Ion allocations are small, so we use a ballast of 1.77 + // ~16K for now. 1.78 + return lifoScope_.alloc().ensureUnusedApproximate(16 * 1024); 1.79 + } 1.80 +}; 1.81 + 1.82 +// Stack allocated rooter for all roots associated with a TempAllocator 1.83 +class AutoTempAllocatorRooter : private AutoGCRooter 1.84 +{ 1.85 + public: 1.86 + explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp 1.87 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.88 + : AutoGCRooter(cx, IONALLOC), temp(temp) 1.89 + { 1.90 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.91 + } 1.92 + 1.93 + friend void AutoGCRooter::trace(JSTracer *trc); 1.94 + void trace(JSTracer *trc); 1.95 + 1.96 + private: 1.97 + TempAllocator *temp; 1.98 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.99 +}; 1.100 + 1.101 +class IonAllocPolicy 1.102 +{ 1.103 + TempAllocator &alloc_; 1.104 + 1.105 + public: 1.106 + IonAllocPolicy(TempAllocator &alloc) 1.107 + : alloc_(alloc) 1.108 + {} 1.109 + void *malloc_(size_t bytes) { 1.110 + return alloc_.allocate(bytes); 1.111 + } 1.112 + void *calloc_(size_t bytes) { 1.113 + void *p = alloc_.allocate(bytes); 1.114 + if (p) 1.115 + memset(p, 0, bytes); 1.116 + return p; 1.117 + } 1.118 + void *realloc_(void *p, size_t oldBytes, size_t bytes) { 1.119 + void *n = malloc_(bytes); 1.120 + if (!n) 1.121 + return n; 1.122 + memcpy(n, p, Min(oldBytes, bytes)); 1.123 + return n; 1.124 + } 1.125 + void free_(void *p) { 1.126 + } 1.127 + void reportAllocOverflow() const { 1.128 + } 1.129 +}; 1.130 + 1.131 +// Deprecated. Don't use this. Will be removed after everything has been 1.132 +// converted to IonAllocPolicy. 1.133 +class OldIonAllocPolicy 1.134 +{ 1.135 + public: 1.136 + OldIonAllocPolicy() 1.137 + {} 1.138 + void *malloc_(size_t bytes) { 1.139 + return GetIonContext()->temp->allocate(bytes); 1.140 + } 1.141 + void *calloc_(size_t bytes) { 1.142 + void *p = GetIonContext()->temp->allocate(bytes); 1.143 + if (p) 1.144 + memset(p, 0, bytes); 1.145 + return p; 1.146 + } 1.147 + void *realloc_(void *p, size_t oldBytes, size_t bytes) { 1.148 + void *n = malloc_(bytes); 1.149 + if (!n) 1.150 + return n; 1.151 + memcpy(n, p, Min(oldBytes, bytes)); 1.152 + return n; 1.153 + } 1.154 + void free_(void *p) { 1.155 + } 1.156 + void reportAllocOverflow() const { 1.157 + } 1.158 +}; 1.159 + 1.160 +class AutoIonContextAlloc 1.161 +{ 1.162 + TempAllocator tempAlloc_; 1.163 + IonContext *icx_; 1.164 + TempAllocator *prevAlloc_; 1.165 + 1.166 + public: 1.167 + explicit AutoIonContextAlloc(JSContext *cx) 1.168 + : tempAlloc_(&cx->tempLifoAlloc()), 1.169 + icx_(GetIonContext()), 1.170 + prevAlloc_(icx_->temp) 1.171 + { 1.172 + icx_->temp = &tempAlloc_; 1.173 + } 1.174 + 1.175 + ~AutoIonContextAlloc() { 1.176 + JS_ASSERT(icx_->temp == &tempAlloc_); 1.177 + icx_->temp = prevAlloc_; 1.178 + } 1.179 +}; 1.180 + 1.181 +struct TempObject 1.182 +{ 1.183 + inline void *operator new(size_t nbytes, TempAllocator &alloc) { 1.184 + return alloc.allocateOrCrash(nbytes); 1.185 + } 1.186 + template <class T> 1.187 + inline void *operator new(size_t nbytes, T *pos) { 1.188 + static_assert(mozilla::IsConvertible<T*, TempObject*>::value, 1.189 + "Placement new argument type must inherit from TempObject"); 1.190 + return pos; 1.191 + } 1.192 +}; 1.193 + 1.194 +template <typename T> 1.195 +class TempObjectPool 1.196 +{ 1.197 + TempAllocator *alloc_; 1.198 + InlineForwardList<T> freed_; 1.199 + 1.200 + public: 1.201 + TempObjectPool() 1.202 + : alloc_(nullptr) 1.203 + {} 1.204 + void setAllocator(TempAllocator &alloc) { 1.205 + JS_ASSERT(freed_.empty()); 1.206 + alloc_ = &alloc; 1.207 + } 1.208 + T *allocate() { 1.209 + JS_ASSERT(alloc_); 1.210 + if (freed_.empty()) 1.211 + return new(*alloc_) T(); 1.212 + return freed_.popFront(); 1.213 + } 1.214 + void free(T *obj) { 1.215 + freed_.pushFront(obj); 1.216 + } 1.217 + void clear() { 1.218 + freed_.clear(); 1.219 + } 1.220 +}; 1.221 + 1.222 +} // namespace jit 1.223 +} // namespace js 1.224 + 1.225 +#endif /* jit_IonAllocPolicy_h */