Add sub-controls for Hack array compat runtime checks
[hiphop-php.git] / hphp / runtime / base / ref-data.h
blob1e23412bf5d27619ef87a88aca84d477a3899188
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 #ifndef incl_HPHP_REF_DATA_H
18 #define incl_HPHP_REF_DATA_H
20 #include "hphp/runtime/base/countable.h"
21 #include "hphp/runtime/base/memory-manager.h"
22 #include "hphp/runtime/base/member-val.h"
23 #include "hphp/runtime/base/typed-value.h"
25 namespace HPHP {
27 struct Variant;
30 * We heap allocate a RefData when we make a reference to something.
31 * A Variant or TypedValue can be KindOfRef and point to a RefData,
32 * but the value held here must not be KindOfRef.
34 * RefData's are also used to implement static locals, but in this
35 * case the RefData itself is allocated in RDS rather than on
36 * the heap. Note that generally speaking a RefData should never
37 * contain KindOfUninit, *except* uninitialized RefDatas for this
38 * RDS case.
40 struct RefData final : Countable, type_scan::MarkScannableCollectable<RefData> {
42 * Some RefData's (static locals) are allocated in RDS, and
43 * live until the end of the request. In this case, we start with a
44 * reference count to keep it alive.
46 * Note that the JIT accesses RDS RefDatas directly---if you need to
47 * change how initialization works it keep that up to date.
49 void initInRDS() {
50 // count=OneReference
51 initHeader_16(HeaderKind::Ref, OneReference, 0);
55 * Create a RefData, allocated in the request local heap.
57 static RefData* Make(TypedValue tv) {
58 return new (tl_heap->objMalloc(sizeof(RefData)))
59 RefData(tv.m_type, tv.m_data.num);
62 ~RefData();
65 * Deallocate a RefData.
67 void release() noexcept {
68 assert(kindIsValid());
69 this->~RefData();
70 tl_heap->objFree(this, sizeof(RefData));
71 AARCH64_WALKABLE_FRAME();
74 ALWAYS_INLINE void decRefAndRelease() {
75 assert(kindIsValid());
76 if (decReleaseCheck()) release();
78 bool kindIsValid() const { return m_kind == HeaderKind::Ref; }
81 * Note, despite the name, this can never return a non-Cell.
83 const Cell* tv() const {
84 assert(kindIsValid());
85 return &m_tv;
87 Cell* tv() {
88 assert(kindIsValid());
89 return &m_tv;
92 const Variant* var() const {
93 return reinterpret_cast<const Variant*>(tv());
95 Variant* var() {
96 return reinterpret_cast<Variant*>(tv());
99 static constexpr int tvOffset() { return offsetof(RefData, m_tv); }
101 void assertValid() const { assert(kindIsValid()); }
103 bool isReferenced() const {
104 assert(kindIsValid());
105 return m_count >= 2;
108 private:
109 RefData(DataType t, int64_t datum) {
110 // Initialize this value by laundering uninitNull -> Null.
111 // count=OneReference
112 initHeader_16(HeaderKind::Ref, OneReference, 0);
113 if (!isNullType(t)) {
114 m_tv.m_type = t;
115 m_tv.m_data.num = datum;
116 } else {
117 m_tv.m_type = KindOfNull;
121 private:
122 TypedValue m_tv;
125 ALWAYS_INLINE void decRefRef(RefData* ref) {
126 ref->decRefAndRelease();
129 } // namespace HPHP
131 #endif //incl_HPHP_REF_DATA_H