@@ -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) {
910912template <class Callback >
911913static 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