@@ -270,6 +270,7 @@ typedef struct {
270
270
PyObject_HEAD
271
271
PyObject * it ;
272
272
PyObject * old ;
273
+ PyObject * result ;
273
274
} pairwiseobject ;
274
275
275
276
/*[clinic input]
@@ -301,6 +302,11 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable)
301
302
}
302
303
po -> it = it ;
303
304
po -> old = NULL ;
305
+ po -> result = PyTuple_Pack (2 , Py_None , Py_None );
306
+ if (po -> result == NULL ) {
307
+ Py_DECREF (po );
308
+ return NULL ;
309
+ }
304
310
return (PyObject * )po ;
305
311
}
306
312
@@ -311,6 +317,7 @@ pairwise_dealloc(pairwiseobject *po)
311
317
PyObject_GC_UnTrack (po );
312
318
Py_XDECREF (po -> it );
313
319
Py_XDECREF (po -> old );
320
+ Py_XDECREF (po -> result );
314
321
tp -> tp_free (po );
315
322
Py_DECREF (tp );
316
323
}
@@ -321,6 +328,7 @@ pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
321
328
Py_VISIT (Py_TYPE (po ));
322
329
Py_VISIT (po -> it );
323
330
Py_VISIT (po -> old );
331
+ Py_VISIT (po -> result );
324
332
return 0 ;
325
333
}
326
334
@@ -355,8 +363,30 @@ pairwise_next(pairwiseobject *po)
355
363
Py_DECREF (old );
356
364
return NULL ;
357
365
}
358
- /* Future optimization: Reuse the result tuple as we do in enumerate() */
359
- result = PyTuple_Pack (2 , old , new );
366
+
367
+ result = po -> result ;
368
+ if (Py_REFCNT (result ) == 1 ) {
369
+ Py_INCREF (result );
370
+ PyObject * last_old = PyTuple_GET_ITEM (result , 0 );
371
+ PyObject * last_new = PyTuple_GET_ITEM (result , 1 );
372
+ PyTuple_SET_ITEM (result , 0 , Py_NewRef (old ));
373
+ PyTuple_SET_ITEM (result , 1 , Py_NewRef (new ));
374
+ Py_DECREF (last_old );
375
+ Py_DECREF (last_new );
376
+ // bpo-42536: The GC may have untracked this result tuple. Since we're
377
+ // recycling it, make sure it's tracked again:
378
+ if (!_PyObject_GC_IS_TRACKED (result )) {
379
+ _PyObject_GC_TRACK (result );
380
+ }
381
+ }
382
+ else {
383
+ result = PyTuple_New (2 );
384
+ if (result != NULL ) {
385
+ PyTuple_SET_ITEM (result , 0 , Py_NewRef (old ));
386
+ PyTuple_SET_ITEM (result , 1 , Py_NewRef (new ));
387
+ }
388
+ }
389
+
360
390
Py_XSETREF (po -> old , new );
361
391
Py_DECREF (old );
362
392
return result ;
0 commit comments