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_ARRAY_H_
18 #define incl_HPHP_APC_ARRAY_H_
20 #include "hphp/runtime/base/apc-handle-defs.h"
21 #include "hphp/runtime/base/mixed-array.h"
22 #include "hphp/runtime/base/packed-array.h"
23 #include "hphp/runtime/base/set-array.h"
24 #include "hphp/util/atomic.h"
25 #include "hphp/util/lock.h"
26 #include "hphp/util/hash.h"
30 //////////////////////////////////////////////////////////////////////
34 //////////////////////////////////////////////////////////////////////
37 static APCHandle::Pair
MakeSharedArray(ArrayData
* data
,
40 static APCHandle::Pair
MakeSharedVec(ArrayData
* data
,
43 static APCHandle::Pair
MakeSharedDict(ArrayData
* data
,
46 static APCHandle::Pair
MakeSharedKeyset(ArrayData
* data
,
50 static APCHandle
* MakeUncountedArray(ArrayData
* array
,
51 PointerMap
* m
= nullptr);
52 static APCHandle
* MakeUncountedVec(ArrayData
* vec
,
53 PointerMap
* m
= nullptr);
54 static APCHandle
* MakeUncountedDict(ArrayData
* dict
,
55 PointerMap
* m
= nullptr);
56 static APCHandle
* MakeUncountedKeyset(ArrayData
* dict
);
58 static APCHandle::Pair
MakeSharedEmptyArray();
59 static void Delete(APCHandle
* handle
);
61 static APCArray
* fromHandle(APCHandle
* handle
) {
62 assertx(handle
->checkInvariants());
63 assertx(handle
->kind() == APCKind::SharedArray
||
64 handle
->kind() == APCKind::SharedPackedArray
||
65 handle
->kind() == APCKind::SharedVArray
||
66 handle
->kind() == APCKind::SharedDArray
||
67 handle
->kind() == APCKind::SharedVec
||
68 handle
->kind() == APCKind::SharedDict
||
69 handle
->kind() == APCKind::SharedKeyset
);
70 static_assert(offsetof(APCArray
, m_handle
) == 0, "");
71 return reinterpret_cast<APCArray
*>(handle
);
74 static const APCArray
* fromHandle(const APCHandle
* handle
) {
75 assertx(handle
->checkInvariants());
76 assertx(handle
->kind() == APCKind::SharedArray
||
77 handle
->kind() == APCKind::SharedPackedArray
||
78 handle
->kind() == APCKind::SharedVArray
||
79 handle
->kind() == APCKind::SharedDArray
||
80 handle
->kind() == APCKind::SharedVec
||
81 handle
->kind() == APCKind::SharedDict
||
82 handle
->kind() == APCKind::SharedKeyset
);
83 static_assert(offsetof(APCArray
, m_handle
) == 0, "");
84 return reinterpret_cast<const APCArray
*>(handle
);
87 // Used when creating/destroying a local wrapper (see APCLocalArray).
88 void reference() const { m_handle
.referenceNonRoot(); }
89 void unreference() const { m_handle
.unreferenceNonRoot(); }
91 ArrayData
* toLocalVArray() const {
92 assertx(!RuntimeOption::EvalHackArrDVArrs
);
93 return PackedArray::MakeVArrayFromAPC(this);
95 ArrayData
* toLocalDArray() const {
96 assertx(!RuntimeOption::EvalHackArrDVArrs
);
97 return MixedArray::MakeDArrayFromAPC(this);
99 ArrayData
* toLocalVec() const { return PackedArray::MakeVecFromAPC(this); }
100 ArrayData
* toLocalDict() const { return MixedArray::MakeDictFromAPC(this); }
101 ArrayData
* toLocalKeyset() const { return SetArray::MakeSetFromAPC(this); }
107 size_t size() const {
108 return isPacked() ? m_size
: m
.m_num
;
111 Variant
getKey(ssize_t pos
) const {
113 assertx(static_cast<size_t>(pos
) < m_size
);
116 assertx(static_cast<size_t>(pos
) < m
.m_num
);
117 return buckets()[pos
].key
->toLocal();
120 APCHandle
* getValue(ssize_t pos
) const {
122 assertx(static_cast<size_t>(pos
) < m_size
);
125 assertx(static_cast<size_t>(pos
) < m
.m_num
);
126 return buckets()[pos
].val
;
129 ssize_t
getIndex(const StringData
* key
) const {
130 return isPacked() ? -1 : indexOf(key
);
133 ssize_t
getIndex(int64_t key
) const {
135 return (static_cast<uint64_t>(key
) >= m_size
) ? -1 : key
;
140 bool isPacked() const {
141 auto const k
= m_handle
.kind();
143 k
== APCKind::SharedPackedArray
||
144 k
== APCKind::SharedVArray
||
145 k
== APCKind::SharedVec
||
146 k
== APCKind::SharedKeyset
;
149 bool isHashed() const {
150 auto const k
= m_handle
.kind();
152 k
== APCKind::SharedArray
||
153 k
== APCKind::SharedDArray
||
154 k
== APCKind::SharedDict
;
157 bool isPHPArray() const {
158 auto const k
= m_handle
.kind();
160 k
== APCKind::SharedArray
||
161 k
== APCKind::SharedPackedArray
||
162 k
== APCKind::SharedVArray
||
163 k
== APCKind::SharedDArray
;
166 bool isVArray() const {
167 return m_handle
.kind() == APCKind::SharedVArray
;
170 bool isDArray() const {
171 return m_handle
.kind() == APCKind::SharedDArray
;
175 return m_handle
.kind() == APCKind::SharedVec
;
178 bool isDict() const {
179 return m_handle
.kind() == APCKind::SharedDict
;
182 bool isKeyset() const {
183 return m_handle
.kind() == APCKind::SharedKeyset
;
188 /** index of the next bucket, or -1 if the end of a chain */
190 /** the value of this bucket */
196 enum class PackedCtor
{};
197 APCArray(PackedCtor
, APCKind kind
, size_t size
)
198 : m_handle(kind
, kInvalidDataType
), m_size(size
) {
202 enum class HashedCtor
{};
203 APCArray(HashedCtor
, APCKind kind
, unsigned int cap
) : m_handle(kind
) {
205 m
.m_capacity_mask
= cap
- 1;
210 APCArray(const APCArray
&) = delete;
211 APCArray
& operator=(const APCArray
&) = delete;
214 template <typename A
, typename B
, typename C
>
215 static APCHandle::Pair
MakeSharedImpl(ArrayData
*, APCHandleLevel
, A
, B
, C
);
217 static APCHandle::Pair
MakeHash(ArrayData
* data
, APCKind kind
,
218 bool unserializeObj
);
219 static APCHandle::Pair
MakePacked(ArrayData
* data
, APCKind kind
,
220 bool unserializeObj
);
223 friend size_t getMemSize(const APCArray
*);
225 void add(APCHandle
* key
, APCHandle
* val
);
226 ssize_t
indexOf(const StringData
* key
) const;
227 ssize_t
indexOf(int64_t key
) const;
229 /* index of the beginning of each hash chain */
230 int* hash() const { return (int*)(this + 1); }
231 /* buckets, stored in index order */
232 Bucket
* buckets() const { return (Bucket
*)(hash() + m
.m_capacity_mask
+ 1); }
233 /* start of the data for packed array */
234 APCHandle
** vals() const { return (APCHandle
**)(this + 1); }
236 APCHandle
* getHandle() {
239 const APCHandle
* getHandle() const {
246 // for map style arrays
248 unsigned int m_capacity_mask
;
256 //////////////////////////////////////////////////////////////////////