struct gc_generation old[2];
/* a permanent generation which won't be collected */
struct gc_generation permanent_generation;
- struct gc_stats generation_stats;
+ struct gc_stats *generation_stats;
/* true if we are currently running the collector */
int collecting;
// The frame that started the current collection. It might be NULL even when
/* To get consistent values despite allocations while constructing
the result list, we use a snapshot of the running stats. */
GCState *gcstate = get_gc_state();
- stats[0] = gcstate->generation_stats.young.items[gcstate->generation_stats.young.index];
- stats[1] = gcstate->generation_stats.old[0].items[gcstate->generation_stats.old[0].index];
- stats[2] = gcstate->generation_stats.old[1].items[gcstate->generation_stats.old[1].index];
+ stats[0] = gcstate->generation_stats->young.items[gcstate->generation_stats->young.index];
+ stats[1] = gcstate->generation_stats->old[0].items[gcstate->generation_stats->old[0].index];
+ stats[2] = gcstate->generation_stats->old[1].items[gcstate->generation_stats->old[1].index];
PyObject *result = PyList_New(0);
if (result == NULL)
{
GCState *gcstate = &interp->gc;
+ gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats));
+ if (gcstate->generation_stats == NULL) {
+ return _PyStatus_NO_MEMORY();
+ }
+
gcstate->garbage = PyList_New(0);
if (gcstate->garbage == NULL) {
return _PyStatus_NO_MEMORY();
gc_get_stats(GCState *gcstate, int gen)
{
if (gen == 0) {
- struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young;
+ struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young;
buffer->index = (buffer->index + 1) % GC_YOUNG_STATS_SIZE;
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
}
else {
- struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1];
+ struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1];
buffer->index = (buffer->index + 1) % GC_OLD_STATS_SIZE;
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
gc_get_prev_stats(GCState *gcstate, int gen)
{
if (gen == 0) {
- struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young;
+ struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young;
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
}
else {
- struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1];
+ struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1];
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
}
GCState *gcstate = &interp->gc;
Py_CLEAR(gcstate->garbage);
Py_CLEAR(gcstate->callbacks);
+ PyMem_RawFree(gcstate->generation_stats);
+ gcstate->generation_stats = NULL;
/* Prevent a subtle bug that affects sub-interpreters that use basic
* single-phase init extensions (m_size == -1). Those extensions cause objects
{
GCState *gcstate = &interp->gc;
+ gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats));
+ if (gcstate->generation_stats == NULL) {
+ return _PyStatus_NO_MEMORY();
+ }
+
gcstate->garbage = PyList_New(0);
if (gcstate->garbage == NULL) {
return _PyStatus_NO_MEMORY();
get_stats(GCState *gcstate, int gen)
{
if (gen == 0) {
- struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young;
+ struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young;
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
}
else {
- struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1];
+ struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1];
struct gc_generation_stats *stats = &buffer->items[buffer->index];
return stats;
}
GCState *gcstate = &interp->gc;
Py_CLEAR(gcstate->garbage);
Py_CLEAR(gcstate->callbacks);
+ PyMem_RawFree(gcstate->generation_stats);
+ gcstate->generation_stats = NULL;
/* We expect that none of this interpreters objects are shared
with other interpreters.