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_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"
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
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.
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
);
65 * Deallocate a RefData.
67 void release() noexcept
{
68 assert(kindIsValid());
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());
88 assert(kindIsValid());
92 const Variant
* var() const {
93 return reinterpret_cast<const Variant
*>(tv());
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());
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
)) {
115 m_tv
.m_data
.num
= datum
;
117 m_tv
.m_type
= KindOfNull
;
125 ALWAYS_INLINE
void decRefRef(RefData
* ref
) {
126 ref
->decRefAndRelease();
131 #endif //incl_HPHP_REF_DATA_H