track total size of static array and Unit/Class/Func
[hiphop-php.git] / hphp / runtime / base / apc-typed-value.h
blob0b23629409e9f75dc214f8e3f3d0337c634e5b05
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_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"
23 namespace HPHP {
25 //////////////////////////////////////////////////////////////////////
27 struct APCTypedValue {
28 // Int or bool
29 enum class Bool {};
30 APCTypedValue(Bool, bool data)
31 : m_handle(APCKind::Bool, KindOfBoolean) {
32 m_data.num = data;
35 explicit APCTypedValue(int64_t data)
36 : m_handle(APCKind::Int, KindOfInt64) {
37 m_data.num = data;
40 explicit APCTypedValue(double data)
41 : m_handle(APCKind::Double, KindOfDouble) {
42 m_data.dbl = data;
45 explicit APCTypedValue(const Func* data)
46 : m_handle(APCKind::PersistentFunc, KindOfFunc) {
47 assertx(data->isPersistent());
48 assertx(!data->isMethod());
49 m_data.func = data;
50 assertx(checkInvariants());
53 enum class StaticStr {};
54 APCTypedValue(StaticStr, StringData* data)
55 : m_handle(APCKind::StaticString, KindOfPersistentString) {
56 assertx(data->isStatic());
57 m_data.str = data;
58 assertx(checkInvariants());
61 enum class UncountedStr {};
62 APCTypedValue(UncountedStr, StringData* data)
63 : m_handle(APCKind::UncountedString, KindOfPersistentString) {
64 assertx(data->isUncounted());
65 m_data.str = data;
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());
74 m_data.arr = data;
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());
83 m_data.arr = data;
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());
92 m_data.vec = data;
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());
101 m_data.vec = data;
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());
110 m_data.dict = data;
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());
119 m_data.dict = data;
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
144 m_data.num = 0;
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() {
160 return &m_handle;
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);
170 return m_data.num;
173 double getDouble() const {
174 assertx(checkInvariants() && m_handle.kind() == APCKind::Double);
175 return m_data.dbl;
178 StringData* getStringData() const {
179 assertx(checkInvariants());
180 assertx(m_handle.kind() == APCKind::StaticString ||
181 m_handle.kind() == APCKind::UncountedString);
182 return m_data.str;
185 ArrayData* getArrayData() const {
186 assertx(checkInvariants());
187 assertx(m_handle.kind() == APCKind::StaticArray ||
188 m_handle.kind() == APCKind::UncountedArray);
189 return m_data.arr;
192 ArrayData* getVecData() const {
193 assertx(checkInvariants());
194 assertx(m_handle.kind() == APCKind::StaticVec ||
195 m_handle.kind() == APCKind::UncountedVec);
196 return m_data.vec;
199 ArrayData* getDictData() const {
200 assertx(checkInvariants());
201 assertx(m_handle.kind() == APCKind::StaticDict ||
202 m_handle.kind() == APCKind::UncountedDict);
203 return m_data.dict;
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());
215 TypedValue tv;
216 tv.m_data.num = m_data.num;
217 tv.m_type = m_handle.type();
218 return tv;
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,
232 UncountedKey ukey,
233 XData *data) {
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)};
244 return {nullptr, 0};
247 private:
248 APCTypedValue(const APCTypedValue&) = delete;
249 APCTypedValue& operator=(const APCTypedValue&) = delete;
250 bool checkInvariants() const;
252 private:
253 union {
254 int64_t num;
255 double dbl;
256 StringData* str;
257 ArrayData* arr;
258 ArrayData* vec;
259 ArrayData* dict;
260 ArrayData* shape;
261 ArrayData* keyset;
262 const Func* func;
263 } m_data;
264 APCHandle m_handle;
267 //////////////////////////////////////////////////////////////////////
268 // Here because of circular dependencies
270 inline Variant APCHandle::toLocal() const {
271 if (isTypedValue()) {
272 Variant ret;
273 *ret.asTypedValue() = APCTypedValue::fromHandle(this)->toTypedValue();
274 return ret;
276 return toLocalHelper();
279 //////////////////////////////////////////////////////////////////////
283 #endif