@@ -1401,10 +1401,32 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
14011401returnn+m;
14021402}
140314031404+staticPyObject*
1405+list_from_object_stack(_PyObjectStack*stack)
1406+{
1407+PyObject*list=PyList_New(_PyObjectStack_Size(stack));
1408+if (list==NULL) {
1409+PyObject*op;
1410+while ((op=_PyObjectStack_Pop(stack)) !=NULL) {
1411+Py_DECREF(op);
1412+ }
1413+returnNULL;
1414+ }
1415+1416+PyObject*op;
1417+Py_ssize_tidx=0;
1418+while ((op=_PyObjectStack_Pop(stack)) !=NULL) {
1419+assert(idx<PyList_GET_SIZE(list));
1420+PyList_SET_ITEM(list, idx++, op);
1421+ }
1422+assert(idx==PyList_GET_SIZE(list));
1423+returnlist;
1424+}
1425+14041426structget_referrers_args {
14051427structvisitor_argsbase;
14061428PyObject*objs;
1407-structworklistresults;
1429+_PyObjectStackresults;
14081430};
1409143114101432staticint
@@ -1428,11 +1450,21 @@ visit_get_referrers(const mi_heap_t *heap, const mi_heap_area_t *area,
14281450if (op==NULL) {
14291451return true;
14301452 }
1453+if (op->ob_gc_bits& (_PyGC_BITS_UNREACHABLE | _PyGC_BITS_FROZEN)) {
1454+// Exclude unreachable objects (in-progress GC) and frozen
1455+// objects from gc.get_objects() to match the default build.
1456+return true;
1457+ }
1431145814321459structget_referrers_args*arg= (structget_referrers_args*)args;
1460+if (op==arg->objs) {
1461+// Don't include the tuple itself in the referrers list.
1462+return true;
1463+ }
14331464if (Py_TYPE(op)->tp_traverse(op, referrersvisit, arg->objs)) {
1434-op->ob_tid=0; // we will restore the refcount later
1435-worklist_push(&arg->results, op);
1465+if (_PyObjectStack_Push(&arg->results, Py_NewRef(op)) <0) {
1466+return false;
1467+ }
14361468 }
1437146914381470return true;
@@ -1441,48 +1473,25 @@ visit_get_referrers(const mi_heap_t *heap, const mi_heap_area_t *area,
14411473PyObject*
14421474_PyGC_GetReferrers(PyInterpreterState*interp, PyObject*objs)
14431475{
1444-PyObject*result=PyList_New(0);
1445-if (!result) {
1446-returnNULL;
1447- }
1448-1449-_PyEval_StopTheWorld(interp);
1450-1451-// Append all objects to a worklist. This abuses ob_tid. We will restore
1452-// it later. NOTE: We can't append to the PyListObject during
1453-// gc_visit_heaps() because PyList_Append() may reclaim an abandoned
1454-// mimalloc segments while we are traversing them.
1476+// NOTE: We can't append to the PyListObject during gc_visit_heaps()
1477+// because PyList_Append() may reclaim an abandoned mimalloc segments
1478+// while we are traversing them.
14551479structget_referrers_argsargs= { .objs=objs };
1456-gc_visit_heaps(interp, &visit_get_referrers, &args.base);
1457-1458-boolerror= false;
1459-PyObject*op;
1460-while ((op=worklist_pop(&args.results)) !=NULL) {
1461-gc_restore_tid(op);
1462-if (op!=objs&&PyList_Append(result, op) <0) {
1463-error= true;
1464-break;
1465- }
1466- }
1467-1468-// In case of error, clear the remaining worklist
1469-while ((op=worklist_pop(&args.results)) !=NULL) {
1470-gc_restore_tid(op);
1471- }
1472-1480+_PyEval_StopTheWorld(interp);
1481+interr=gc_visit_heaps(interp, &visit_get_referrers, &args.base);
14731482_PyEval_StartTheWorld(interp);
147414831475-if (error) {
1476-Py_DECREF(result);
1477-returnNULL;
1484+PyObject*list=list_from_object_stack(&args.results);
1485+if (err<0) {
1486+PyErr_NoMemory();
1487+Py_CLEAR(list);
14781488 }
1479-1480-returnresult;
1489+returnlist;
14811490}
1482149114831492structget_objects_args {
14841493structvisitor_argsbase;
1485-structworklistobjects;
1494+_PyObjectStackobjects;
14861495};
1487149614881497staticbool
@@ -1493,54 +1502,36 @@ visit_get_objects(const mi_heap_t *heap, const mi_heap_area_t *area,
14931502if (op==NULL) {
14941503return true;
14951504 }
1505+if (op->ob_gc_bits& (_PyGC_BITS_UNREACHABLE | _PyGC_BITS_FROZEN)) {
1506+// Exclude unreachable objects (in-progress GC) and frozen
1507+// objects from gc.get_objects() to match the default build.
1508+return true;
1509+ }
1496151014971511structget_objects_args*arg= (structget_objects_args*)args;
1498-op->ob_tid=0; // we will restore the refcount later
1499-worklist_push(&arg->objects, op);
1500-1512+if (_PyObjectStack_Push(&arg->objects, Py_NewRef(op)) <0) {
1513+return false;
1514+ }
15011515return true;
15021516}
1503151715041518PyObject*
15051519_PyGC_GetObjects(PyInterpreterState*interp, intgeneration)
15061520{
1507-PyObject*result=PyList_New(0);
1508-if (!result) {
1509-returnNULL;
1510- }
1511-1512-_PyEval_StopTheWorld(interp);
1513-1514-// Append all objects to a worklist. This abuses ob_tid. We will restore
1515-// it later. NOTE: We can't append to the list during gc_visit_heaps()
1516-// because PyList_Append() may reclaim an abandoned mimalloc segment
1517-// while we are traversing it.
1521+// NOTE: We can't append to the PyListObject during gc_visit_heaps()
1522+// because PyList_Append() may reclaim an abandoned mimalloc segments
1523+// while we are traversing them.
15181524structget_objects_argsargs= { 0 };
1519-gc_visit_heaps(interp, &visit_get_objects, &args.base);
1520-1521-boolerror= false;
1522-PyObject*op;
1523-while ((op=worklist_pop(&args.objects)) !=NULL) {
1524-gc_restore_tid(op);
1525-if (op!=result&&PyList_Append(result, op) <0) {
1526-error= true;
1527-break;
1528- }
1529- }
1530-1531-// In case of error, clear the remaining worklist
1532-while ((op=worklist_pop(&args.objects)) !=NULL) {
1533-gc_restore_tid(op);
1534- }
1535-1525+_PyEval_StopTheWorld(interp);
1526+interr=gc_visit_heaps(interp, &visit_get_objects, &args.base);
15361527_PyEval_StartTheWorld(interp);
153715281538-if (error) {
1539-Py_DECREF(result);
1540-returnNULL;
1529+PyObject*list=list_from_object_stack(&args.objects);
1530+if (err<0) {
1531+PyErr_NoMemory();
1532+Py_CLEAR(list);
15411533 }
1542-1543-returnresult;
1534+returnlist;
15441535}
1545153615461537staticbool