Eliminate plain req::malloc, use malloc_unk explicitly or something better
[hiphop-php.git] / hphp / runtime / base / req-malloc.h
blobce21c5dd0ef0c1b4da7f8cbe4793a78eaa99dc6b
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_RUNTIME_BASE_REQ_MALLOC_H_
18 #define incl_HPHP_RUNTIME_BASE_REQ_MALLOC_H_
20 #include "hphp/util/type-scan.h"
23 * req::malloc api for request-scoped memory
25 * This is the most generic entry point to the request local
26 * allocator. If you easily know the size of the allocation at free
27 * time, it might be more efficient to use MM() apis directly.
29 * These functions behave like C's malloc/free, but get memory from
30 * the current thread's MemoryManager instance. At request-end, any
31 * un-freed memory is explicitly freed (and in debug, garbage filled).
32 * If any pointers to this memory survive beyond a request, they'll be
33 * dangling pointers.
35 * These functions only guarantee 8-byte alignment for the returned
36 * pointer.
39 namespace HPHP { namespace req {
41 ////////////////////////////////////////////////////////////////////////////////
44 * Plain malloc-style allocation in the request heap is not available;
45 * please choose one of the variants below. Memory obtained through any
46 * of these will be freed at end-of-request, unless passed back to req::free().
48 * 1. malloc_noptrs, if you know the memory will not contain heap pointers,
49 * e.g. c-strings, pixels, compressed or encrypted data, etc.
51 * 2. make_raw<T>(...) or make_raw_array<T>(count), if you know the type,
52 * whether or not it contains pointers. These are analogs of C++ new.
54 * 3. malloc(type_scan::Index) like make_raw<T>, but you provide the type id,
55 * which must not be type_scan::kIndexUnknown; intended for implementing
56 * templated apis.
58 * 4. malloc_unk() memory will be treated as root and conservative scanned,
59 * because we don't know whether or not it will have pointers.
61 void* malloc(size_t nbytes) = delete;
62 void* calloc(size_t count, size_t bytes) = delete;
63 void* realloc(void* ptr, size_t nbytes) = delete;
66 * Interfaces to receive raw memory. Whenever possible, prefer the typed
67 * interfaces below, such as make_raw<T>.
69 void* malloc(size_t nbytes, type_scan::Index);
70 void* calloc(size_t count, size_t bytes, type_scan::Index);
71 void* realloc(void* ptr, size_t nbytes, type_scan::Index);
73 // Unknown type-index, conservative scan contents and treat as root.
74 void* malloc_untyped(size_t nbytes);
75 void* calloc_untyped(size_t count, size_t bytes);
76 void* realloc_untyped(void* ptr, size_t nbytes);
78 // Unknown type-index, but assert there's no pointers within.
79 inline void* malloc_noptrs(size_t nbytes) {
80 return malloc(nbytes, type_scan::kIndexUnknownNoPtrs);
82 inline void* calloc_noptrs(size_t count, size_t bytes) {
83 return calloc(count, bytes, type_scan::kIndexUnknownNoPtrs);
85 inline void* realloc_noptrs(void* ptr, size_t nbytes) {
86 return realloc(ptr, nbytes, type_scan::kIndexUnknownNoPtrs);
89 char* strndup(const char* str, size_t len);
91 void free(void* ptr);
94 * request-heap (de)allocators for non-POD C++-style stuff. Runs constructors
95 * and destructors.
97 * Unlike the normal operator delete, req::destroy_raw() requires ~T() must
98 * be nothrow and that p is not null.
100 template<class T, class... Args> T* make_raw(Args&&...);
101 template<class T> void destroy_raw(T* p);
104 * Allocate an array of objects. Similar to req::malloc, but with
105 * support for constructors.
107 * Note that explicitly calling req::destroy_raw will run the destructors,
108 * but if you let the allocator sweep it the destructors will not be
109 * called.
111 * Unlike the normal operator delete, req::destroy_raw_array requires
112 * ~T() must be nothrow.
114 template<class T> T* make_raw_array(size_t count);
115 template<class T> void destroy_raw_array(T* t, size_t count);
118 * Allocate an array of objects, memset to 0. Does *not* run any constructors.
120 template<class T> T* calloc_raw_array(size_t count);
122 //////////////////////////////////////////////////////////////////////
124 // STL-style allocator for the request-heap allocator. (Unfortunately we
125 // can't use allocator_traits yet.)
127 // You can also use req::Allocator as a model of folly's
128 // SimpleAllocator where appropriate.
131 template <class T, typename Action = type_scan::Action::Auto>
132 struct Allocator {
133 typedef T value_type;
134 typedef T* pointer;
135 typedef const T* const_pointer;
136 typedef T& reference;
137 typedef const T& const_reference;
138 typedef std::size_t size_type;
139 typedef std::ptrdiff_t difference_type;
141 template <class U>
142 struct rebind {
143 typedef Allocator<U, Action> other;
146 pointer address(reference value) {
147 return &value;
149 const_pointer address(const_reference value) const {
150 return &value;
153 Allocator() noexcept {}
154 Allocator(const Allocator&) noexcept {}
155 template<class U, typename A> Allocator(const Allocator<U,A>&) noexcept {}
156 ~Allocator() noexcept {}
158 Allocator& operator=(const Allocator&) noexcept { return *this; }
160 size_type max_size() const {
161 return std::numeric_limits<std::size_t>::max() / sizeof(T);
164 pointer allocate(size_type num, const void* = 0) {
165 pointer ret = (pointer)req::malloc(
166 num * sizeof(T),
167 type_scan::getIndexForMalloc<T, Action>()
169 return ret;
172 template<class U, class... Args>
173 void construct(U* p, Args&&... args) {
174 ::new ((void*)p) U(std::forward<Args>(args)...);
177 void destroy(pointer p) {
178 p->~T();
181 void deallocate(pointer p, size_type num) {
182 req::free((void*)p);
185 template<class U, typename A> bool operator==(const Allocator<U,A>&) const {
186 return true;
189 template<class U, typename A> bool operator!=(const Allocator<U,A>&) const {
190 return false;
194 // Variant of Allocator which indicates to the GC type-scanning machinery T
195 // should be conservative scanned. Meant to be used for container internal
196 // allocations where we don't want to attempt to exactly scan the internal
197 // contents. Such containers often using type-punning and other tricks, which
198 // means an exact scan will fail to find valid pointers (where as conservative
199 // scan will). Where-ever possible, we'll use the container's public interface
200 // to scan the values it holds in an exact manner.
201 template<typename T>
202 using ConservativeAllocator = Allocator<T, type_scan::Action::Conservative<T>>;
204 /////////////////////////////////////////////////////////////////////
206 template<class T, class... Args> T* make_raw(Args&&... args) {
207 auto const mem = req::malloc(sizeof(T), type_scan::getIndexForMalloc<T>());
208 try {
209 return new (mem) T(std::forward<Args>(args)...);
210 } catch (...) {
211 req::free(mem);
212 throw;
216 template<class T> void destroy_raw(T* t) {
217 t->~T();
218 req::free(t);
221 template<class T> T* make_raw_array(size_t count) {
222 T* ret = static_cast<T*>(
223 req::malloc(count * sizeof(T), type_scan::getIndexForMalloc<T>())
225 size_t i = 0;
226 try {
227 for (; i < count; ++i) {
228 new (&ret[i]) T();
230 } catch (...) {
231 size_t j = i;
232 while (j-- > 0) {
233 ret[j].~T();
235 req::free(ret);
236 throw;
238 return ret;
241 template<class T>
242 void destroy_raw_array(T* t, size_t count) {
243 size_t i = count;
244 while (i-- > 0) {
245 t[i].~T();
247 req::free(t);
250 template<class T> T* calloc_raw_array(size_t count) {
251 return static_cast<T*>(
252 req::calloc(count, sizeof(T), type_scan::getIndexForMalloc<T>())
256 ////////////////////////////////////////////////////////////////////////////////
260 #endif