2 +----------------------------------------------------------------------+
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 #include "hphp/util/data-block.h"
21 void* DataBlock::allocInner(size_t len
) {
22 assert(len
< std::numeric_limits
<Size
>::max());
24 if (!len
) return nullptr;
26 auto freeList
= m_freeLists
.lower_bound(len
);
27 if (freeList
== m_freeLists
.end()) {
30 always_assert(!freeList
->second
.empty());
32 auto size
= freeList
->first
;
33 auto off
= *freeList
->second
.begin();
34 freeList
->second
.erase(off
);
35 m_freeRanges
.erase(off
);
36 m_freeRanges
.erase(off
+ size
);
41 m_freeLists
[size
- len
].emplace(off
+ len
);
42 m_freeRanges
[off
+ len
] = size
- len
;
43 m_freeRanges
[off
+ size
] = -(int64_t)(size
- len
);
49 if (freeList
->second
.empty()) m_freeLists
.erase(freeList
);
51 return m_destBase
+ off
;
54 void DataBlock::free(void* vaddr
, size_t len
) {
55 auto addr
= static_cast<void*>(((char*)vaddr
- (char*)m_destBase
) + m_base
);
57 assert(len
< std::numeric_limits
<uint32_t>::max() &&
58 (CodeAddress
)addr
+ len
<= m_frontier
);
62 Offset off
= (Offset
)((CodeAddress
)addr
- m_base
);
64 auto after
= m_freeRanges
.find(off
+ len
);
65 auto before
= m_freeRanges
.find(off
);
66 if (before
!= m_freeRanges
.end()) {
67 assertx(before
->second
< 0);
68 auto beforeEnd
= before
;
69 before
= m_freeRanges
.find(off
+ before
->second
);
70 m_freeRanges
.erase(beforeEnd
);
71 assertx(before
!= m_freeRanges
.end());
74 if (before
!= m_freeRanges
.end()) {
75 auto list
= m_freeLists
.find(before
->second
);
76 assertx(list
!= m_freeLists
.end());
78 list
->second
.erase(before
->first
);
79 if (list
->second
.empty()) m_freeLists
.erase(list
);
82 if ((CodeAddress
)addr
+ len
== m_frontier
) {
83 if (before
!= m_freeRanges
.end()) {
84 m_bytesFree
-= before
->second
;
85 len
+= before
->second
;
86 m_freeRanges
.erase(before
);
88 assert(after
== m_freeRanges
.end());
95 if (after
!= m_freeRanges
.end()) {
97 auto list
= m_freeLists
.find(after
->second
);
98 assertx(list
!= m_freeLists
.end());
100 list
->second
.erase(after
->first
);
101 if (list
->second
.empty()) m_freeLists
.erase(list
);
102 m_freeRanges
.erase(after
);
105 if (before
!= m_freeRanges
.end()) {
106 before
->second
= (len
+= before
->second
);
109 m_freeRanges
[off
] = len
;
111 m_freeLists
[len
].emplace(off
);
112 m_freeRanges
[off
+ len
] = -(int64_t)len
;
115 void DataBlock::reportFull(size_t nBytes
) const {
116 throw DataBlockFull(m_name
, folly::sformat(
117 "Attempted to emit {} byte(s) into a {} byte DataBlock with {} bytes "
118 "available ({} max bytes). This almost certainly means the TC is full. If "
119 "this is the case, increasing Eval.JitASize, Eval.JitAColdSize, "
120 "Eval.JitAFrozenSize and Eval.JitGlobalDataSize in the configuration "
121 "file when running this script or application should fix this problem.",
122 nBytes
, m_size
, m_size
- (m_frontier
- m_base
), m_maxGrow
));
125 void DataBlock::reportMallocError(size_t nBytes
) const {
126 throw DataBlockFull(m_name
, folly::sformat(
127 "Encountered a malloc/realloc error while attempting to grow a {} byte "
128 "DataBlock to {} bytes. The maximum size for this DataBlock is {} byte(s).",
129 m_size
, nBytes
, m_maxGrow
));