Codemod asserts to assertxs in the runtime
[hiphop-php.git] / hphp / runtime / base / packed-array-defs.h
blobb30213ea717f6ecc76f8dad2eaa4d03d5b06b10d
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 +----------------------------------------------------------------------+
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"
27 namespace HPHP {
29 //////////////////////////////////////////////////////////////////////
32 * Return the payload from a ArrayData* that is kPacked/VecKind.
34 ALWAYS_INLINE
35 TypedValue* packedData(const ArrayData* arr) {
36 return const_cast<TypedValue*>(
37 reinterpret_cast<const TypedValue*>(arr + 1)
41 ALWAYS_INLINE
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(
49 size_t index,
50 size_t lg_grp,
51 size_t lg_delta,
52 size_t ndelta
53 ) {
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))
58 / sizeof(TypedValue)
59 : 0;
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),
68 SIZE_CLASSES
69 #undef SIZE_CLASS
72 static_assert(
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)
83 static_assert(
84 kSizeIndex2PackedArrayCapacity[PackedArray::MaxSizeIndex]
85 == array::HashTableCommon::MaxSize - 1,
86 "MaxSizeIndex must be the largest possible size class index for PackedArrays"
89 ALWAYS_INLINE
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);
98 return sizeIndex;
101 ALWAYS_INLINE
102 uint32_t PackedArray::capacity(const ArrayData* ad) {
103 return kSizeIndex2PackedArrayCapacity[sizeClass(ad)];
106 ALWAYS_INLINE
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
114 // upper.
115 ALWAYS_INLINE
116 uint16_t PackedArray::packSizeIndexAndDV(uint8_t idx, ArrayData::DVArray dv) {
117 return (static_cast<uint16_t>(idx) << 8) | dv;
120 ALWAYS_INLINE
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 //////////////////////////////////////////////////////////////////////
158 #endif