track total size of static array and Unit/Class/Func
[hiphop-php.git] / hphp / runtime / base / req-root.h
blob8a4e508287785c5f1543c79810857c40f72ba291
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_REQ_ROOT_H_
18 #define incl_HPHP_REQ_ROOT_H_
20 #include "hphp/runtime/base/typed-value.h"
21 #include "hphp/runtime/base/runtime-option.h"
22 #include <utility>
24 namespace HPHP { namespace req {
27 * An explicitly-tracked root, registered on construction and de-registered
28 * on destruction. Subclasses of this implement tyindex() and detach() methods
29 * so instances can be scanned as needed.
30 * Warning: this extra tracking is expensive, and only necessary when
31 * creating and destroying heap pointers in areas not already known
32 * as roots (thread locals, stack, rds, ExecutionContext, etc).
34 struct root_handle {
35 static constexpr uint32_t INVALID = ~0;
37 root_handle(uint16_t size, type_scan::Index tyindex)
38 : m_id(addRootHandle()), m_size(size), m_tyindex(tyindex)
41 // move construction takes over the old handle's id.
42 root_handle(root_handle&& h) noexcept
43 : m_id(h.m_id != INVALID ? stealRootHandle(&h) : INVALID)
44 , m_size(h.m_size)
45 , m_tyindex(h.m_tyindex)
48 // move-assignment poaches the old handle's id if necessary.
49 root_handle& operator=(root_handle&& h) {
50 if (m_id == INVALID) m_id = stealRootHandle(&h);
51 return *this;
54 // root_handles must all be unique; remove copy-construct and copy-assign
55 root_handle(const root_handle&) = delete;
56 root_handle& operator=(const root_handle&) = delete;
58 virtual ~root_handle() {
59 if (m_id != INVALID) delRootHandle();
62 void invalidate() {
63 m_id = INVALID;
64 detach();
66 virtual void scan(type_scan::Scanner&) const = 0;
67 virtual void detach() = 0;
69 template<class Fn> void iterate(Fn fn) const {
70 fn(this, m_size, m_tyindex);
72 private:
73 uint32_t addRootHandle();
74 uint32_t stealRootHandle(root_handle*);
75 void delRootHandle();
76 private:
77 uint32_t m_id;
78 protected:
79 const uint16_t m_size;
80 const type_scan::Index m_tyindex;
83 // e.g. req::root<Array>, req::root<Variant>
84 template<class T>
85 struct root : T, root_handle {
86 root() : T(),
87 root_handle(sizeof(root<T>), type_scan::getIndexForScan<root<T>>())
89 static_assert(sizeof(root<T>) <= 0xffff, "");
92 // copy constructor
93 root(const root<T>& r)
94 : T(static_cast<const T&>(r)),
95 root_handle(sizeof(root<T>), type_scan::getIndexForScan<root<T>>())
97 static_assert(sizeof(root<T>) <= 0xffff, "");
100 // conversion constructor
101 template<class S> /* implicit */ root(const S& s)
102 : T(s),
103 root_handle(sizeof(root<T>), type_scan::getIndexForScan<root<T>>())
105 static_assert(sizeof(root<T>) <= 0xffff, "");
108 // copy assign
109 root<T>& operator=(const root<T>& r) {
110 T::operator=(static_cast<const T&>(r));
111 return *this;
114 // converting assign from any type only deals with T
115 template<class S> root<T>& operator=(const S& s) {
116 T::operator=(s);
117 return *this;
120 // move ctors
121 root(root<T>&& r) noexcept
122 : T(std::move(r)), root_handle(std::move(r))
124 /* implicit */ root(T&& t) noexcept
125 : T(std::move(t)),
126 root_handle(sizeof(root<T>), type_scan::getIndexForScan<root<T>>())
129 // move assign
130 root<T>& operator=(root<T>&& r) {
131 T::operator=(std::move(static_cast<T&&>(r)));
132 root_handle::operator=(std::move(r));
133 return *this;
135 root<T>& operator=(T&& t) {
136 T::operator=(std::move(t));
137 return *this;
140 // implement root_handle
141 void scan(type_scan::Scanner&) const override;
142 void detach() override;
145 template<> void root<TypedValue>::scan(type_scan::Scanner&) const;
146 template<> void root<TypedValue>::detach();
149 #endif