Skip to content

Commit b3cec96

Browse files
committed
Merge pull request #113366 from aaronp64/free_gamestate_snapshots
Fix `GameStateSnapshot`s not being freed
2 parents 6b0a740 + ed6181c commit b3cec96

File tree

4 files changed

+25
-49
lines changed

4 files changed

+25
-49
lines changed

modules/objectdb_profiler/editor/objectdb_profiler_panel.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
#include "core/os/time.h"
4242
#include "editor/debugger/editor_debugger_node.h"
4343
#include "editor/debugger/script_editor_debugger.h"
44+
#include "editor/docks/inspector_dock.h"
4445
#include "editor/editor_node.h"
46+
#include "editor/inspector/editor_inspector.h"
4547
#include "editor/themes/editor_scale.h"
4648
#include "scene/gui/button.h"
4749
#include "scene/gui/label.h"
@@ -167,7 +169,7 @@ TreeItem *ObjectDBProfilerPanel::_add_snapshot_button(const String &p_snapshot_f
167169
void ObjectDBProfilerPanel::_show_selected_snapshot() {
168170
if (snapshot_list->get_selected()->get_text(0) == (String)diff_button->get_selected_metadata()) {
169171
for (int i = 0; i < diff_button->get_item_count(); i++) {
170-
if (diff_button->get_item_text(i) == current_snapshot->get_snapshot()->name) {
172+
if (diff_button->get_item_text(i) == current_snapshot->name) {
171173
diff_button->select(i);
172174
break;
173175
}
@@ -184,7 +186,7 @@ void ObjectDBProfilerPanel::_on_snapshot_deselected() {
184186
_update_enabled_diff_items();
185187
}
186188

187-
Ref<GameStateSnapshotRef> ObjectDBProfilerPanel::get_snapshot(const String &p_snapshot_file_name) {
189+
Ref<GameStateSnapshot> ObjectDBProfilerPanel::get_snapshot(const String &p_snapshot_file_name) {
188190
if (snapshot_cache.has(p_snapshot_file_name)) {
189191
return snapshot_cache.get(p_snapshot_file_name);
190192
}
@@ -201,7 +203,7 @@ Ref<GameStateSnapshotRef> ObjectDBProfilerPanel::get_snapshot(const String &p_sn
201203
Vector<uint8_t> content = snapshot_file->get_buffer(snapshot_file->get_length()); // We want to split on newlines, so normalize them.
202204
ERR_FAIL_COND_V_MSG(content.is_empty(), nullptr, "ObjectDB Snapshot file is empty: " + full_file_path);
203205

204-
Ref<GameStateSnapshotRef> snapshot = GameStateSnapshot::create_ref(p_snapshot_file_name, content);
206+
Ref<GameStateSnapshot> snapshot = GameStateSnapshot::create_ref(p_snapshot_file_name, content);
205207
if (snapshot.is_valid()) {
206208
snapshot_cache.insert(p_snapshot_file_name, snapshot);
207209
}
@@ -225,8 +227,8 @@ void ObjectDBProfilerPanel::_view_tab_changed(int p_tab_idx) {
225227
// Populating tabs only on tab changed because we're handling a lot of data,
226228
// and the editor freezes for a while if we try to populate every tab at once.
227229
SnapshotView *view = cast_to<SnapshotView>(view_tabs->get_current_tab_control());
228-
GameStateSnapshot *snapshot = current_snapshot.is_null() ? nullptr : current_snapshot->get_snapshot();
229-
GameStateSnapshot *diff = diff_snapshot.is_null() ? nullptr : diff_snapshot->get_snapshot();
230+
GameStateSnapshot *snapshot = current_snapshot.ptr();
231+
GameStateSnapshot *diff = diff_snapshot.ptr();
230232
if (snapshot != nullptr && !view->is_showing_snapshot(snapshot, diff)) {
231233
view->show_snapshot(snapshot, diff);
232234
}
@@ -237,6 +239,11 @@ void ObjectDBProfilerPanel::clear_snapshot(bool p_update_view_tabs) {
237239
view->clear_snapshot();
238240
}
239241

242+
const Object *edited_object = InspectorDock::get_inspector_singleton()->get_edited_object();
243+
if (Object::cast_to<SnapshotDataObject>(edited_object)) {
244+
EditorNode::get_singleton()->push_item(nullptr);
245+
}
246+
240247
current_snapshot.unref();
241248
diff_snapshot.unref();
242249

@@ -333,7 +340,7 @@ void ObjectDBProfilerPanel::_edit_snapshot_name() {
333340
ObjectDBProfilerPanel::ObjectDBProfilerPanel() {
334341
set_name(TTRC("ObjectDB Profiler"));
335342

336-
snapshot_cache = LRUCache<String, Ref<GameStateSnapshotRef>>(SNAPSHOT_CACHE_MAX_SIZE);
343+
snapshot_cache = LRUCache<String, Ref<GameStateSnapshot>>(SNAPSHOT_CACHE_MAX_SIZE);
337344

338345
EditorDebuggerNode::get_singleton()->get_current_debugger()->connect("breaked", callable_mp(this, &ObjectDBProfilerPanel::_on_debug_breaked));
339346

modules/objectdb_profiler/editor/objectdb_profiler_panel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ class ObjectDBProfilerPanel : public Control {
6969
HashMap<int, PartialSnapshot> partial_snapshots;
7070

7171
LocalVector<SnapshotView *> views;
72-
Ref<GameStateSnapshotRef> current_snapshot;
73-
Ref<GameStateSnapshotRef> diff_snapshot;
74-
LRUCache<String, Ref<GameStateSnapshotRef>> snapshot_cache;
72+
Ref<GameStateSnapshot> current_snapshot;
73+
Ref<GameStateSnapshot> diff_snapshot;
74+
LRUCache<String, Ref<GameStateSnapshot>> snapshot_cache;
7575

7676
void _request_object_snapshot();
7777
void _begin_object_snapshot();
@@ -95,7 +95,7 @@ class ObjectDBProfilerPanel : public Control {
9595
void receive_snapshot(int p_request_id);
9696
void show_snapshot(const String &p_snapshot_file_name, const String &p_snapshot_diff_file_name);
9797
void clear_snapshot(bool p_update_view_tabs = true);
98-
Ref<GameStateSnapshotRef> get_snapshot(const String &p_snapshot_file_name);
98+
Ref<GameStateSnapshot> get_snapshot(const String &p_snapshot_file_name);
9999
void set_enabled(bool p_enabled);
100100
void add_view(SnapshotView *p_to_add);
101101

modules/objectdb_profiler/editor/snapshot_data.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,9 @@ void GameStateSnapshot::recompute_references() {
318318
}
319319
}
320320

321-
Ref<GameStateSnapshotRef> GameStateSnapshot::create_ref(const String &p_snapshot_name, const Vector<uint8_t> &p_snapshot_buffer) {
322-
// A ref to a refcounted object which is a wrapper of a non-refcounted object.
323-
Ref<GameStateSnapshotRef> sn;
324-
sn.instantiate(memnew(GameStateSnapshot));
325-
GameStateSnapshot *snapshot = sn->get_snapshot();
321+
Ref<GameStateSnapshot> GameStateSnapshot::create_ref(const String &p_snapshot_name, const Vector<uint8_t> &p_snapshot_buffer) {
322+
Ref<GameStateSnapshot> snapshot;
323+
snapshot.instantiate();
326324
snapshot->name = p_snapshot_name;
327325

328326
// Snapshots may have been created by an older version of the editor. Handle parsing old snapshot versions here based on the version number.
@@ -347,29 +345,17 @@ Ref<GameStateSnapshotRef> GameStateSnapshot::create_ref(const String &p_snapshot
347345
continue;
348346
}
349347

350-
snapshot->objects[obj.id] = memnew(SnapshotDataObject(obj, snapshot, resource_cache));
348+
snapshot->objects[obj.id] = memnew(SnapshotDataObject(obj, snapshot.ptr(), resource_cache));
351349
snapshot->objects[obj.id]->extra_debug_data = (Dictionary)snapshot_data[i + 3];
352350
}
353351

354352
snapshot->recompute_references();
355353
print_verbose("Resource cache hits: " + String::num(resource_cache.hits) + ". Resource cache misses: " + String::num(resource_cache.misses));
356-
return sn;
354+
return snapshot;
357355
}
358356

359357
GameStateSnapshot::~GameStateSnapshot() {
360358
for (const KeyValue<ObjectID, SnapshotDataObject *> &item : objects) {
361359
memdelete(item.value);
362360
}
363361
}
364-
365-
bool GameStateSnapshotRef::unreference() {
366-
bool die = RefCounted::unreference();
367-
if (die) {
368-
memdelete(gamestate_snapshot);
369-
}
370-
return die;
371-
}
372-
373-
GameStateSnapshot *GameStateSnapshotRef::get_snapshot() {
374-
return gamestate_snapshot;
375-
}

modules/objectdb_profiler/editor/snapshot_data.h

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "editor/debugger/editor_debugger_inspector.h"
3434

3535
class GameStateSnapshot;
36-
class GameStateSnapshotRef;
3736

3837
class SnapshotDataObject : public Object {
3938
GDCLASS(SnapshotDataObject, Object);
@@ -77,8 +76,8 @@ class SnapshotDataObject : public Object {
7776
static void _bind_methods();
7877
};
7978

80-
class GameStateSnapshot : public Object {
81-
GDCLASS(GameStateSnapshot, Object);
79+
class GameStateSnapshot : public RefCounted {
80+
GDCLASS(GameStateSnapshot, RefCounted);
8281

8382
void _get_outbound_references(Variant &p_var, HashMap<String, ObjectID> &r_ret_val, const String &p_current_path = "");
8483
void _get_rc_cycles(SnapshotDataObject *p_obj, SnapshotDataObject *p_source_obj, HashSet<SnapshotDataObject *> p_traversed_objs, LocalVector<String> &r_ret_val, const String &p_current_path = "");
@@ -88,24 +87,8 @@ class GameStateSnapshot : public Object {
8887
HashMap<ObjectID, SnapshotDataObject *> objects;
8988
Dictionary snapshot_context;
9089

91-
// Ideally, this would extend EditorDebuggerRemoteObject and be refcounted, but we can't have it both ways.
92-
// So, instead we have this static 'constructor' that returns a RefCounted wrapper around a GameStateSnapshot.
93-
static Ref<GameStateSnapshotRef> create_ref(const String &p_snapshot_name, const Vector<uint8_t> &p_snapshot_buffer);
90+
static Ref<GameStateSnapshot> create_ref(const String &p_snapshot_name, const Vector<uint8_t> &p_snapshot_buffer);
9491
~GameStateSnapshot();
9592

9693
void recompute_references();
9794
};
98-
99-
// Thin RefCounted wrapper around a GameStateSnapshot.
100-
class GameStateSnapshotRef : public RefCounted {
101-
GDCLASS(GameStateSnapshotRef, RefCounted);
102-
103-
GameStateSnapshot *gamestate_snapshot = nullptr;
104-
105-
public:
106-
GameStateSnapshotRef(GameStateSnapshot *p_gss) :
107-
gamestate_snapshot(p_gss) {}
108-
109-
bool unreference();
110-
GameStateSnapshot *get_snapshot();
111-
};

0 commit comments

Comments
 (0)