Reinstate error on tuple array get with non-int
[hiphop-php.git] / hphp / util / bump-mapper.h
blob74027a57babf5c1ec1549a5481fcfb9e98e9565c
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 #pragma once
19 #include "hphp/util/address-range.h"
20 #include "hphp/util/alloc-defs.h"
21 #include "hphp/util/alloc.h"
22 #include <functional>
23 #include <utility>
25 #if USE_JEMALLOC_EXTENT_HOOKS
27 namespace HPHP {
29 extern bool g_useTHPUponHugeTLBFailure;
31 namespace alloc {
33 // Interface for all mappers. It also includes data about page limit (for huge
34 // page mappers) and NUMA support.
35 struct RangeMapper {
36 public:
37 // State is shared between multiple mappers and multiple threads.
38 explicit RangeMapper(RangeState& state, uint32_t maxHugePages = 0,
39 uint32_t numaMask = 0, short nextNode = 0)
40 : m_state(state)
41 , m_maxHugePages(maxHugePages)
42 , m_interleaveMask(numaMask)
43 , m_nextNode(nextNode) {}
45 virtual ~RangeMapper() = default;
47 // Form a linked list of mappers for the same range.
48 static void append(RangeMapper**& ptail, RangeMapper* next) {
49 assert((*ptail) == nullptr); // always keep track of the tail.
50 *ptail = next;
51 ptail = &(next->m_fallback);
52 assert((*ptail) == nullptr); // next already has fallback?
55 RangeMapper* next() {
56 return m_fallback;
59 RangeState& getRangeState() {
60 return m_state;
63 void setMaxPages(uint32_t maxHugePages) {
64 m_maxHugePages = maxHugePages;
67 bool addMapping() {
68 if (!m_failed) {
69 if (addMappingImpl()) return true;
70 // Some hugepage mappers start with zero page budget. Don't fail
71 // permanently if they didn't work in the beginning.
72 if (m_maxHugePages) m_failed = true;
74 return false;
77 void* alloc(size_t size, size_t align) {
78 if (!m_failed) {
79 auto const d = direction();
80 do {
81 if (m_state.trivial(size, align, d)) {
82 if (auto r = m_state.tryAlloc(size, align, d)) return r;
84 if (m_state.infeasible(size, align, d)) return nullptr;
85 } while (addMapping());
87 if (m_fallback) return m_fallback->alloc(size, align);
88 return nullptr;
91 protected:
92 virtual bool addMappingImpl() = 0;
93 virtual Direction direction() const = 0;
95 protected:
96 RangeState& m_state;
97 uint32_t m_maxHugePages{0};
98 uint32_t m_currHugePages{0};
99 uint32_t m_interleaveMask; // 0 indicates no NUMA
100 short m_nextNode{0};
101 bool m_failed{false};
102 RangeMapper* m_fallback{nullptr};
106 struct Bump1GMapper : public RangeMapper {
107 public:
108 template<typename... Args>
109 explicit Bump1GMapper(Args&&... args)
110 : RangeMapper(std::forward<Args>(args)...) {}
112 protected:
113 Direction direction() const override { return Direction::LowToHigh; }
114 bool addMappingImpl() override;
118 struct Bump2MMapper : public RangeMapper {
119 public:
120 template<typename... Args>
121 explicit Bump2MMapper(Args&&... args)
122 : RangeMapper(std::forward<Args>(args)...) {}
124 protected:
125 Direction direction() const override { return Direction::LowToHigh; }
126 bool addMappingImpl() override;
130 template<Direction D = Direction::LowToHigh>
131 struct BumpNormalMapper : public RangeMapper {
132 public:
133 template<typename... Args>
134 explicit BumpNormalMapper(Args&&... args)
135 : RangeMapper(std::forward<Args>(args)...) {}
137 protected:
138 Direction direction() const override { return D; }
139 bool addMappingImpl() override;
142 // Create mappings backed by a file
143 struct BumpFileMapper : public RangeMapper {
144 public:
145 template<typename... Args>
146 explicit BumpFileMapper(Args&&... args)
147 : RangeMapper(std::forward<Args>(args)...) {
148 m_failed = true; // disabled initially
150 void enable() {
151 m_failed = false;
153 bool setDirectory(const char* dir);
155 protected:
156 Direction direction() const override { return Direction::LowToHigh; }
157 bool addMappingImpl() override;
158 private:
159 int m_fd{0};
160 // PATH_MAX feels like a waste of memory, so use something smaller and make it
161 // configurable at build time.
162 #ifndef TMPDIRMAXLEN
163 #define TMPDIRMAXLEN 80
164 #endif
165 char m_dirName[TMPDIRMAXLEN]{};
169 // A mapper that is used when other mappers all fail. To avoid crashing, this
170 // could allocate from some emergency buffer, and initiate a graceful shutdown.
171 // The range passed in should be pre-mapped.
172 struct BumpEmergencyMapper : public RangeMapper {
173 public:
174 using ExitFun = std::function<void()>;
175 template<typename... Args>
176 explicit BumpEmergencyMapper(ExitFun&& exitFn, Args&&... args)
177 : RangeMapper(std::forward<Args>(args)...)
178 , m_exit(exitFn) {}
179 protected:
180 Direction direction() const override { return Direction::LowToHigh; }
181 bool addMappingImpl() override;
182 protected:
183 // The exit function to call when we start using the emergency mapping.
184 ExitFun m_exit;
189 #endif