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 #ifndef incl_HPHP_APC_TYPED_VALUE_H_
18 #define incl_HPHP_APC_TYPED_VALUE_H_
20 #include "hphp/runtime/base/apc-handle.h"
21 #include "hphp/runtime/base/apc-handle-defs.h"
25 //////////////////////////////////////////////////////////////////////
27 struct APCTypedValue
{
30 APCTypedValue(Bool
, bool data
)
31 : m_handle(APCKind::Bool
, KindOfBoolean
) {
35 explicit APCTypedValue(int64_t data
)
36 : m_handle(APCKind::Int
, KindOfInt64
) {
40 explicit APCTypedValue(double data
)
41 : m_handle(APCKind::Double
, KindOfDouble
) {
45 explicit APCTypedValue(const Func
* data
)
46 : m_handle(APCKind::PersistentFunc
, KindOfFunc
) {
47 assertx(data
->isPersistent());
48 assertx(!data
->isMethod());
50 assertx(checkInvariants());
53 enum class StaticStr
{};
54 APCTypedValue(StaticStr
, StringData
* data
)
55 : m_handle(APCKind::StaticString
, KindOfPersistentString
) {
56 assertx(data
->isStatic());
58 assertx(checkInvariants());
61 enum class UncountedStr
{};
62 APCTypedValue(UncountedStr
, StringData
* data
)
63 : m_handle(APCKind::UncountedString
, KindOfPersistentString
) {
64 assertx(data
->isUncounted());
66 assertx(checkInvariants());
69 enum class StaticArr
{};
70 APCTypedValue(StaticArr
, ArrayData
* data
)
71 : m_handle(APCKind::StaticArray
, KindOfPersistentArray
) {
72 assertx(data
->isPHPArrayKind());
73 assertx(data
->isStatic());
75 assertx(checkInvariants());
78 enum class UncountedArr
{};
79 APCTypedValue(UncountedArr
, ArrayData
* data
)
80 : m_handle(APCKind::UncountedArray
, KindOfPersistentArray
) {
81 assertx(data
->isPHPArrayKind());
82 assertx(data
->isUncounted());
84 assertx(checkInvariants());
87 enum class StaticVec
{};
88 APCTypedValue(StaticVec
, ArrayData
* data
)
89 : m_handle(APCKind::StaticVec
, KindOfPersistentVec
) {
90 assertx(data
->isVecArrayKind());
91 assertx(data
->isStatic());
93 assertx(checkInvariants());
96 enum class UncountedVec
{};
97 APCTypedValue(UncountedVec
, ArrayData
* data
)
98 : m_handle(APCKind::UncountedVec
, KindOfPersistentVec
) {
99 assertx(data
->isVecArrayKind());
100 assertx(data
->isUncounted());
102 assertx(checkInvariants());
105 enum class StaticDict
{};
106 APCTypedValue(StaticDict
, ArrayData
* data
)
107 : m_handle(APCKind::StaticDict
, KindOfPersistentDict
) {
108 assertx(data
->isDictKind());
109 assertx(data
->isStatic());
111 assertx(checkInvariants());
114 enum class UncountedDict
{};
115 APCTypedValue(UncountedDict
, ArrayData
* data
)
116 : m_handle(APCKind::UncountedDict
, KindOfPersistentDict
) {
117 assertx(data
->isDictKind());
118 assertx(data
->isUncounted());
120 assertx(checkInvariants());
123 enum class StaticKeyset
{};
124 APCTypedValue(StaticKeyset
, ArrayData
* data
)
125 : m_handle(APCKind::StaticKeyset
, KindOfPersistentKeyset
) {
126 assertx(data
->isKeysetKind());
127 assertx(data
->isStatic());
128 m_data
.keyset
= data
;
129 assertx(checkInvariants());
132 enum class UncountedKeyset
{};
133 APCTypedValue(UncountedKeyset
, ArrayData
* data
)
134 : m_handle(APCKind::UncountedKeyset
, KindOfPersistentKeyset
) {
135 assertx(data
->isKeysetKind());
136 assertx(data
->isUncounted());
137 m_data
.keyset
= data
;
138 assertx(checkInvariants());
141 explicit APCTypedValue(DataType type
)
142 : m_handle(type
== KindOfUninit
? APCKind::Uninit
: APCKind::Null
, type
) {
143 assertx(isNullType(type
)); // Uninit or Null
147 static APCTypedValue
* fromHandle(APCHandle
* handle
) {
148 assertx(handle
->checkInvariants() && !handle
->isAtomicCounted());
149 static_assert(offsetof(APCTypedValue
, m_handle
) == sizeof(APCHandle
), "");
150 return reinterpret_cast<APCTypedValue
*>(handle
- 1);
153 static const APCTypedValue
* fromHandle(const APCHandle
* handle
) {
154 assertx(handle
->checkInvariants() && !handle
->isAtomicCounted());
155 static_assert(offsetof(APCTypedValue
, m_handle
) == sizeof(APCHandle
), "");
156 return reinterpret_cast<const APCTypedValue
*>(handle
- 1);
159 APCHandle
* getHandle() {
163 bool getBoolean() const {
164 assertx(checkInvariants() && m_handle
.kind() == APCKind::Bool
);
165 return m_data
.num
!= 0;
168 int64_t getInt64() const {
169 assertx(checkInvariants() && m_handle
.kind() == APCKind::Int
);
173 double getDouble() const {
174 assertx(checkInvariants() && m_handle
.kind() == APCKind::Double
);
178 StringData
* getStringData() const {
179 assertx(checkInvariants());
180 assertx(m_handle
.kind() == APCKind::StaticString
||
181 m_handle
.kind() == APCKind::UncountedString
);
185 ArrayData
* getArrayData() const {
186 assertx(checkInvariants());
187 assertx(m_handle
.kind() == APCKind::StaticArray
||
188 m_handle
.kind() == APCKind::UncountedArray
);
192 ArrayData
* getVecData() const {
193 assertx(checkInvariants());
194 assertx(m_handle
.kind() == APCKind::StaticVec
||
195 m_handle
.kind() == APCKind::UncountedVec
);
199 ArrayData
* getDictData() const {
200 assertx(checkInvariants());
201 assertx(m_handle
.kind() == APCKind::StaticDict
||
202 m_handle
.kind() == APCKind::UncountedDict
);
206 ArrayData
* getKeysetData() const {
207 assertx(checkInvariants());
208 assertx(m_handle
.kind() == APCKind::StaticKeyset
||
209 m_handle
.kind() == APCKind::UncountedKeyset
);
210 return m_data
.keyset
;
213 TypedValue
toTypedValue() const {
214 assertx(m_handle
.isTypedValue());
216 tv
.m_data
.num
= m_data
.num
;
217 tv
.m_type
= m_handle
.type();
221 static APCTypedValue
* tvUninit();
222 static APCTypedValue
* tvNull();
223 static APCTypedValue
* tvTrue();
224 static APCTypedValue
* tvFalse();
226 void deleteUncounted();
227 // Recursively register all {allocation, root} with APCGCManager
228 void registerUncountedAllocations();
230 template <class StaticKey
, class UncountedKey
, class XData
>
231 static APCHandle::Pair
HandlePersistent(StaticKey skey
,
234 if (!data
->isRefCounted()) {
235 if (data
->isStatic()) {
236 auto const value
= new APCTypedValue(skey
, data
);
237 return {value
->getHandle(), sizeof(APCTypedValue
)};
239 if (data
->uncountedIncRef()) {
240 auto const value
= new APCTypedValue(ukey
, data
);
241 return {value
->getHandle(), sizeof(APCTypedValue
)};
248 APCTypedValue(const APCTypedValue
&) = delete;
249 APCTypedValue
& operator=(const APCTypedValue
&) = delete;
250 bool checkInvariants() const;
267 //////////////////////////////////////////////////////////////////////
268 // Here because of circular dependencies
270 inline Variant
APCHandle::toLocal() const {
271 if (isTypedValue()) {
273 *ret
.asTypedValue() = APCTypedValue::fromHandle(this)->toTypedValue();
276 return toLocalHelper();
279 //////////////////////////////////////////////////////////////////////