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 +----------------------------------------------------------------------+
19 #include "hphp/runtime/base/apc-handle.h"
20 #include "hphp/runtime/base/apc-handle-defs.h"
24 //////////////////////////////////////////////////////////////////////
26 struct APCTypedValue
{
29 APCTypedValue(Bool
, bool data
)
30 : m_handle(APCKind::Bool
, KindOfBoolean
) {
34 explicit APCTypedValue(int64_t data
)
35 : m_handle(APCKind::Int
, KindOfInt64
) {
39 explicit APCTypedValue(double data
)
40 : m_handle(APCKind::Double
, KindOfDouble
) {
44 explicit APCTypedValue(const Func
* data
)
45 : m_handle(APCKind::PersistentFunc
, KindOfFunc
) {
46 assertx(data
->isPersistent());
47 assertx(!data
->isMethod());
49 assertx(checkInvariants());
52 explicit APCTypedValue(const Class
* data
)
53 : m_handle(APCKind::PersistentClass
, KindOfClass
) {
54 assertx(data
->isPersistent());
56 assertx(checkInvariants());
59 explicit APCTypedValue(LazyClassData data
)
60 : m_handle(APCKind::LazyClass
, KindOfLazyClass
) {
61 m_data
.str
= const_cast<StringData
*>(data
.name());
62 assertx(checkInvariants());
65 explicit APCTypedValue(const ClsMethDataRef ref
)
66 : m_handle(APCKind::PersistentClsMeth
, KindOfClsMeth
) {
67 assertx(ref
->getCls()->isPersistent());
68 m_data
.pclsmeth
= ref
;
71 enum class StaticStr
{};
72 APCTypedValue(StaticStr
, StringData
* data
)
73 : m_handle(APCKind::StaticString
, KindOfPersistentString
) {
74 assertx(data
->isStatic());
76 assertx(checkInvariants());
79 enum class UncountedStr
{};
80 APCTypedValue(UncountedStr
, StringData
* data
)
81 : m_handle(APCKind::UncountedString
, KindOfPersistentString
) {
82 assertx(data
->isUncounted());
84 assertx(checkInvariants());
87 explicit APCTypedValue(DataType type
)
88 : m_handle(type
== KindOfUninit
? APCKind::Uninit
: APCKind::Null
, type
) {
89 assertx(isNullType(type
)); // Uninit or Null
93 static APCTypedValue
* fromHandle(APCHandle
* handle
) {
94 assertx(handle
->checkInvariants() && !handle
->isAtomicCounted());
95 static_assert(offsetof(APCTypedValue
, m_handle
) == sizeof(APCHandle
), "");
96 return reinterpret_cast<APCTypedValue
*>(handle
- 1);
99 static const APCTypedValue
* fromHandle(const APCHandle
* handle
) {
100 assertx(handle
->checkInvariants() && !handle
->isAtomicCounted());
101 static_assert(offsetof(APCTypedValue
, m_handle
) == sizeof(APCHandle
), "");
102 return reinterpret_cast<const APCTypedValue
*>(handle
- 1);
105 APCHandle
* getHandle() {
109 bool getBoolean() const {
110 assertx(checkInvariants() && m_handle
.kind() == APCKind::Bool
);
111 return m_data
.num
!= 0;
114 int64_t getInt64() const {
115 assertx(checkInvariants() && m_handle
.kind() == APCKind::Int
);
119 double getDouble() const {
120 assertx(checkInvariants() && m_handle
.kind() == APCKind::Double
);
124 StringData
* getStringData() const {
125 assertx(checkInvariants());
126 assertx(m_handle
.kind() == APCKind::StaticString
||
127 m_handle
.kind() == APCKind::UncountedString
);
131 ArrayData
* getArrayData() const;
132 void setArrayData(ArrayData
* ad
);
134 TypedValue
toTypedValue() const;
136 static APCTypedValue
* ForArray(ArrayData
* ad
);
138 static APCTypedValue
* tvUninit();
139 static APCTypedValue
* tvNull();
140 static APCTypedValue
* tvTrue();
141 static APCTypedValue
* tvFalse();
143 static void FreeHazardPointers();
144 static void PushHazardPointer(const APCHandle
* handle
);
145 static bool UseStringHazardPointers();
147 void deleteUncounted();
149 static APCHandle::Pair
HandlePersistent(ArrayData
* data
) {
150 if (!data
->persistentIncRef()) return {nullptr, 0};
151 auto const value
= APCTypedValue::ForArray(data
);
152 return {value
->getHandle(), sizeof(APCTypedValue
)};
155 static APCHandle::Pair
HandlePersistent(StringData
* data
) {
156 if (data
->isRefCounted()) {
159 if (data
->isStatic()) {
160 auto const value
= new APCTypedValue(StaticStr
{}, data
);
161 return {value
->getHandle(), sizeof(APCTypedValue
)};
163 data
->uncountedIncRef();
164 auto const value
= new APCTypedValue(UncountedStr
{}, data
);
165 return {value
->getHandle(), sizeof(APCTypedValue
)};
169 APCTypedValue(ArrayData
* ad
, APCKind kind
, DataType dt
);
171 APCTypedValue(const APCTypedValue
&) = delete;
172 APCTypedValue
& operator=(const APCTypedValue
&) = delete;
173 bool checkInvariants() const;
182 ClsMethDataRef pclsmeth
;
183 std::atomic
<ArrayData
*> arr
{};
188 //////////////////////////////////////////////////////////////////////
189 // Here because of circular dependencies
191 inline TypedValue
APCHandle::toLazyProp() const {
192 if (isTypedValue()) return APCTypedValue::fromHandle(this)->toTypedValue();
195 result
.m_type
= kInvalidDataType
;
196 result
.m_data
.num
= static_cast<int64_t>(uintptr_t(this));
200 inline Variant
APCHandle::toLocal(bool pure
) const {
201 if (isTypedValue()) {
203 *ret
.asTypedValue() = APCTypedValue::fromHandle(this)->toTypedValue();
206 return toLocalHelper(pure
);
209 //////////////////////////////////////////////////////////////////////