Skip to content

Commit bfb56ee

Browse files
committed
code refactor, split respoisibilities
1 parent bed4bc6 commit bfb56ee

File tree

2 files changed

+243
-180
lines changed

2 files changed

+243
-180
lines changed

Source/Library/MemoryManager.cpp

Lines changed: 106 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,10 @@
1-
#include <chrono>
2-
#include <condition_variable>
3-
#include <format>
4-
#include <functional>
5-
#include <memory>
6-
#include <mutex>
7-
#include <ranges>
81
#include <setjmp.h>
9-
#include <tuple>
10-
#include <unordered_map>
11-
#include <utility>
12-
#include <vcruntime.h>
132

143
#include "MemoryManager.hpp"
154

165
#ifdef _WIN32
17-
#include <stdio.h>
18-
#include <tchar.h>
6+
197
#include <windows.h>
20-
#include <winuser.h>
218

229
#include <processthreadsapi.h>
2310

@@ -40,7 +27,6 @@ namespace sd
4027
{
4128
namespace
4229
{
43-
const std::thread::id MAIN_THREAD_ID = std::this_thread::get_id();
4430

4531
// #define __READ_RBP() __asm__ volatile("movq %%rbp, %0" : "=r"(__rbp))
4632
#define __READ_RSP(rsp) __asm__ volatile("movq %%rsp, %0" : "=r"(rsp))
@@ -61,151 +47,137 @@ namespace sd
6147
#endif
6248
} // namespace
6349

64-
class MemoryManagerImpl final : public IMemoryManagerImpl
50+
void MemoryManager::ObjectsRegister::registerNew(const Object &object)
6551
{
66-
private:
67-
std::unordered_map<void *, ObjectMetadata> _objectsMetadata;
52+
_objectsMap.insert({object.getRawPtr(), object});
53+
}
6854

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); }
7156

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+
}
8161

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(); }
9163

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();
99109

100-
void registerObject(void *object, const TypeInfo *typeInfo) final
110+
while (!worklist.empty())
101111
{
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())
105117
{
106-
return;
118+
continue;
107119
}
108-
auto freedBytes = garbageCollect();
109-
if (!freedBytes)
120+
object.mark();
121+
for (const auto &p : getInnerObjects(object))
110122
{
111-
_memoryLimit *= 2;
123+
worklist.push_back(p);
112124
}
113125
}
126+
}
114127

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())
123132
{
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;
137135
}
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+
}
160143

161-
std::vector<void *> getRoots()
162-
{
144+
std::vector<void *> MemoryManager::getRoots()
145+
{
163146

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);
167150

168-
auto [top, bot, rsp] = getStackBounds();
151+
auto [top, bot, rsp] = getStackBounds();
169152

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))
172158
{
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);
179160
}
180-
181-
return result;
161+
rsp++;
182162
}
183163

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)
185173
{
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))
190176
{
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);
197178
}
198-
return result;
179+
p++;
199180
}
200-
};
201-
202-
MemoryManager &MemoryManager::instance()
203-
{
204-
static thread_local MemoryManager ob{std::make_unique<MemoryManagerImpl>()};
205-
return ob;
181+
return result;
206182
}
207-
208-
MemoryManager::MemoryManager(std::unique_ptr<IMemoryManagerImpl> impl) : _impl(std::move(impl)) {}
209-
210-
size_t MemoryManager::garbageCollect() { return _impl->garbageCollect(); }
211183
} // namespace sd

0 commit comments

Comments
 (0)