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 #ifndef incl_HPHP_PACKED_ARRAY_DEFS_H_
17 #define incl_HPHP_PACKED_ARRAY_DEFS_H_
19 #include "hphp/runtime/base/packed-array.h"
21 #include "hphp/runtime/base/array-data.h"
22 #include "hphp/runtime/base/hash-table.h"
23 #include "hphp/runtime/base/typed-value.h"
25 #include "hphp/util/type-scan.h"
29 //////////////////////////////////////////////////////////////////////
32 * Return the payload from a ArrayData* that is kPacked/VecKind.
35 TypedValue
* packedData(const ArrayData
* arr
) {
36 return const_cast<TypedValue
*>(
37 reinterpret_cast<const TypedValue
*>(arr
+ 1)
42 ptrdiff_t PackedArray::entriesOffset() {
43 return reinterpret_cast<ptrdiff_t>(
44 packedData(reinterpret_cast<ArrayData
*>(0x0)));
47 /* this only exists to make compilers happy about types in the below macro */
48 inline constexpr uint32_t sizeClassParams2PackedArrayCapacity(
54 static_assert(sizeof(ArrayData
) <= kSizeIndex2Size
[0],
55 "this math only works if ArrayData fits in the smallest size class");
56 return index
<= PackedArray::MaxSizeIndex
57 ? (((size_t{1} << lg_grp
) + (ndelta
<< lg_delta
)) - sizeof(ArrayData
))
62 /* We can use uint32_t safely because capacity is in units of array elements,
63 * and arrays can't have more than 32 bits worth of elements.
65 alignas(64) constexpr uint32_t kSizeIndex2PackedArrayCapacity
[] = {
66 #define SIZE_CLASS(index, lg_grp, lg_delta, ndelta, lg_delta_lookup, ncontig) \
67 sizeClassParams2PackedArrayCapacity(index, lg_grp, lg_delta, ndelta),
73 kSizeIndex2PackedArrayCapacity
[PackedArray::SmallSizeIndex
]
74 == PackedArray::SmallSize
,
75 "SmallSizeIndex must be MM size class index for array of SmallSize"
78 // MaxSizeIndex corresponds to HashTableCommon::MaxSize - 1 (which is the same
79 // as MixedArray::MaxSize - 1) because HashTableCommon::MaxSize - 1 exactly fits
80 // into a MM size class, PackedArray::capacity is a function of MM size class,
81 // and we can't allow a capacity > MaxSize since most operations only check
82 // that size <= capacity stays true (and don't explicitly check size <= MaxSize)
84 kSizeIndex2PackedArrayCapacity
[PackedArray::MaxSizeIndex
]
85 == array::HashTableCommon::MaxSize
- 1,
86 "MaxSizeIndex must be the largest possible size class index for PackedArrays"
90 size_t PackedArray::capacityToSizeIndex(size_t cap
) {
91 if (cap
<= PackedArray::SmallSize
) {
92 return PackedArray::SmallSizeIndex
;
94 auto const sizeIndex
= MemoryManager::size2Index(
95 sizeof(ArrayData
) + cap
* sizeof(TypedValue
)
97 assertx(sizeIndex
<= PackedArray::MaxSizeIndex
);
102 uint32_t PackedArray::capacity(const ArrayData
* ad
) {
103 return kSizeIndex2PackedArrayCapacity
[sizeClass(ad
)];
107 size_t PackedArray::heapSize(const ArrayData
* ad
) {
108 return kSizeIndex2Size
[sizeClass(ad
)];
111 // Pack together the size class and the varray/darray state into a single 16-bit
112 // number which can be stored in the HeapObject object. ArrayData requires the
113 // varray/darray state to be in the lower 8-bits, but we're free to use the
116 uint16_t PackedArray::packSizeIndexAndDV(uint8_t idx
, ArrayData::DVArray dv
) {
117 return (static_cast<uint16_t>(idx
) << 8) | dv
;
121 uint8_t PackedArray::sizeClass(const ArrayData
* ad
) {
122 return ad
->m_aux16
>> 8;
125 inline void PackedArray::scan(const ArrayData
* a
, type_scan::Scanner
& scanner
) {
126 assertx(checkInvariants(a
));
127 auto data
= packedData(a
);
128 scanner
.scan(*data
, a
->getSize() * sizeof(*data
));
131 template <class F
, bool inc
>
132 void PackedArray::IterateV(const ArrayData
* arr
, F fn
) {
133 assertx(checkInvariants(arr
));
134 auto elm
= packedData(arr
);
135 if (inc
) arr
->incRefCount();
136 SCOPE_EXIT
{ if (inc
) decRefArr(const_cast<ArrayData
*>(arr
)); };
137 for (auto i
= arr
->m_size
; i
--; elm
++) {
138 if (ArrayData::call_helper(fn
, *elm
)) break;
142 template <class F
, bool inc
>
143 void PackedArray::IterateKV(const ArrayData
* arr
, F fn
) {
144 assertx(checkInvariants(arr
));
145 auto elm
= packedData(arr
);
146 if (inc
) arr
->incRefCount();
147 SCOPE_EXIT
{ if (inc
) decRefArr(const_cast<ArrayData
*>(arr
)); };
148 auto key
= make_tv
<KindOfInt64
>(0);
149 for (auto i
= arr
->m_size
; i
--; key
.m_data
.num
++, elm
++) {
150 if (ArrayData::call_helper(fn
, key
, *elm
)) break;
154 //////////////////////////////////////////////////////////////////////