Heap Tracer
[hiphop-php.git] / hphp / runtime / vm / native-data.cpp
blob54168cddc494323511ddaf3a36491a994e1711b2
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 #include "hphp/runtime/vm/native-data.h"
19 #include "hphp/runtime/base/memory-manager.h"
20 #include "hphp/runtime/base/type-variant.h"
21 #include "hphp/runtime/vm/class.h"
23 namespace HPHP { namespace Native {
24 //////////////////////////////////////////////////////////////////////////////
26 typedef std::unordered_map<const StringData*,NativeDataInfo> NativeDataInfoMap;
27 static NativeDataInfoMap s_nativedatainfo;
29 void registerNativeDataInfo(const StringData* name,
30 size_t sz,
31 NativeDataInfo::InitFunc init,
32 NativeDataInfo::CopyFunc copy,
33 NativeDataInfo::DestroyFunc destroy,
34 NativeDataInfo::SweepFunc sweep,
35 NativeDataInfo::SleepFunc sleep,
36 NativeDataInfo::WakeupFunc wakeup) {
37 assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
38 assert((sleep == nullptr && wakeup == nullptr) ||
39 (sleep != nullptr && wakeup != nullptr));
40 NativeDataInfo info;
41 info.sz = sz;
42 info.odattrs = ObjectData::Attribute::HasNativeData;
43 info.init = init;
44 info.copy = copy;
45 info.destroy = destroy;
46 info.sweep = sweep;
47 info.sleep = sleep;
48 info.wakeup = wakeup;
49 s_nativedatainfo[name] = info;
52 NativeDataInfo* getNativeDataInfo(const StringData* name) {
53 auto it = s_nativedatainfo.find(name);
54 if (it == s_nativedatainfo.end()) {
55 return nullptr;
57 return &it->second;
60 /* Classes with NativeData structs allocate extra memory prior
61 * to the ObjectData.
63 * [NativeNode][padding][NativeData][ObjectData](prop0)...(propN)
64 * /\
65 * ObjectData* points here
67 * padding is added by alignTypedValue(sizeof(NativeData)) to ensure
68 * that ObjectData* falls on a 16-aligned boundary. NativeData is
69 * sizeof(NativeData) (NativeDataInfo.sz) bytes for the custom struct.
70 * NativeNode is a link in the NativeData sweep list for this ND block
72 ObjectData* nativeDataInstanceCtor(Class* cls) {
73 Attr attrs = cls->attrs();
74 if (UNLIKELY(attrs &
75 (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) {
76 ObjectData::raiseAbstractClassError(cls);
78 if (cls->needInitialization()) {
79 cls->initialize();
81 auto ndi = cls->getNativeDataInfo();
82 size_t nativeDataSize = ndsize(ndi);
83 size_t nProps = cls->numDeclProperties();
84 size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize;
86 auto node = reinterpret_cast<NativeNode*>(
87 MM().objMallocLogged(size)
89 node->obj_offset = nativeDataSize;
90 node->kind = HeaderKind::Native;
91 auto obj = new (reinterpret_cast<char*>(node) + nativeDataSize)
92 ObjectData(cls);
93 obj->setAttribute(static_cast<ObjectData::Attribute>(ndi->odattrs));
94 if (ndi->init) {
95 ndi->init(obj);
97 if (ndi->sweep) {
98 MM().addNativeObject(node);
100 if (UNLIKELY(cls->callsCustomInstanceInit())) {
101 obj->callCustomInstanceInit();
103 if (UNLIKELY(cls->hasNativePropHandler())) {
104 obj->setAttribute(ObjectData::Attribute::HasNativePropHandler);
106 return obj;
109 void nativeDataInstanceCopy(ObjectData* dest, ObjectData *src) {
110 auto ndi = dest->getVMClass()->getNativeDataInfo();
111 if (!ndi) return;
112 assert(ndi == src->getVMClass()->getNativeDataInfo());
113 if (!ndi->copy) {
114 throw_not_implemented("NativeDataInfoCopy");
116 ndi->copy(dest, src);
117 // Already in the sweep list from init call, no need to add again
120 void nativeDataInstanceDtor(ObjectData* obj, const Class* cls) {
121 assert(!cls->preClass()->builtinObjSize());
122 assert(!cls->preClass()->builtinODOffset());
123 obj->~ObjectData();
125 auto const nProps = size_t{cls->numDeclProperties()};
126 auto prop = reinterpret_cast<TypedValue*>(obj + 1);
127 auto const stop = prop + nProps;
128 for (; prop != stop; ++prop) {
129 tvRefcountedDecRef(prop);
132 auto ndi = cls->getNativeDataInfo();
133 if (ndi->destroy) {
134 ndi->destroy(obj);
136 auto node = getNativeNode(obj, ndi);
137 if (ndi->sweep) {
138 MM().removeNativeObject(node);
141 size_t size = ObjectData::sizeForNProps(nProps) + ndsize(ndi);
142 if (LIKELY(size <= kMaxSmartSize)) {
143 return MM().smartFreeSizeLogged(node, size);
145 MM().smartFreeSizeBigLogged(node, size);
148 Variant nativeDataSleep(const ObjectData* obj) {
149 auto ndi = obj->getVMClass()->getNativeDataInfo();
150 assert(ndi);
151 assert(ndi->sleep);
152 return ndi->sleep(obj);
155 void nativeDataWakeup(ObjectData* obj, const Variant& data) {
156 auto ndi = obj->getVMClass()->getNativeDataInfo();
157 assert(ndi);
158 assert(ndi->wakeup);
159 ndi->wakeup(obj, data);
162 //////////////////////////////////////////////////////////////////////////////
163 }} // namespace HPHP::Native