Remove empty from slow runtime tests
[hiphop-php.git] / hphp / runtime / base / array-data-inl.h
blob054970fae3619e8be0543591dfd0c816ca86fc8e
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 #include "hphp/runtime/base/runtime-option.h"
19 #include "hphp/util/portability.h"
21 namespace HPHP {
23 ///////////////////////////////////////////////////////////////////////////////
26 * NOTE: MixedArray no longer calls this constructor. If you change it, change
27 * the MixedArray::Make functions as appropriate.
29 inline ArrayData::ArrayData(ArrayKind kind, RefCount initial_count)
30 : m_sizeAndPos(uint32_t(-1))
32 initHeader(static_cast<HeaderKind>(kind), initial_count);
33 assertx(m_size == -1);
34 assertx(m_pos == 0);
35 assertx(m_kind == static_cast<HeaderKind>(kind));
36 assertx(dvArraySanityCheck());
39 ///////////////////////////////////////////////////////////////////////////////
41 ALWAYS_INLINE ArrayData* staticEmptyArray() {
42 void* vp = &s_theEmptyArray;
43 return static_cast<ArrayData*>(vp);
46 ALWAYS_INLINE ArrayData* staticEmptyVArray() {
47 void* vp1 = &s_theEmptyVArray;
48 void* vp2 = &s_theEmptyVecArray;
49 return static_cast<ArrayData*>(RuntimeOption::EvalHackArrDVArrs ? vp2 : vp1);
52 ALWAYS_INLINE ArrayData* staticEmptyVecArray() {
53 void* vp = &s_theEmptyVecArray;
54 return static_cast<ArrayData*>(vp);
57 ALWAYS_INLINE ArrayData* staticEmptyDArray() {
58 void* vp1 = &s_theEmptyDArray;
59 void* vp2 = &s_theEmptyDictArray;
60 return static_cast<ArrayData*>(RuntimeOption::EvalHackArrDVArrs ? vp2 : vp1);
63 ALWAYS_INLINE ArrayData* staticEmptyDictArray() {
64 void* vp = &s_theEmptyDictArray;
65 return static_cast<ArrayData*>(vp);
68 ALWAYS_INLINE ArrayData* staticEmptyShapeArray() {
69 void* vp = RuntimeOption::EvalHackArrDVArrs
70 ? &s_theEmptyShapeDict : &s_theEmptyShapeDArray;
71 return static_cast<ArrayData*>(vp);
74 ALWAYS_INLINE ArrayData* staticEmptyKeysetArray() {
75 void* vp = &s_theEmptySetArray;
76 return static_cast<ArrayData*>(vp);
79 ///////////////////////////////////////////////////////////////////////////////
80 // Creation and destruction.
82 ALWAYS_INLINE ArrayData* ArrayData::Create() {
83 return staticEmptyArray();
86 ALWAYS_INLINE ArrayData* ArrayData::CreateVArray() {
87 return staticEmptyVArray();
90 ALWAYS_INLINE ArrayData* ArrayData::CreateVec() {
91 return staticEmptyVecArray();
94 ALWAYS_INLINE ArrayData* ArrayData::CreateDArray() {
95 return staticEmptyDArray();
98 ALWAYS_INLINE ArrayData* ArrayData::CreateDict() {
99 return staticEmptyDictArray();
102 ALWAYS_INLINE ArrayData* ArrayData::CreateShape() {
103 return staticEmptyShapeArray();
106 ALWAYS_INLINE ArrayData* ArrayData::CreateKeyset() {
107 return staticEmptyKeysetArray();
110 ALWAYS_INLINE void ArrayData::decRefAndRelease() {
111 assertx(kindIsValid());
112 if (decReleaseCheck()) release();
115 ///////////////////////////////////////////////////////////////////////////////
116 // ArrayFunction dispatch.
118 inline size_t ArrayData::vsize() const {
119 return g_array_funcs.vsize[kind()](this);
122 ///////////////////////////////////////////////////////////////////////////////
123 // Introspection.
125 inline size_t ArrayData::size() const {
126 if (UNLIKELY((int)m_size) < 0) return vsize();
127 return m_size;
130 inline size_t ArrayData::getSize() const {
131 return m_size;
134 inline bool ArrayData::empty() const {
135 return size() == 0;
138 inline bool ArrayData::kindIsValid() const {
139 return isArrayKind(m_kind);
142 inline ArrayData::ArrayKind ArrayData::kind() const {
143 assertx(kindIsValid());
144 return static_cast<ArrayKind>(m_kind);
147 inline bool ArrayData::noCopyOnWrite() const {
148 // GlobalsArray doesn't support COW.
149 return kind() == kGlobalsKind;
152 inline bool ArrayData::isPacked() const { return kind() == kPackedKind; }
153 inline bool ArrayData::isMixed() const { return kind() == kMixedKind; }
156 * isMixedOrShape checks whether the ArrayData is kMixedKind or a Shape that
157 * behaves like a mixed PHP Array. This is important because this check is
158 * often used to check that a piece of code is only operating on
159 * mixed PHP array-like objects and not dict-like objects.
161 inline bool ArrayData::isMixedOrShape() const {
162 return kind() == kMixedKind ||
163 (!RuntimeOption::EvalHackArrDVArrs && kind() == kShapeKind);
165 inline bool ArrayData::isApcArray() const { return kind() == kApcKind; }
166 inline bool ArrayData::isGlobalsArray() const { return kind() == kGlobalsKind; }
167 inline bool ArrayData::isEmptyArray() const { return kind() == kEmptyKind; }
168 inline bool ArrayData::isDict() const { return kind() == kDictKind; }
171 * isDictOrShape checks whether the ArrayData is a dict or a Shape that
172 * behaves like a dict. This is important because this check is often used
173 * to check that a piece of code is only operating on dict-like objects and
174 * not array-like objects.
176 inline bool ArrayData::isDictOrShape() const {
177 return kind() == kDictKind ||
178 (RuntimeOption::EvalHackArrDVArrs && kind() == kShapeKind);
180 inline bool ArrayData::isVecArray() const { return kind() == kVecKind; }
181 inline bool ArrayData::isKeyset() const { return kind() == kKeysetKind; }
182 inline bool ArrayData::isShape() const { return kind() == kShapeKind; }
184 inline bool ArrayData::hasPackedLayout() const {
185 return isPacked() || isVecArray();
187 inline bool ArrayData::hasMixedLayout() const {
188 return isMixed() || isDict() || isShape();
191 inline bool ArrayData::isPHPArray() const {
192 return RuntimeOption::EvalHackArrDVArrs
193 ? kind() < kShapeKind
194 : kind() <= kShapeKind;
197 inline bool ArrayData::isHackArray() const {
198 return RuntimeOption::EvalHackArrDVArrs
199 ? kind() >= kShapeKind
200 : kind() >= kDictKind;
203 inline ArrayData::DVArray ArrayData::dvArray() const {
204 // The darray/varray state is stored in the lower 2-bits of m_aux16. The
205 // array is free to store whatever it wants in the upper 14-bits.
206 return static_cast<DVArray>(m_aux16 & kDVArrayMask);
209 inline void ArrayData::setDVArray(DVArray d) {
210 assertx(!RuntimeOption::EvalHackArrDVArrs || d == kNotDVArray);
211 assertx(!(d & ~kDVArrayMask));
212 m_aux16 = (m_aux16 & ~kDVArrayMask) | d;
215 inline bool ArrayData::isVArray() const { return dvArray() & kVArray; }
216 inline bool ArrayData::isDArray() const { return dvArray() & kDArray; }
218 inline bool ArrayData::isNotDVArray() const { return dvArray() == kNotDVArray; }
219 inline bool ArrayData::isVecOrVArray() const {
220 return RuntimeOption::EvalHackArrDVArrs ? isVecArray() : isVArray();
222 inline bool ArrayData::isDictOrDArray() const {
223 return RuntimeOption::EvalHackArrDVArrs ? isDict() : isDArray();
226 inline bool ArrayData::isDictOrDArrayOrShape() const {
227 return isShape() || isDictOrDArray();
230 // gcc doesn't optimize (a & 3) == (b & 3) very well; help it a little.
231 inline bool ArrayData::dvArrayEqual(const ArrayData* a, const ArrayData* b) {
232 return ((a->m_aux16 ^ b->m_aux16) & kDVArrayMask) == 0;
235 inline bool ArrayData::dvArraySanityCheck() const {
236 auto const dv = dvArray();
237 if (!RuntimeOption::EvalHackArrDVArrs) {
238 if (isPacked()) return !(dv & kDArray);
239 if (isMixed()) return !(dv & kVArray);
240 if (isShape()) return dv == kDArray;
242 return dv == kNotDVArray;
245 inline bool ArrayData::hasApcTv() const { return m_aux16 & kHasApcTv; }
247 inline bool ArrayData::isLegacyArray() const { return m_aux16 & kLegacyArray; }
249 inline void ArrayData::setLegacyArray(bool legacy) {
250 assertx(!legacy || kind() == kDictKind || kind() == kVecKind);
251 m_aux16 = (m_aux16 & ~kLegacyArray) | (legacy ? kLegacyArray : 0);
254 inline uint8_t ArrayData::auxBits() const {
255 return dvArray() | (isLegacyArray() ? kLegacyArray : 0);
258 inline bool ArrayData::useWeakKeys() const { return isPHPArray(); }
260 inline DataType ArrayData::toDataType() const {
261 auto const k = kind();
262 if (k < kShapeKind) return KindOfArray;
263 if (k == kVecKind) return KindOfVec;
264 if (k == kDictKind) return KindOfDict;
265 if (k == kShapeKind) return KindOfShape;
266 assertx(k == kKeysetKind);
267 return KindOfKeyset;
270 inline DataType ArrayData::toPersistentDataType() const {
271 auto const k = kind();
272 if (k < kShapeKind) return KindOfPersistentArray;
273 if (k == kVecKind) return KindOfPersistentVec;
274 if (k == kDictKind) return KindOfPersistentDict;
275 if (k == kShapeKind) return KindOfPersistentShape;
276 assertx(k == kKeysetKind);
277 return KindOfPersistentKeyset;
280 ///////////////////////////////////////////////////////////////////////////////
281 // Iteration.
283 inline int32_t ArrayData::getPosition() const {
284 return m_pos;
287 inline void ArrayData::setPosition(int32_t p) {
288 assertx(m_pos == p || !isStatic());
289 m_pos = p;
292 inline bool ArrayData::isHead() const {
293 return m_pos == iter_begin();
296 inline bool ArrayData::isTail() const {
297 return m_pos == iter_last();
300 inline bool ArrayData::isInvalid() const {
301 return m_pos == iter_end();
304 ///////////////////////////////////////////////////////////////////////////////
306 inline bool ArrayData::IsValidKey(const StringData* k) {
307 return k;
310 ///////////////////////////////////////////////////////////////////////////////
312 ALWAYS_INLINE
313 bool ArrayData::hasProvenanceData() const {
314 return m_aux16 & kHasProvenanceData;
317 ALWAYS_INLINE
318 void ArrayData::markHasProvenanceData() {
319 m_aux16 |= kHasProvenanceData;
322 ///////////////////////////////////////////////////////////////////////////////
324 ALWAYS_INLINE void decRefArr(ArrayData* arr) {
325 arr->decRefAndRelease();
328 ///////////////////////////////////////////////////////////////////////////////
330 ALWAYS_INLINE bool checkHACRefBind() {
331 return RuntimeOption::EvalHackArrCompatNotices &&
332 RuntimeOption::EvalHackArrCompatCheckRefBind;
334 ALWAYS_INLINE bool checkHACFalseyPromote() {
335 return RuntimeOption::EvalHackArrCompatNotices &&
336 RuntimeOption::EvalHackArrCompatCheckFalseyPromote;
338 ALWAYS_INLINE bool checkHACEmptyStringPromote() {
339 return RuntimeOption::EvalHackArrCompatNotices &&
340 RuntimeOption::EvalHackArrCompatCheckEmptyStringPromote;
342 ALWAYS_INLINE bool checkHACCompare() {
343 return RuntimeOption::EvalHackArrCompatNotices &&
344 RuntimeOption::EvalHackArrCompatCheckCompare;
346 ALWAYS_INLINE bool checkHACArrayPlus() {
347 return RuntimeOption::EvalHackArrCompatNotices &&
348 RuntimeOption::EvalHackArrCompatCheckArrayPlus;
350 ALWAYS_INLINE bool checkHACArrayKeyCast() {
351 return RuntimeOption::EvalHackArrCompatNotices &&
352 RuntimeOption::EvalHackArrCompatCheckArrayKeyCast;
355 ///////////////////////////////////////////////////////////////////////////////