Fix crash when trying to change staticness of a property
[hiphop-php.git] / hphp / util / alloc.h
blobdfcd334afe876db48de492b6a3af9eb90c0a8c43
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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_UTIL_ALLOC_H_
18 #define incl_HPHP_UTIL_ALLOC_H_
20 #include <stdint.h>
21 #include <cassert>
22 #include <atomic>
24 #include "folly/Portability.h"
26 #include "hphp/util/exception.h"
28 #ifdef FOLLY_SANITIZE_ADDRESS
29 // ASan is less precise than valgrind so we'll need a superset of those tweaks
30 # define VALGRIND
31 // TODO: (t2869817) ASan doesn't play well with jemalloc
32 # ifdef USE_JEMALLOC
33 # undef USE_JEMALLOC
34 # endif
35 #endif
37 #ifdef USE_TCMALLOC
38 #include <google/malloc_extension.h>
39 #endif
41 #ifndef USE_JEMALLOC
42 # ifdef __FreeBSD__
43 # include "stdlib.h"
44 # include "malloc_np.h"
45 # else
46 # include "malloc.h"
47 # endif
48 #else
49 # undef ALLOCM_ZERO
50 # undef ALLOCM_NO_MOVE
51 # include <jemalloc/jemalloc.h>
52 # ifndef ALLOCM_ARENA
53 # define ALLOCM_ARENA(a) 0
54 # endif
55 # if JEMALLOC_VERSION_MAJOR > 3 || \
56 (JEMALLOC_VERSION_MAJOR == 3 && JEMALLOC_VERSION_MINOR >= 5)
57 # define USE_JEMALLOC_MALLOCX
58 # endif
59 #endif
61 #include "hphp/util/maphuge.h"
63 extern "C" {
64 #ifdef USE_TCMALLOC
65 #define MallocExtensionInstance _ZN15MallocExtension8instanceEv
66 MallocExtension* MallocExtensionInstance() __attribute__((weak));
67 #endif
69 #ifdef USE_JEMALLOC
71 int mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
72 size_t newlen) __attribute__((weak));
73 int mallctlnametomib(const char *name, size_t* mibp, size_t*miblenp)
74 __attribute__((weak));
75 int mallctlbymib(const size_t* mibp, size_t miblen, void *oldp,
76 size_t *oldlenp, void *newp, size_t newlen) __attribute__((weak));
77 void malloc_stats_print(void (*write_cb)(void *, const char *),
78 void *cbopaque, const char *opts)
79 __attribute__((weak));
80 #endif
83 namespace HPHP {
84 ///////////////////////////////////////////////////////////////////////////////
86 const bool use_jemalloc =
87 #ifdef USE_JEMALLOC
88 true
89 #else
90 false
91 #endif
94 class OutOfMemoryException : public Exception {
95 public:
96 explicit OutOfMemoryException(size_t size)
97 : Exception("Unable to allocate %zu bytes of memory", size) {}
98 virtual ~OutOfMemoryException() throw() {}
99 EXCEPTION_COMMON_IMPL(OutOfMemoryException);
102 ///////////////////////////////////////////////////////////////////////////////
104 #ifdef USE_JEMALLOC
105 extern unsigned low_arena;
106 extern std::atomic<int> low_huge_pages;
107 #endif
109 inline void* low_malloc(size_t size) {
110 #ifndef USE_JEMALLOC
111 return malloc(size);
112 #else
113 extern void* low_malloc_impl(size_t size);
114 return low_malloc_impl(size);
115 #endif
118 inline void low_free(void* ptr) {
119 #ifndef USE_JEMALLOC
120 free(ptr);
121 #elif defined(USE_JEMALLOC_MALLOCX)
122 dallocx(ptr, MALLOCX_ARENA(low_arena));
123 #else
124 dallocm(ptr, ALLOCM_ARENA(low_arena));
125 #endif
128 inline void low_malloc_huge_pages(int pages) {
129 #ifdef USE_JEMALLOC
130 low_huge_pages = pages;
131 #endif
134 void low_malloc_skip_huge(void* start, void* end);
137 * Safe memory allocation.
139 inline void* safe_malloc(size_t size) {
140 void* p = malloc(size);
141 if (!p) throw OutOfMemoryException(size);
142 return p;
145 inline void* safe_calloc(size_t count, size_t size) {
146 void* p = calloc(count, size);
147 if (!p) throw OutOfMemoryException(size);
148 return p;
151 inline void* safe_realloc(void* ptr, size_t size) {
152 ptr = realloc(ptr, size);
153 if (!ptr && size > 0) throw OutOfMemoryException(size);
154 return ptr;
157 inline void safe_free(void* ptr) {
158 return free(ptr);
162 * Instruct low level memory allocator to free memory back to system. Called
163 * when thread's been idle and predicted to continue to be idle for a while.
165 void flush_thread_caches();
168 * Instruct the kernel to free parts of the unused stack back to the system.
169 * Like flush_thread_caches, this is called when the thread has been idle
170 * and predicted to continue to be idle for a while.
172 void flush_thread_stack();
175 * Like scoped_ptr, but calls free() on destruct
177 class ScopedMem {
178 ScopedMem(const ScopedMem&); // disable copying
179 ScopedMem& operator=(const ScopedMem&);
180 public:
181 ScopedMem() : m_ptr(0) {}
182 explicit ScopedMem(void* ptr) : m_ptr(ptr) {}
183 ~ScopedMem() { free(m_ptr); }
184 ScopedMem& operator=(void* ptr) {
185 assert(!m_ptr);
186 m_ptr = ptr;
187 return *this;
189 private:
190 void* m_ptr;
193 extern __thread uintptr_t s_stackLimit;
194 extern __thread size_t s_stackSize;
195 void init_stack_limits(pthread_attr_t* attr);
197 extern const size_t s_pageSize;
200 * The numa node this thread is bound to
202 extern __thread int32_t s_numaNode;
204 * enable the numa support in hhvm,
205 * and determine whether threads should default to using
206 * local memory.
208 void enable_numa(bool local);
210 * Determine the node that the next thread should run on.
212 int next_numa_node();
214 * Set the thread affinity, and the jemalloc arena for the current
215 * thread.
216 * Also initializes s_numaNode
218 void set_numa_binding(int node);
220 * The number of numa nodes in the system
222 int num_numa_nodes();
224 * Enable numa interleaving for the specified address range
226 void numa_interleave(void* start, size_t size);
228 * Allocate the specified address range on the local node
230 void numa_local(void* start, size_t size);
232 * Allocate the specified address range on the given node
234 void numa_bind_to(void* start, size_t size, int node);
236 #ifdef USE_JEMALLOC
239 * jemalloc pprof utility functions.
241 int jemalloc_pprof_enable();
242 int jemalloc_pprof_disable();
243 int jemalloc_pprof_dump(const std::string& prefix, bool force);
245 #endif // USE_JEMALLOC
247 ///////////////////////////////////////////////////////////////////////////////
250 #endif // incl_HPHP_UTIL_ALLOC_H_