Add missing #include<utility>
[hiphop-php.git] / hphp / runtime / base / apc-typed-value.h
blobda90661a769b66de376271e63ccced1c3b6e4c03
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 #pragma once
19 #include "hphp/runtime/base/apc-handle.h"
20 #include "hphp/runtime/base/apc-handle-defs.h"
22 namespace HPHP {
24 //////////////////////////////////////////////////////////////////////
26 struct APCTypedValue {
27 // Int or bool
28 enum class Bool {};
29 APCTypedValue(Bool, bool data)
30 : m_handle(APCKind::Bool, KindOfBoolean) {
31 m_data.num = data;
34 explicit APCTypedValue(int64_t data)
35 : m_handle(APCKind::Int, KindOfInt64) {
36 m_data.num = data;
39 explicit APCTypedValue(double data)
40 : m_handle(APCKind::Double, KindOfDouble) {
41 m_data.dbl = data;
44 explicit APCTypedValue(const Func* data)
45 : m_handle(APCKind::PersistentFunc, KindOfFunc) {
46 assertx(data->isPersistent());
47 assertx(!data->isMethod());
48 m_data.func = data;
49 assertx(checkInvariants());
52 explicit APCTypedValue(const Class* data)
53 : m_handle(APCKind::PersistentClass, KindOfClass) {
54 assertx(data->isPersistent());
55 m_data.cls = data;
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());
75 m_data.str = data;
76 assertx(checkInvariants());
79 enum class UncountedStr {};
80 APCTypedValue(UncountedStr, StringData* data)
81 : m_handle(APCKind::UncountedString, KindOfPersistentString) {
82 assertx(data->isUncounted());
83 m_data.str = data;
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
90 m_data.num = 0;
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() {
106 return &m_handle;
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);
116 return m_data.num;
119 double getDouble() const {
120 assertx(checkInvariants() && m_handle.kind() == APCKind::Double);
121 return m_data.dbl;
124 StringData* getStringData() const {
125 assertx(checkInvariants());
126 assertx(m_handle.kind() == APCKind::StaticString ||
127 m_handle.kind() == APCKind::UncountedString);
128 return m_data.str;
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()) {
157 return {nullptr, 0};
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)};
168 private:
169 APCTypedValue(ArrayData* ad, APCKind kind, DataType dt);
171 APCTypedValue(const APCTypedValue&) = delete;
172 APCTypedValue& operator=(const APCTypedValue&) = delete;
173 bool checkInvariants() const;
175 private:
176 union {
177 int64_t num;
178 double dbl;
179 StringData* str;
180 const Func* func;
181 const Class* cls;
182 ClsMethDataRef pclsmeth;
183 std::atomic<ArrayData*> arr{};
184 } m_data;
185 APCHandle m_handle;
188 //////////////////////////////////////////////////////////////////////
189 // Here because of circular dependencies
191 inline TypedValue APCHandle::toLazyProp() const {
192 if (isTypedValue()) return APCTypedValue::fromHandle(this)->toTypedValue();
194 TypedValue result;
195 result.m_type = kInvalidDataType;
196 result.m_data.num = static_cast<int64_t>(uintptr_t(this));
197 return result;
200 inline Variant APCHandle::toLocal(bool pure) const {
201 if (isTypedValue()) {
202 Variant ret;
203 *ret.asTypedValue() = APCTypedValue::fromHandle(this)->toTypedValue();
204 return ret;
206 return toLocalHelper(pure);
209 //////////////////////////////////////////////////////////////////////