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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/base/apc-handle.h"
18 #include "hphp/runtime/base/apc-array.h"
19 #include "hphp/runtime/base/apc-bespoke.h"
20 #include "hphp/runtime/base/apc-clsmeth.h"
21 #include "hphp/runtime/base/apc-collection.h"
22 #include "hphp/runtime/base/apc-named-entity.h"
23 #include "hphp/runtime/base/apc-object.h"
24 #include "hphp/runtime/base/apc-rclass-meth.h"
25 #include "hphp/runtime/base/apc-rfunc.h"
26 #include "hphp/runtime/base/apc-string.h"
27 #include "hphp/runtime/base/apc-typed-value.h"
28 #include "hphp/runtime/base/vanilla-dict.h"
29 #include "hphp/runtime/ext/apc/ext_apc.h"
30 #include "hphp/runtime/vm/class-meth-data-ref.h"
34 //////////////////////////////////////////////////////////////////////
36 const StaticString
s_invalidMethCaller("Cannot store meth_caller in APC");
38 APCHandle::Pair
APCHandle::Create(const_variant_ref source
,
42 auto const cell
= source
.asTypedValue();
43 switch (cell
.type()) {
45 auto const value
= APCTypedValue::tvUninit();
46 return {value
->getHandle(), sizeof(APCTypedValue
)};
49 auto const value
= APCTypedValue::tvNull();
50 return {value
->getHandle(), sizeof(APCTypedValue
)};
53 auto const value
= val(cell
).num
? APCTypedValue::tvTrue()
54 : APCTypedValue::tvFalse();
55 return {value
->getHandle(), sizeof(APCTypedValue
)};
58 auto const value
= new APCTypedValue(val(cell
).num
);
59 return {value
->getHandle(), sizeof(APCTypedValue
)};
62 auto const value
= new APCTypedValue(val(cell
).dbl
);
63 return {value
->getHandle(), sizeof(APCTypedValue
)};
66 return APCRFunc::Construct(val(cell
).prfunc
);
68 auto const func
= val(cell
).pfunc
;
69 if (func
->isMethCaller()) {
70 SystemLib::throwInvalidOperationExceptionObject(
71 VarNR
{s_invalidMethCaller
.get()}
74 auto const serialize_func
=
75 RuntimeOption::EvalAPCSerializeFuncs
&&
76 // Right now cls_meth() can serialize as an array, and attempting to
77 // recursively serialize elements in the array will eventually attempt
78 // to serialize a method pointer.
81 if (func
->isPersistent()) {
82 auto const value
= new APCTypedValue(func
);
83 return {value
->getHandle(), sizeof(APCTypedValue
)};
85 auto const value
= new APCNamedFunc(func
);
86 return {value
->getHandle(), sizeof(APCNamedFunc
)};
88 invalidFuncConversion("string");
91 auto const cls
= val(cell
).pclass
;
92 if (cls
->isPersistent()) {
93 auto const value
= new APCTypedValue(cls
);
94 return {value
->getHandle(), sizeof(APCTypedValue
)};
96 auto const value
= new APCNamedClass(cls
);
97 return {value
->getHandle(), sizeof(APCNamedClass
)};
99 case KindOfLazyClass
: {
100 auto const value
= new APCTypedValue(val(cell
).plazyclass
);
101 return {value
->getHandle(), sizeof(APCTypedValue
)};
103 case KindOfPersistentString
:
105 auto const s
= val(cell
).pstr
;
106 if (auto const value
= APCTypedValue::HandlePersistent(s
)) {
109 if (auto const st
= lookupStaticString(s
)) {
110 auto const value
= new APCTypedValue(APCTypedValue::StaticStr
{}, st
);
111 return {value
->getHandle(), sizeof(APCTypedValue
)};
113 auto const st
= StringData::MakeUncounted(s
->slice());
114 auto const value
= new APCTypedValue(APCTypedValue::UncountedStr
{}, st
);
115 return {value
->getHandle(), st
->size() + sizeof(APCTypedValue
)};
118 case KindOfPersistentVec
:
120 auto const ad
= val(cell
).parr
;
121 assertx(ad
->isVecType());
122 return APCArray::MakeSharedVec(ad
, level
, unserializeObj
, pure
);
125 case KindOfPersistentDict
:
127 auto const ad
= val(cell
).parr
;
128 assertx(ad
->isDictType());
129 return APCArray::MakeSharedDict(ad
, level
, unserializeObj
, pure
);
132 case KindOfPersistentKeyset
:
134 auto const ad
= val(cell
).parr
;
135 assertx(ad
->isKeysetType());
136 return APCArray::MakeSharedKeyset(ad
, level
, unserializeObj
);
140 if (val(cell
).pobj
->isCollection()) {
141 return APCCollection::Make(val(cell
).pobj
,
146 return unserializeObj
? APCObject::Construct(val(cell
).pobj
, pure
) :
147 APCString::MakeSerializedObject(apc_serialize(source
, pure
));
150 case KindOfEnumClassLabel
:
151 return APCArray::MakeSharedEmptyVec();
154 if (RO::EvalAPCSerializeClsMeth
) {
155 auto const meth
= val(cell
).pclsmeth
;
156 if (meth
->getCls()->isPersistent()) {
157 auto const value
= new APCTypedValue(meth
);
158 return {value
->getHandle(), sizeof(APCTypedValue
)};
160 auto const value
= new APCClsMeth(meth
->getCls(), meth
->getFunc());
161 return {value
->getHandle(), sizeof(APCClsMeth
)};
166 return APCRClsMeth::Construct(val(cell
).prclsmeth
);
171 Variant
APCHandle::toLocalHelper(bool pure
) const {
172 assertx(!isTypedValue());
174 case APCKind::Uninit
:
178 case APCKind::Double
:
179 case APCKind::PersistentFunc
:
180 case APCKind::PersistentClass
:
181 case APCKind::LazyClass
:
182 case APCKind::PersistentClsMeth
:
183 case APCKind::StaticArray
:
184 case APCKind::StaticBespoke
:
185 case APCKind::StaticString
:
186 case APCKind::UncountedArray
:
187 case APCKind::UncountedBespoke
:
188 case APCKind::UncountedString
:
191 case APCKind::FuncEntity
:
192 return APCNamedFunc::fromHandle(this)->getEntityOrNull();
194 case APCKind::ClassEntity
:
195 return APCNamedClass::fromHandle(this)->getEntityOrNull();
197 case APCKind::ClsMeth
:
198 return APCClsMeth::fromHandle(this)->getEntityOrNull();
200 case APCKind::SerializedVec
: {
201 auto const serVec
= APCString::fromHandle(this)->getStringData();
202 auto const v
= apc_unserialize(serVec
->data(), serVec
->size(), pure
);
206 case APCKind::SerializedDict
: {
207 auto const serDict
= APCString::fromHandle(this)->getStringData();
208 auto const v
= apc_unserialize(serDict
->data(), serDict
->size(), pure
);
212 case APCKind::SerializedKeyset
: {
213 auto const serKeyset
= APCString::fromHandle(this)->getStringData();
214 auto const v
= apc_unserialize(serKeyset
->data(), serKeyset
->size(), true /* irrelevant for arraykeys */);
215 assertx(v
.isKeyset());
218 case APCKind::SharedVec
:
219 return Variant::attach(
220 APCArray::fromHandle(this)->toLocalVec(pure
)
222 case APCKind::SharedLegacyVec
:
223 return Variant::attach(
224 APCArray::fromHandle(this)->toLocalLegacyVec(pure
)
226 case APCKind::SharedDict
:
227 return Variant::attach(
228 APCArray::fromHandle(this)->toLocalDict(pure
)
230 case APCKind::SharedLegacyDict
:
231 return Variant::attach(
232 APCArray::fromHandle(this)->toLocalLegacyDict(pure
)
234 case APCKind::SharedKeyset
:
235 return Variant::attach(
236 APCArray::fromHandle(this)->toLocalKeyset()
238 case APCKind::SerializedObject
: {
239 auto const serObj
= APCString::fromHandle(this)->getStringData();
240 return apc_unserialize(serObj
->data(), serObj
->size(), pure
);
242 case APCKind::SharedCollection
:
243 return APCCollection::fromHandle(this)->createObject(pure
);
244 case APCKind::SharedObject
:
245 return APCObject::MakeLocalObject(this, pure
);
247 return APCRFunc::Make(this);
248 case APCKind::RClsMeth
:
249 return APCRClsMeth::Make(this);
254 bool APCHandle::toLocalMayRaise() const {
256 case APCKind::Uninit
:
260 case APCKind::Double
:
261 case APCKind::PersistentFunc
:
262 case APCKind::PersistentClass
:
263 case APCKind::LazyClass
:
264 case APCKind::PersistentClsMeth
:
265 case APCKind::StaticArray
:
266 case APCKind::StaticBespoke
:
267 case APCKind::StaticString
:
268 case APCKind::UncountedArray
:
269 case APCKind::UncountedBespoke
:
270 case APCKind::UncountedString
:
273 case APCKind::FuncEntity
:
274 case APCKind::ClassEntity
:
275 case APCKind::ClsMeth
:
276 case APCKind::SerializedVec
:
277 case APCKind::SerializedDict
:
278 case APCKind::SerializedKeyset
:
279 case APCKind::SerializedObject
:
281 case APCKind::RClsMeth
:
284 case APCKind::SharedVec
:
285 case APCKind::SharedLegacyVec
:
286 case APCKind::SharedDict
:
287 case APCKind::SharedLegacyDict
:
288 case APCKind::SharedKeyset
:
289 return APCArray::fromHandle(this)->toLocalMayRaise();
291 case APCKind::SharedCollection
:
292 return APCCollection::fromHandle(this)->toLocalMayRaise();
294 case APCKind::SharedObject
:
295 return APCObject::fromHandle(this)->toLocalMayRaise();
300 void APCHandle::deleteShared() {
301 assertx(checkInvariants());
303 case APCKind::Uninit
:
308 case APCKind::Double
:
309 case APCKind::StaticArray
:
310 case APCKind::StaticString
:
311 case APCKind::PersistentFunc
:
312 case APCKind::PersistentClass
:
313 case APCKind::LazyClass
:
314 case APCKind::PersistentClsMeth
:
315 delete APCTypedValue::fromHandle(this);
318 case APCKind::ClsMeth
:
319 delete APCClsMeth::fromHandle(this);
322 case APCKind::FuncEntity
:
323 delete APCNamedFunc::fromHandle(this);
326 case APCKind::ClassEntity
:
327 delete APCNamedClass::fromHandle(this);
330 case APCKind::SerializedVec
:
331 case APCKind::SerializedDict
:
332 case APCKind::SerializedKeyset
:
333 case APCKind::SerializedObject
:
334 APCString::Delete(APCString::fromHandle(this));
337 case APCKind::SharedVec
:
338 case APCKind::SharedLegacyVec
:
339 case APCKind::SharedDict
:
340 case APCKind::SharedLegacyDict
:
341 case APCKind::SharedKeyset
:
342 APCArray::Delete(this);
345 case APCKind::SharedObject
:
346 APCObject::Delete(this);
349 case APCKind::SharedCollection
:
350 APCCollection::Delete(this);
354 APCRFunc::Delete(this);
357 case APCKind::RClsMeth
:
358 APCRClsMeth::Delete(this);
361 case APCKind::StaticBespoke
:
362 freeAPCBespoke(APCTypedValue::fromHandle(this));
365 case APCKind::UncountedArray
:
366 case APCKind::UncountedBespoke
:
367 case APCKind::UncountedString
:
374 bool APCHandle::checkInvariants() const {
376 case APCKind::Uninit
:
377 assertx(m_type
== KindOfUninit
);
380 assertx(m_type
== KindOfNull
);
383 assertx(m_type
== KindOfBoolean
);
386 assertx(m_type
== KindOfInt64
);
388 case APCKind::Double
:
389 assertx(m_type
== KindOfDouble
);
391 case APCKind::PersistentFunc
:
392 assertx(m_type
== KindOfFunc
);
394 case APCKind::PersistentClass
:
395 assertx(m_type
== KindOfClass
);
397 case APCKind::LazyClass
:
398 assertx(m_type
== KindOfLazyClass
);
400 case APCKind::PersistentClsMeth
:
401 assertx(m_type
== KindOfClsMeth
);
403 case APCKind::StaticString
:
404 case APCKind::UncountedString
:
405 assertx(m_type
== KindOfPersistentString
);
407 case APCKind::StaticArray
:
408 case APCKind::StaticBespoke
:
409 case APCKind::UncountedArray
:
410 case APCKind::UncountedBespoke
:
411 assertx(m_type
== KindOfPersistentVec
||
412 m_type
== KindOfPersistentDict
||
413 m_type
== KindOfPersistentKeyset
);
415 case APCKind::FuncEntity
:
416 case APCKind::ClassEntity
:
417 case APCKind::ClsMeth
:
419 case APCKind::RClsMeth
:
420 case APCKind::SharedVec
:
421 case APCKind::SharedLegacyVec
:
422 case APCKind::SharedDict
:
423 case APCKind::SharedLegacyDict
:
424 case APCKind::SharedKeyset
:
425 case APCKind::SharedObject
:
426 case APCKind::SharedCollection
:
427 case APCKind::SerializedVec
:
428 case APCKind::SerializedDict
:
429 case APCKind::SerializedKeyset
:
430 case APCKind::SerializedObject
:
431 assertx(m_type
== kInvalidDataType
);
438 void APCHandle::unreferenceRoot(size_t size
) {
439 assertx(isSingletonKind() || m_unref_root_count
++ == 0);
440 if (!isUncounted()) {
442 } else if (APCTypedValue::UseStringHazardPointers()) {
443 APCTypedValue::fromHandle(this)->deleteUncounted();
445 g_context
->enqueueAPCHandle(this, size
);
449 //////////////////////////////////////////////////////////////////////