js/src/jit/IonAllocPolicy.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:b5e308d94d88
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 jit_IonAllocPolicy_h
8 #define jit_IonAllocPolicy_h
9
10 #include "mozilla/GuardObjects.h"
11 #include "mozilla/TypeTraits.h"
12
13 #include "jscntxt.h"
14
15 #include "ds/LifoAlloc.h"
16 #include "jit/InlineList.h"
17 #include "jit/Ion.h"
18
19 namespace js {
20 namespace jit {
21
22 class TempAllocator
23 {
24 LifoAllocScope lifoScope_;
25
26 // Linked list of GCThings rooted by this allocator.
27 CompilerRootNode *rootList_;
28
29 public:
30 TempAllocator(LifoAlloc *lifoAlloc)
31 : lifoScope_(lifoAlloc),
32 rootList_(nullptr)
33 { }
34
35 void *allocateOrCrash(size_t bytes)
36 {
37 void *p = lifoScope_.alloc().alloc(bytes);
38 if (!p)
39 js::CrashAtUnhandlableOOM("LifoAlloc::allocOrCrash");
40 return p;
41 }
42
43 void *allocate(size_t bytes)
44 {
45 void *p = lifoScope_.alloc().alloc(bytes);
46 if (!ensureBallast())
47 return nullptr;
48 return p;
49 }
50
51 template <size_t ElemSize>
52 void *allocateArray(size_t n)
53 {
54 if (n & mozilla::tl::MulOverflowMask<ElemSize>::value)
55 return nullptr;
56 void *p = lifoScope_.alloc().alloc(n * ElemSize);
57 if (!ensureBallast())
58 return nullptr;
59 return p;
60 }
61
62 LifoAlloc *lifoAlloc()
63 {
64 return &lifoScope_.alloc();
65 }
66
67 CompilerRootNode *&rootList()
68 {
69 return rootList_;
70 }
71
72 bool ensureBallast() {
73 // Most infallible Ion allocations are small, so we use a ballast of
74 // ~16K for now.
75 return lifoScope_.alloc().ensureUnusedApproximate(16 * 1024);
76 }
77 };
78
79 // Stack allocated rooter for all roots associated with a TempAllocator
80 class AutoTempAllocatorRooter : private AutoGCRooter
81 {
82 public:
83 explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp
84 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
85 : AutoGCRooter(cx, IONALLOC), temp(temp)
86 {
87 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
88 }
89
90 friend void AutoGCRooter::trace(JSTracer *trc);
91 void trace(JSTracer *trc);
92
93 private:
94 TempAllocator *temp;
95 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
96 };
97
98 class IonAllocPolicy
99 {
100 TempAllocator &alloc_;
101
102 public:
103 IonAllocPolicy(TempAllocator &alloc)
104 : alloc_(alloc)
105 {}
106 void *malloc_(size_t bytes) {
107 return alloc_.allocate(bytes);
108 }
109 void *calloc_(size_t bytes) {
110 void *p = alloc_.allocate(bytes);
111 if (p)
112 memset(p, 0, bytes);
113 return p;
114 }
115 void *realloc_(void *p, size_t oldBytes, size_t bytes) {
116 void *n = malloc_(bytes);
117 if (!n)
118 return n;
119 memcpy(n, p, Min(oldBytes, bytes));
120 return n;
121 }
122 void free_(void *p) {
123 }
124 void reportAllocOverflow() const {
125 }
126 };
127
128 // Deprecated. Don't use this. Will be removed after everything has been
129 // converted to IonAllocPolicy.
130 class OldIonAllocPolicy
131 {
132 public:
133 OldIonAllocPolicy()
134 {}
135 void *malloc_(size_t bytes) {
136 return GetIonContext()->temp->allocate(bytes);
137 }
138 void *calloc_(size_t bytes) {
139 void *p = GetIonContext()->temp->allocate(bytes);
140 if (p)
141 memset(p, 0, bytes);
142 return p;
143 }
144 void *realloc_(void *p, size_t oldBytes, size_t bytes) {
145 void *n = malloc_(bytes);
146 if (!n)
147 return n;
148 memcpy(n, p, Min(oldBytes, bytes));
149 return n;
150 }
151 void free_(void *p) {
152 }
153 void reportAllocOverflow() const {
154 }
155 };
156
157 class AutoIonContextAlloc
158 {
159 TempAllocator tempAlloc_;
160 IonContext *icx_;
161 TempAllocator *prevAlloc_;
162
163 public:
164 explicit AutoIonContextAlloc(JSContext *cx)
165 : tempAlloc_(&cx->tempLifoAlloc()),
166 icx_(GetIonContext()),
167 prevAlloc_(icx_->temp)
168 {
169 icx_->temp = &tempAlloc_;
170 }
171
172 ~AutoIonContextAlloc() {
173 JS_ASSERT(icx_->temp == &tempAlloc_);
174 icx_->temp = prevAlloc_;
175 }
176 };
177
178 struct TempObject
179 {
180 inline void *operator new(size_t nbytes, TempAllocator &alloc) {
181 return alloc.allocateOrCrash(nbytes);
182 }
183 template <class T>
184 inline void *operator new(size_t nbytes, T *pos) {
185 static_assert(mozilla::IsConvertible<T*, TempObject*>::value,
186 "Placement new argument type must inherit from TempObject");
187 return pos;
188 }
189 };
190
191 template <typename T>
192 class TempObjectPool
193 {
194 TempAllocator *alloc_;
195 InlineForwardList<T> freed_;
196
197 public:
198 TempObjectPool()
199 : alloc_(nullptr)
200 {}
201 void setAllocator(TempAllocator &alloc) {
202 JS_ASSERT(freed_.empty());
203 alloc_ = &alloc;
204 }
205 T *allocate() {
206 JS_ASSERT(alloc_);
207 if (freed_.empty())
208 return new(*alloc_) T();
209 return freed_.popFront();
210 }
211 void free(T *obj) {
212 freed_.pushFront(obj);
213 }
214 void clear() {
215 freed_.clear();
216 }
217 };
218
219 } // namespace jit
220 } // namespace js
221
222 #endif /* jit_IonAllocPolicy_h */

mercurial