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 +----------------------------------------------------------------------+
16 #ifndef _incl_HPHP_RUNTIME_VM_NATIVE_DATA_H
17 #define _incl_HPHP_RUNTIME_VM_NATIVE_DATA_H
19 #include "hphp/runtime/base/memory-manager.h"
20 #include "hphp/runtime/base/typed-value.h"
21 #include "hphp/runtime/base/type-object.h"
23 #include <type_traits>
25 namespace HPHP
{ namespace Native
{
26 //////////////////////////////////////////////////////////////////////////////
29 struct NativeDataInfo
{
30 typedef void (*InitFunc
)(ObjectData
*obj
);
31 typedef void (*CopyFunc
)(ObjectData
*dest
, ObjectData
*src
);
32 typedef void (*DestroyFunc
)(ObjectData
*obj
);
33 typedef void (*SweepFunc
)(ObjectData
*sweep
);
34 typedef Variant (*SleepFunc
)(const ObjectData
*sleep
);
35 typedef void (*WakeupFunc
)(ObjectData
*wakeup
, const Variant
& data
);
39 type_scan::Index tyindex
;
40 InitFunc init
; // new Object
41 CopyFunc copy
; // clone $obj
42 DestroyFunc destroy
; // unset($obj)
43 SweepFunc sweep
; // sweep $obj
44 SleepFunc sleep
; // serialize($obj)
45 WakeupFunc wakeup
; // unserialize($obj)
47 bool isSerializable() const {
48 return sleep
!= nullptr && wakeup
!= nullptr;
52 NativeDataInfo
* getNativeDataInfo(const StringData
* name
);
53 NativeNode
* getNativeNode(ObjectData
*, const NativeDataInfo
*);
54 const NativeNode
* getNativeNode(const ObjectData
*, const NativeDataInfo
*);
57 T
* data(ObjectData
*obj
) {
58 return reinterpret_cast<T
*>(obj
) - 1;
62 const T
* data(const ObjectData
*obj
) {
63 return reinterpret_cast<const T
*>(obj
) - 1;
67 T
* data(Object
& obj
) {
68 return data
<T
>(obj
.get());
72 T
* data(const Object
& obj
) {
73 return data
<T
>(obj
.get());
77 constexpr ptrdiff_t dataOffset() {
82 ObjectData
* object(T
*data
) {
83 return reinterpret_cast<ObjectData
*>(data
+ 1);
86 void registerNativeDataInfo(const StringData
* name
,
88 NativeDataInfo::InitFunc init
,
89 NativeDataInfo::CopyFunc copy
,
90 NativeDataInfo::DestroyFunc destroy
,
91 NativeDataInfo::SweepFunc sweep
,
92 NativeDataInfo::SleepFunc sleep
,
93 NativeDataInfo::WakeupFunc wakeup
,
94 type_scan::Index tyindex
);
97 void nativeDataInfoInit(ObjectData
* obj
) {
102 typename
std::enable_if
<std::is_assignable
<T
,T
>::value
,
103 void>::type
nativeDataInfoCopy(ObjectData
* dest
, ObjectData
* src
) {
104 *data
<T
>(dest
) = *data
<T
>(src
);
107 // Dummy copy method for classes where the assignment has been deleted
109 typename
std::enable_if
<!std::is_assignable
<T
,T
>::value
,
110 void>::type
nativeDataInfoCopy(ObjectData
* dest
, ObjectData
* src
) {}
113 void nativeDataInfoDestroy(ObjectData
* obj
) {
118 typename
std::enable_if
<!std::is_trivially_destructible
<T
>::value
,
119 void(*)(ObjectData
*)>::type
120 getNativeDataInfoDestroy() {
121 return &nativeDataInfoDestroy
<T
>;
125 typename
std::enable_if
<std::is_trivially_destructible
<T
>::value
,
126 void(*)(ObjectData
*)>::type
127 getNativeDataInfoDestroy() {
131 // If the NDI class has a void sweep() method,
132 // call it during sweep, otherwise call ~T()
133 // unless its trivial, or the class defines a
135 // static const bool sweep = false;
136 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(hasSweep
, sweep
);
138 // class to test for presence of a sweep set to false
139 template <typename T
>
141 template <typename C
>
142 constexpr static typename
std::enable_if
<C::sweep
== false, bool>::type
143 test(void*) { return false; }
145 constexpr static bool test(...) { return true; }
146 constexpr static bool value
= test
<T
>(nullptr);
150 void callSweep(ObjectData
* obj
) {
151 data
<T
>(obj
)->sweep();
155 typename
std::enable_if
<hasSweep
<T
,void ()>::value
,
156 void(*)(ObjectData
*)>::type
157 getNativeDataInfoSweep() {
158 return &callSweep
<T
>;
162 typename
std::enable_if
<(!hasSweep
<T
,void ()>::value
&&
163 !std::is_trivially_destructible
<T
>::value
&&
165 void(*)(ObjectData
*)>::type
166 getNativeDataInfoSweep() {
167 return &nativeDataInfoDestroy
<T
>;
171 typename
std::enable_if
<(!hasSweep
<T
,void ()>::value
&&
172 (std::is_trivially_destructible
<T
>::value
||
173 !doSweep
<T
>::value
)),
174 void(*)(ObjectData
*)>::type
175 getNativeDataInfoSweep() {
179 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(hasSleep
, sleep
);
182 typename
std::enable_if
<hasSleep
<T
, Variant() const>::value
,
183 Variant
>::type
nativeDataInfoSleep(const ObjectData
* obj
) {
184 return data
<T
>(obj
)->sleep();
188 typename
std::enable_if
<!hasSleep
<T
, Variant() const>::value
,
189 Variant
>::type
nativeDataInfoSleep(const ObjectData
* obj
) {
193 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(hasWakeup
, wakeup
);
196 typename
std::enable_if
<hasWakeup
<T
, void(const Variant
&, ObjectData
*)>::value
,
197 void>::type
nativeDataInfoWakeup(ObjectData
* obj
, const Variant
& content
) {
198 data
<T
>(obj
)->wakeup(content
, obj
);
202 typename
std::enable_if
<!hasWakeup
<T
, void(const Variant
&, ObjectData
*)>::value
,
203 void>::type
nativeDataInfoWakeup(ObjectData
* obj
, const Variant
& content
) {
209 // Skipping the ctor/dtor is generally a bad idea
210 // since memory props won't get setup/torn-down
216 type_scan::Index
nativeTyindex() {
217 // get the gc scanner type-id for T. getIndexForMalloc<T> provides
218 // a scanner for T and causes pointer fields of type T* to be scanned.
219 return type_scan::getIndexForMalloc
<T
>();
222 // NativeData's should not extend sweepable, to sweep a native data define
223 // a sweep() function and register the NativeData without the NO_SWEEP flag.
225 typename
std::enable_if
<
226 !std::is_base_of
<Sweepable
, T
>::value
,
228 >::type
registerNativeDataInfo(const StringData
* name
,
230 auto ndic
= &nativeDataInfoCopy
<T
>;
231 auto ndisw
= getNativeDataInfoSweep
<T
>();
232 auto ndisl
= &nativeDataInfoSleep
<T
>;
233 auto ndiw
= &nativeDataInfoWakeup
<T
>;
235 registerNativeDataInfo(
237 &nativeDataInfoInit
<T
>,
238 (flags
& NDIFlags::NO_COPY
) ? nullptr : ndic
,
239 getNativeDataInfoDestroy
<T
>(),
240 (flags
& NDIFlags::NO_SWEEP
) ? nullptr : ndisw
,
241 hasSleep
<T
, Variant() const>::value
? ndisl
: nullptr,
242 hasWakeup
<T
, void(const Variant
&, ObjectData
*)>::value
? ndiw
: nullptr,
246 // Return the ObjectData payload allocated after this NativeNode header
247 inline ObjectData
* obj(NativeNode
* node
) {
248 return reinterpret_cast<ObjectData
*>(
249 reinterpret_cast<char*>(node
) + node
->obj_offset
253 // Return the ObjectData payload allocated after this NativeNode header
254 inline const ObjectData
* obj(const NativeNode
* node
) {
255 return reinterpret_cast<const ObjectData
*>(
256 reinterpret_cast<const char*>(node
) + node
->obj_offset
260 ObjectData
* nativeDataInstanceCtor(Class
* cls
);
261 void nativeDataInstanceCopy(ObjectData
* dest
, ObjectData
*src
);
262 void nativeDataInstanceDtor(ObjectData
* obj
, const Class
* cls
);
264 Variant
nativeDataSleep(const ObjectData
* obj
);
265 void nativeDataWakeup(ObjectData
* obj
, const Variant
& data
);
267 size_t ndsize(const ObjectData
* obj
, const NativeDataInfo
* ndi
);
269 // return the full native header size, which is also the distance from
270 // the allocated pointer to the ObjectData*.
271 inline size_t ndsize(size_t dataSize
) {
272 return alignTypedValue(dataSize
+ sizeof(NativeNode
));
275 inline size_t ndextra(const ObjectData
* obj
, const NativeDataInfo
* ndi
) {
276 return ndsize(obj
, ndi
) - ndsize(ndi
->sz
);
279 inline NativeNode
* getNativeNode(ObjectData
* obj
, const NativeDataInfo
* ndi
) {
280 return reinterpret_cast<NativeNode
*>(
281 reinterpret_cast<char*>(obj
) - ndsize(obj
, ndi
)
285 inline const NativeNode
*
286 getNativeNode(const ObjectData
* obj
, const NativeDataInfo
* ndi
) {
287 return reinterpret_cast<const NativeNode
*>(
288 reinterpret_cast<const char*>(obj
) - ndsize(obj
, ndi
)
292 //////////////////////////////////////////////////////////////////////////////
293 }} // namespace HPHP::Native
295 #endif // _incl_HPHP_RUNTIME_VM_NATIVE_DATA_H