1
- #include < chrono>
2
- #include < condition_variable>
3
- #include < format>
4
- #include < functional>
5
- #include < memory>
6
- #include < mutex>
7
- #include < ranges>
8
1
#include < setjmp.h>
9
- #include < tuple>
10
- #include < unordered_map>
11
- #include < utility>
12
- #include < vcruntime.h>
13
2
14
3
#include " MemoryManager.hpp"
15
4
16
5
#ifdef _WIN32
17
- #include < stdio.h>
18
- #include < tchar.h>
6
+
19
7
#include < windows.h>
20
- #include < winuser.h>
21
8
22
9
#include < processthreadsapi.h>
23
10
@@ -40,7 +27,6 @@ namespace sd
40
27
{
41
28
namespace
42
29
{
43
- const std::thread::id MAIN_THREAD_ID = std::this_thread::get_id();
44
30
45
31
// #define __READ_RBP() __asm__ volatile("movq %%rbp, %0" : "=r"(__rbp))
46
32
#define __READ_RSP (rsp ) __asm__ volatile (" movq %%rsp, %0" : " =r" (rsp))
@@ -61,151 +47,137 @@ namespace sd
61
47
#endif
62
48
} // namespace
63
49
64
- class MemoryManagerImpl final : public IMemoryManagerImpl
50
+ void MemoryManager::ObjectsRegister::registerNew ( const Object &object)
65
51
{
66
- private:
67
- std::unordered_map< void *, ObjectMetadata> _objectsMetadata;
52
+ _objectsMap. insert ({object. getRawPtr (), object});
53
+ }
68
54
69
- size_t _memoryAllocated = 0 ;
70
- size_t _memoryLimit = 1 * 1024 * 1024 ; // ~1MB
55
+ bool MemoryManager::ObjectsRegister::contains (void *objectPtr) const { return _objectsMap.contains (objectPtr); }
71
56
72
- public:
73
- ~MemoryManagerImpl ()
74
- {
75
- // cleanup if running in local threads
76
- if (std::this_thread::get_id () != MAIN_THREAD_ID)
77
- {
78
- clear ();
79
- }
80
- }
57
+ MemoryManager::Object &MemoryManager::ObjectsRegister::getObject (void *objectPtr)
58
+ {
59
+ return _objectsMap.at (objectPtr);
60
+ }
81
61
82
- void clear ()
83
- {
84
- for (auto &item : _objectsMetadata)
85
- {
86
- auto &[ptr, meta] = item;
87
- auto deleter = meta.typeInfo ->deleter ;
88
- (*deleter)(ptr); // (2)
89
- }
90
- }
62
+ void MemoryManager::ObjectsRegister::clear () { return _objectsMap.clear (); }
91
63
92
- size_t garbageCollect () final
93
- {
94
- auto snapshot = _memoryAllocated;
95
- mark ();
96
- sweep ();
97
- return snapshot - _memoryAllocated;
98
- }
64
+ size_t MemoryManager::ObjectsRegister::numberOfRegisteredObjects () const { return _objectsMap.size (); }
65
+
66
+ bool MemoryManager::ObjectsRegister::anyObjectRegistered () const { return _objectsMap.empty (); }
67
+
68
+ MemoryManager &MemoryManager::instance ()
69
+ {
70
+ static thread_local MemoryManager ob;
71
+ return ob;
72
+ }
73
+
74
+ MemoryManager::~MemoryManager () { clear (); }
75
+
76
+ size_t MemoryManager::garbageCollect ()
77
+ {
78
+ auto snapshot = getAllocatedMemory ();
79
+ mark ();
80
+ sweep ();
81
+ auto freedBytes = snapshot - getAllocatedMemory ();
82
+ return freedBytes;
83
+ }
84
+
85
+ size_t MemoryManager::getAllocatedMemory () const { return _allocatedMemory; }
86
+
87
+ size_t MemoryManager::getMemoryLimit () const { return _memoryLimit; }
88
+
89
+ void MemoryManager::bumpMemoryLimit () { _memoryLimit *= 2 ; }
90
+
91
+ void MemoryManager::clear ()
92
+ {
93
+ _register.forEach ([this ](auto &object) { destroy (object); });
94
+ _register.clear ();
95
+ }
96
+
97
+ void MemoryManager::destroy (Object &object)
98
+ {
99
+ auto size = object.getSize ();
100
+ object.destroy ();
101
+ _allocatedMemory -= size;
102
+ }
103
+
104
+ bool MemoryManager::isGBCollectionNeeded () { return getAllocatedMemory () > getMemoryLimit (); }
105
+
106
+ void MemoryManager::mark ()
107
+ {
108
+ auto worklist = getRoots ();
99
109
100
- void registerObject ( void *object, const TypeInfo *typeInfo) final
110
+ while (!worklist. empty ())
101
111
{
102
- _memoryAllocated += typeInfo->size ;
103
- _objectsMetadata[object] = {.marked = false , .typeInfo = typeInfo};
104
- if (!isGBCollectionNeeded ())
112
+ auto ptr = worklist.back ();
113
+ worklist.pop_back ();
114
+ auto &object = _register.getObject (ptr);
115
+
116
+ if (object.isMarked ())
105
117
{
106
- return ;
118
+ continue ;
107
119
}
108
- auto freedBytes = garbageCollect ();
109
- if (!freedBytes )
120
+ object. mark ();
121
+ for ( const auto &p : getInnerObjects (object) )
110
122
{
111
- _memoryLimit *= 2 ;
123
+ worklist. push_back (p) ;
112
124
}
113
125
}
126
+ }
114
127
115
- private:
116
- bool isGBCollectionNeeded () { return _memoryAllocated > _memoryLimit; }
117
-
118
- void mark ()
119
- {
120
- auto worklist = getRoots ();
121
-
122
- while (!worklist.empty ())
128
+ void MemoryManager::sweep ()
129
+ {
130
+ _register.unregisterIf ([this ](auto &object) {
131
+ if (object.isMarked ())
123
132
{
124
- auto o = worklist.back ();
125
- worklist.pop_back ();
126
- auto &meta = getObjectMetadata (o);
127
-
128
- if (meta.marked )
129
- {
130
- continue ;
131
- }
132
- meta.marked = true ;
133
- for (const auto &p : getInnerObjects (o))
134
- {
135
- worklist.push_back (p);
136
- }
133
+ object.unmark ();
134
+ return false ;
137
135
}
138
- }
139
-
140
- void sweep ()
141
- {
142
- std::erase_if (_objectsMetadata, [this ](auto &item) {
143
- auto &[ptr, meta] = item;
144
- if (meta.marked )
145
- {
146
- meta.marked = false ;
147
- return false ;
148
- }
149
- else
150
- {
151
- auto deleter = meta.typeInfo ->deleter ;
152
- (*deleter)(ptr); // (2)
153
- _memoryAllocated -= meta.typeInfo ->size ;
154
- return true ;
155
- }
156
- });
157
- }
158
-
159
- ObjectMetadata &getObjectMetadata (void *object) { return _objectsMetadata.at (object); }
136
+ else
137
+ {
138
+ destroy (object);
139
+ return true ;
140
+ }
141
+ });
142
+ }
160
143
161
- std::vector<void *> getRoots ()
162
- {
144
+ std::vector<void *> MemoryManager:: getRoots ()
145
+ {
163
146
164
- // push local variables stored in registers onto the stack.
165
- jmp_buf jb;
166
- setjmp (jb);
147
+ // push local variables stored in registers onto the stack.
148
+ jmp_buf jb;
149
+ setjmp (jb);
167
150
168
- auto [top, bot, rsp] = getStackBounds ();
151
+ auto [top, bot, rsp] = getStackBounds ();
169
152
170
- std::vector<void *> result;
171
- while (rsp < top)
153
+ std::vector<void *> result;
154
+ while (rsp < top)
155
+ {
156
+ auto address = (void *)*reinterpret_cast <void **>(rsp);
157
+ if (_register.contains (address))
172
158
{
173
- auto address = (void *)*reinterpret_cast <void **>(rsp);
174
- if (_objectsMetadata.contains (address))
175
- {
176
- result.emplace_back (address);
177
- }
178
- rsp++;
159
+ result.emplace_back (address);
179
160
}
180
-
181
- return result;
161
+ rsp++;
182
162
}
183
163
184
- std::vector<void *> getInnerObjects (void *object)
164
+ return result;
165
+ }
166
+
167
+ std::vector<void *> MemoryManager::getInnerObjects (const Object &object)
168
+ {
169
+ auto p = (uint8_t *)object.getRawPtr ();
170
+ auto end = (p + object.getSize ());
171
+ std::vector<void *> result;
172
+ while (p < end)
185
173
{
186
- auto p = (uint8_t *)object;
187
- auto end = (p + getObjectMetadata (object).typeInfo ->size );
188
- std::vector<void *> result;
189
- while (p < end)
174
+ auto address = (void *)*reinterpret_cast <void **>(p);
175
+ if (_register.contains (address))
190
176
{
191
- auto address = (void *)*reinterpret_cast <void **>(p);
192
- if (_objectsMetadata.contains (address))
193
- {
194
- result.emplace_back (address);
195
- }
196
- p++;
177
+ result.emplace_back (address);
197
178
}
198
- return result ;
179
+ p++ ;
199
180
}
200
- };
201
-
202
- MemoryManager &MemoryManager::instance ()
203
- {
204
- static thread_local MemoryManager ob{std::make_unique<MemoryManagerImpl>()};
205
- return ob;
181
+ return result;
206
182
}
207
-
208
- MemoryManager::MemoryManager (std::unique_ptr<IMemoryManagerImpl> impl) : _impl(std::move(impl)) {}
209
-
210
- size_t MemoryManager::garbageCollect () { return _impl->garbageCollect (); }
211
183
} // namespace sd
0 commit comments