codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / vm / native-data.h
blob6d463bef0862fd5391c5869a9b5ffdd23cce94f0
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 +----------------------------------------------------------------------+
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 //////////////////////////////////////////////////////////////////////////////
27 // Class NativeData
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);
37 size_t sz;
38 uint16_t odattrs;
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*);
56 template<class T>
57 T* data(ObjectData *obj) {
58 return reinterpret_cast<T*>(obj) - 1;
61 template<class T>
62 const T* data(const ObjectData *obj) {
63 return reinterpret_cast<const T*>(obj) - 1;
66 template <class T>
67 T* data(Object& obj) {
68 return data<T>(obj.get());
71 template <class T>
72 T* data(const Object& obj) {
73 return data<T>(obj.get());
76 template<class T>
77 constexpr ptrdiff_t dataOffset() {
78 return -sizeof(T);
81 template<class T>
82 ObjectData* object(T *data) {
83 return reinterpret_cast<ObjectData*>(data + 1);
86 void registerNativeDataInfo(const StringData* name,
87 size_t sz,
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);
96 template<class T>
97 void nativeDataInfoInit(ObjectData* obj) {
98 new (data<T>(obj)) T;
101 template<class T>
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
108 template<class T>
109 typename std::enable_if<!std::is_assignable<T,T>::value,
110 void>::type nativeDataInfoCopy(ObjectData* dest, ObjectData* src) {}
112 template<class T>
113 void nativeDataInfoDestroy(ObjectData* obj) {
114 data<T>(obj)->~T();
117 template<class T>
118 typename std::enable_if<!std::is_trivially_destructible<T>::value,
119 void(*)(ObjectData*)>::type
120 getNativeDataInfoDestroy() {
121 return &nativeDataInfoDestroy<T>;
124 template<class T>
125 typename std::enable_if<std::is_trivially_destructible<T>::value,
126 void(*)(ObjectData*)>::type
127 getNativeDataInfoDestroy() {
128 return nullptr;
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>
140 struct doSweep {
141 template <typename C>
142 constexpr static typename std::enable_if<C::sweep == false, bool>::type
143 test(void*) { return false; }
144 template <typename>
145 constexpr static bool test(...) { return true; }
146 constexpr static bool value = test<T>(nullptr);
149 template<class T>
150 void callSweep(ObjectData* obj) {
151 data<T>(obj)->sweep();
154 template<class T>
155 typename std::enable_if<hasSweep<T,void ()>::value,
156 void(*)(ObjectData*)>::type
157 getNativeDataInfoSweep() {
158 return &callSweep<T>;
161 template<class T>
162 typename std::enable_if<(!hasSweep<T,void ()>::value &&
163 !std::is_trivially_destructible<T>::value &&
164 doSweep<T>::value),
165 void(*)(ObjectData*)>::type
166 getNativeDataInfoSweep() {
167 return &nativeDataInfoDestroy<T>;
170 template<class 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() {
176 return nullptr;
179 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(hasSleep, sleep);
181 template<class T>
182 typename std::enable_if<hasSleep<T, Variant() const>::value,
183 Variant>::type nativeDataInfoSleep(const ObjectData* obj) {
184 return data<T>(obj)->sleep();
187 template<class T>
188 typename std::enable_if<!hasSleep<T, Variant() const>::value,
189 Variant>::type nativeDataInfoSleep(const ObjectData* obj) {
190 always_assert(0);
193 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(hasWakeup, wakeup);
195 template<class T>
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);
201 template<class T>
202 typename std::enable_if<!hasWakeup<T, void(const Variant&, ObjectData*)>::value,
203 void>::type nativeDataInfoWakeup(ObjectData* obj, const Variant& content) {
204 always_assert(0);
207 enum NDIFlags {
208 NONE = 0,
209 // Skipping the ctor/dtor is generally a bad idea
210 // since memory props won't get setup/torn-down
211 NO_COPY = (1<<0),
212 NO_SWEEP = (1<<1),
215 template<class T>
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.
224 template<class T>
225 typename std::enable_if<
226 !std::is_base_of<Sweepable, T>::value,
227 void
228 >::type registerNativeDataInfo(const StringData* name,
229 int64_t flags = 0) {
230 auto ndic = &nativeDataInfoCopy<T>;
231 auto ndisw = getNativeDataInfoSweep<T>();
232 auto ndisl = &nativeDataInfoSleep<T>;
233 auto ndiw = &nativeDataInfoWakeup<T>;
235 registerNativeDataInfo(
236 name, sizeof(T),
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,
243 nativeTyindex<T>());
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