track total size of static array and Unit/Class/Func
[hiphop-php.git] / hphp / runtime / base / weakref-data.cpp
blobb1a065f6b63ee24cdd57aa611e68ba5ed727747a
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 #include "hphp/runtime/base/weakref-data.h"
18 #include "hphp/runtime/base/string-hash-map.h"
19 #include "hphp/runtime/base/tv-refcount.h"
20 #include "hphp/runtime/base/type-object.h"
21 #include "hphp/runtime/base/type-variant.h"
22 #include "hphp/system/systemlib.h"
23 #include "hphp/util/rds-local.h"
25 namespace HPHP {
27 // Maps object ids to the WeakRefData associated to them.
28 using weakref_data_map = req::fast_map<uintptr_t, req::weak_ptr<WeakRefData>>;
29 RDS_LOCAL(weakref_data_map, s_weakref_data);
31 void weakref_cleanup() {
32 s_weakref_data.destroy();
35 void WeakRefData::invalidateWeakRef(uintptr_t ptr) {
36 auto weakmap = s_weakref_data.get();
37 auto map_entry = weakmap->find(ptr);
38 if (map_entry != weakmap->end()) {
39 map_entry->second.lock()->pointee = make_tv<KindOfUninit>();
40 weakmap->erase(map_entry);
44 req::shared_ptr<WeakRefData> WeakRefData::forObject(Object obj) {
45 req::shared_ptr<WeakRefData> wr_data;
47 auto weakmap = s_weakref_data.get();
49 auto map_entry = weakmap->find((uintptr_t)obj.get());
50 if (map_entry != weakmap->end()) {
51 wr_data = map_entry->second.lock();
52 } else {
53 wr_data = req::make_shared<WeakRefData>(make_tv<KindOfObject>(obj.get()));
55 obj->setWeakRefed();
56 req::weak_ptr<WeakRefData> weak_data = req::weak_ptr<WeakRefData>(wr_data);
57 auto const DEBUG_ONLY result = weakmap->emplace(
58 reinterpret_cast<uintptr_t>(obj.get()),
59 weak_data
61 // Failure. Key should be unique. We just checked.
62 assertx(result.second);
64 return wr_data;
67 WeakRefData::~WeakRefData() {
68 if (type(pointee) != KindOfUninit) {
69 s_weakref_data.get()->erase(reinterpret_cast<uintptr_t>(val(pointee).pobj));
73 /**
74 * The problem this logic tries to solve:
75 * - We have a weakref object that points to an object.
76 * - We use DecRefNZ to get the reference count of the object down to 0 but it
77 * hasn't been destructed or sweeped yet. But the GC could sweep it at any
78 * moment.
79 * - Some code now call valid() or get() which without the refcount check would
80 * return true or the object.
81 * - Because we know that if the sweep or destructor had run the pointer would
82 * have been cleaned up so if we have a pointer it is safe to look at the
83 * object.
84 * - So we look at the refcount of the object and make sure it is > 0.
86 bool WeakRefData::isValid() const {
87 auto const ty = type(pointee);
88 return LIKELY(isRefcountedType(ty))
89 ? tvGetCount(pointee) > 0
90 : ty != KindOfUninit;
93 } // namespace HPHP