Skip to content

Commit 29e1e09

Browse files
committed
Remove some GC abstraction breaking in the debugger
I don't think we'll be able to provide GC_base in every possible GC - whippet doesn't expose it, for example, and really I'd like to not require interior pointer work anyway. Using boehm's GC_base outside of boehmGarbageCollection.cc is right out anyway.
1 parent 681ef98 commit 29e1e09

File tree

4 files changed

+41
-41
lines changed

4 files changed

+41
-41
lines changed

include/clasp/gctools/memoryManagement.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
// Define compile-time flags that effect structure sizes
2323
//
2424
#include <atomic>
25+
#include <set>
26+
#include <utility> // pair
2527
#include <clasp/gctools/configure_memory.h>
2628
#include <clasp/gctools/hardErrors.h>
2729

@@ -1296,7 +1298,7 @@ typedef void (*PointerFix)(uintptr_t* clientAddress, uintptr_t client, uintptr_t
12961298

12971299
void mapAllObjects(void (*)(Tagged, void*), void*);
12981300
std::set<Tagged> setOfAllObjects();
1299-
std::set<Tagged*> memtest(std::set<core::T_sp>&);
1301+
std::set<std::pair<Tagged, Tagged*>> memtest(std::set<core::T_sp>&);
13001302
size_t objectSize(BaseHeader_s* header);
13011303

13021304
bool is_memory_readable(const void* address, size_t bytes = 8);

src/core/debugger.cc

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -490,20 +490,7 @@ std::string dbg_safe_repr_depth(int depth, void* raw) {
490490
ss << "#<EXCEEDED-DEPTH>";
491491
return ss.str();
492492
}
493-
gctools::Header_s* header = (gctools::Header_s*)GC_base(raw);
494-
if (header==NULL) {
495-
ss << "#<NON-GC-POINTER=" << (void*)raw<<">";
496-
return ss.str();
497-
}
498-
gctools::clasp_ptr_t client = NULL;
499-
if (header->_badge_stamp_wtag_mtag.stampP()) {
500-
client = (gctools::clasp_ptr_t)((uintptr_t)gctools::HeaderPtrToGeneralPtr<core::General_O>((gctools::clasp_ptr_t)header) | GENERAL_TAG);
501-
} else if (header->_badge_stamp_wtag_mtag.consObjectP()) {
502-
client = (gctools::clasp_ptr_t)((uintptr_t)gctools::HeaderPtrToConsPtr(header) | CONS_TAG);
503-
} else if (header->_badge_stamp_wtag_mtag.weakObjectP()) {
504-
client = (gctools::clasp_ptr_t)((uintptr_t)gctools::HeaderPtrToWeakPtr(header) | GENERAL_TAG);
505-
}
506-
core::T_sp obj((gc::Tagged)client);
493+
core::T_sp obj((gc::Tagged)raw);
507494
if (obj.generalp()) {
508495
if (gc::IsA<core::Symbol_sp>(obj)) {
509496
core::Symbol_sp sym = gc::As_unsafe<core::Symbol_sp>(obj);

src/gctools/gcFunctions.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,13 +400,14 @@ bool memory_test() {
400400
result = false;
401401
core::lisp_write(fmt::format("{} corrupt objects in memory test\n", corrupt.size()));
402402
size_t idx = 0;
403-
for (const auto& field : corrupt) {
404-
auto cur = *field;
405-
void* base = GC_base(field);
403+
for (const auto& cur : corrupt) {
404+
Tagged base = cur.first;
405+
Tagged* field = cur.second;
406+
Tagged corruptObj = *field;
406407
if (base) {
407-
core::lisp_write(fmt::format("#{} -> {} @{} base: {} == {}\n", idx, (void*)cur, (void*)field, (void*)base, (std::string)dbg_safe_repr(base)));
408+
core::lisp_write(fmt::format("#{} -> {} @{} base: {} == {}\n", idx, (void*)corruptObj, (void*)field, (void*)base, dbg_safe_repr((void*)base)));
408409
} else {
409-
core::lisp_write(fmt::format("#{} -> {} @{} base: NULL\n", idx, (void*)cur, (void*)field ));
410+
core::lisp_write(fmt::format("#{} -> {} @{} base: [root]", idx, (void*)corruptObj, (void*)field ));
410411
}
411412
idx++;
412413
}

src/gctools/memoryManagement.cc

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ THE SOFTWARE.
2828

2929
#define DEBUG_LEVEL_NONE
3030

31+
#include <stack>
32+
#include <utility> // pair
3133
#include <unistd.h>
3234
#include <fcntl.h>
3335
#include <clasp/core/foundation.h>
@@ -881,9 +883,9 @@ void walkRoots(RootWalkCallback&& callback) {
881883
// #define HEADER_PTR_TO_WEAK_PTR(_header_) headerPointerToGeneralPointer((gctools::Header_s*)_header_)
882884

883885
#define ADDR_T uintptr_t
884-
#define EXTRA_ARGUMENTS , std::stack<Tagged*>& markStack
886+
#define EXTRA_ARGUMENTS , Tagged containingObject, std::stack<std::pair<Tagged, Tagged*>>& markStack
885887

886-
#define POINTER_FIX(_ptr_) markStack.push(reinterpret_cast<Tagged*>(_ptr_))
888+
#define POINTER_FIX(_ptr_) markStack.emplace(containingObject, reinterpret_cast<Tagged*>(_ptr_))
887889

888890
#define OBJECT_SCAN mw_obj_scan
889891
#define OBJECT_SKIP mw_obj_skip
@@ -910,12 +912,14 @@ void walkRoots(RootWalkCallback&& callback) {
910912
template <class Callback>
911913
static void mapAllObjectsInternal(std::set<Tagged>& markSet,
912914
Callback callback) {
913-
std::stack<Tagged*> markStack;
915+
std::stack<std::pair<Tagged, Tagged*>> markStack;
914916

915-
walkRoots([&](Tagged* rootf) { markStack.push(rootf); }); // process all roots
917+
// process all roots
918+
walkRoots([&](Tagged* rootf) { markStack.emplace(0, rootf); });
916919

917920
while (!markStack.empty()) {
918-
Tagged* field = markStack.top(); markStack.pop(); // pop a field
921+
// pop a field. we don't need the containing object.
922+
Tagged* field = markStack.top().second; markStack.pop();
919923
Tagged tagged = *field;
920924

921925
switch(ptag(tagged)) {
@@ -927,8 +931,8 @@ static void mapAllObjectsInternal(std::set<Tagged>& markSet,
927931
// the mw_foo_scan functions push all fields of the object
928932
// onto the markStack to keep the loop going.
929933
if (header->_badge_stamp_wtag_mtag.weakObjectP())
930-
mw_weak_scan(client, markStack);
931-
else mw_obj_scan(client, markStack);
934+
mw_weak_scan(client, tagged, markStack);
935+
else mw_obj_scan(client, tagged, markStack);
932936
// now's the time to callback. Could also go before the scan
933937
callback(tagged);
934938
}
@@ -937,7 +941,7 @@ static void mapAllObjectsInternal(std::set<Tagged>& markSet,
937941
if (!markSet.contains(tagged)) {
938942
markSet.insert(tagged);
939943
uintptr_t client = untag_object(tagged);
940-
mw_cons_scan(client, markStack);
944+
mw_cons_scan(client, tagged, markStack);
941945
callback(tagged);
942946
}
943947
} break;
@@ -961,19 +965,25 @@ std::set<Tagged> setOfAllObjects() {
961965
// Check that all fields in all objects point to valid objects.
962966
// Also check for functions that can't be resolved with dlsym, since that's
963967
// important for snapshot save.
964-
// Return the set of tagged pointers located in fields that are not valid.
965-
std::set<Tagged*> memtest(std::set<core::T_sp>& dladdrFailed) {
966-
std::stack<Tagged*> markStack;
968+
// Return the set of corrupt fields, represented as pairs of a non-corrupt
969+
// object and the address of a field within that object; the object contained
970+
// in that field is corrupt.
971+
// If a corrupt object is accessible in multiple fields, only one field containing
972+
// it is returned.
973+
std::set<std::pair<Tagged, Tagged*>> memtest(std::set<core::T_sp>& dladdrFailed) {
974+
std::stack<std::pair<Tagged, Tagged*>> markStack;
967975
std::set<Tagged> markSet;
968-
std::set<Tagged*> corrupt;
976+
std::set<std::pair<Tagged, Tagged*>> corrupt;
969977

970978
std::set<void*> uniqueEntryPoints;
971979

972-
walkRoots([&](Tagged* rootAddr) { markStack.push(rootAddr); });
980+
walkRoots([&](Tagged* rootAddr) { markStack.emplace(0, rootAddr); });
973981

974982
while (!markStack.empty()) {
975-
Tagged* field = markStack.top(); markStack.pop();
976-
gctools::Tagged tagged = *field;
983+
auto p = markStack.top(); markStack.pop();
984+
Tagged containingObject = p.first;
985+
Tagged* field = p.second;
986+
Tagged tagged = *field;
977987

978988
switch (tagged & ptag_mask) {
979989
case general_tag: {
@@ -983,9 +993,9 @@ std::set<Tagged*> memtest(std::set<core::T_sp>& dladdrFailed) {
983993
Header_s* header = (Header_s*)GeneralPtrToHeaderPtr((void*)client);
984994
if (header->isValidGeneralObject()) {
985995
if (header->_badge_stamp_wtag_mtag.weakObjectP())
986-
mw_weak_scan(client, markStack);
996+
mw_weak_scan(client, tagged, markStack);
987997
else {
988-
mw_obj_scan(client, markStack);
998+
mw_obj_scan(client, tagged, markStack);
989999
// If this is a function, check its dladdrability.
9901000
core::T_sp tobj(tagged);
9911001
if (tobj.isA<core::SimpleFun_O>()) {
@@ -1005,7 +1015,7 @@ std::set<Tagged*> memtest(std::set<core::T_sp>& dladdrFailed) {
10051015
}*/
10061016
}
10071017
} else {
1008-
corrupt.insert(field);
1018+
corrupt.emplace(containingObject, field);
10091019
}
10101020
}
10111021
} break;
@@ -1015,9 +1025,9 @@ std::set<Tagged*> memtest(std::set<core::T_sp>& dladdrFailed) {
10151025
uintptr_t client = tagged & ptr_mask;
10161026
ConsHeader_s* header = (ConsHeader_s*)ConsPtrToHeaderPtr((void*)client);
10171027
if (header->isValidConsObject())
1018-
mw_cons_scan(client, markStack);
1028+
mw_cons_scan(client, tagged, markStack);
10191029
else {
1020-
corrupt.insert(field);
1030+
corrupt.emplace(containingObject, field);
10211031
}
10221032
}
10231033
} break;
@@ -1040,7 +1050,7 @@ std::set<Tagged*> memtest(std::set<core::T_sp>& dladdrFailed) {
10401050
case UNBOUND_TAG: // FIXME: put const definition in pointer_tagging.h somewhere?
10411051
break; // immediate, nothing to do
10421052
default: // unknown tag - object is corrupt
1043-
corrupt.insert(field); break;
1053+
corrupt.emplace(containingObject, field); break;
10441054
}
10451055
}
10461056
return corrupt;

0 commit comments

Comments
 (0)