File tree Expand file tree Collapse file tree 3 files changed +49
-26
lines changed
Misc/NEWS.d/next/Core and Builtins Expand file tree Collapse file tree 3 files changed +49
-26
lines changed Original file line number Diff line number Diff line change 1+ Certain sequence multiplication operations like ``[0] * 1_000 `` are now faster due to reference-counting optimizations. Patch by Dennis Sweeney.
Original file line number Diff line number Diff line change @@ -553,11 +553,8 @@ list_concat(PyListObject *a, PyObject *bb)
553553static PyObject *
554554list_repeat (PyListObject * a , Py_ssize_t n )
555555{
556- Py_ssize_t i , j ;
557556 Py_ssize_t size ;
558557 PyListObject * np ;
559- PyObject * * p , * * items ;
560- PyObject * elem ;
561558 if (n < 0 )
562559 n = 0 ;
563560 if (n > 0 && Py_SIZE (a ) > PY_SSIZE_T_MAX / n )
@@ -568,24 +565,32 @@ list_repeat(PyListObject *a, Py_ssize_t n)
568565 np = (PyListObject * ) list_new_prealloc (size );
569566 if (np == NULL )
570567 return NULL ;
571-
568+ PyObject * * dest = np -> ob_item ;
569+ PyObject * * dest_end = dest + size ;
572570 if (Py_SIZE (a ) == 1 ) {
573- items = np -> ob_item ;
574- elem = a -> ob_item [0 ];
575- for (i = 0 ; i < n ; i ++ ) {
576- items [i ] = elem ;
577- Py_INCREF (elem );
571+ PyObject * elem = a -> ob_item [0 ];
572+ Py_SET_REFCNT (elem , Py_REFCNT (elem ) + n );
573+ #ifdef Py_REF_DEBUG
574+ _Py_RefTotal += n ;
575+ #endif
576+ while (dest < dest_end ) {
577+ * dest ++ = elem ;
578578 }
579579 }
580580 else {
581- p = np -> ob_item ;
582- items = a -> ob_item ;
583- for (i = 0 ; i < n ; i ++ ) {
584- for (j = 0 ; j < Py_SIZE (a ); j ++ ) {
585- * p = items [j ];
586- Py_INCREF (* p );
587- p ++ ;
588- }
581+ PyObject * * src = a -> ob_item ;
582+ PyObject * * src_end = src + Py_SIZE (a );
583+ while (src < src_end ) {
584+ Py_SET_REFCNT (* src , Py_REFCNT (* src ) + n );
585+ #ifdef Py_REF_DEBUG
586+ _Py_RefTotal += n ;
587+ #endif
588+ * dest ++ = * src ++ ;
589+ }
590+ // Now src chases after dest in the same buffer
591+ src = np -> ob_item ;
592+ while (dest < dest_end ) {
593+ * dest ++ = * src ++ ;
589594 }
590595 }
591596 Py_SET_SIZE (np , size );
Original file line number Diff line number Diff line change @@ -589,10 +589,8 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
589589static PyObject *
590590tuplerepeat (PyTupleObject * a , Py_ssize_t n )
591591{
592- Py_ssize_t i , j ;
593592 Py_ssize_t size ;
594593 PyTupleObject * np ;
595- PyObject * * p , * * items ;
596594 if (Py_SIZE (a ) == 0 || n == 1 ) {
597595 if (PyTuple_CheckExact (a )) {
598596 /* Since tuples are immutable, we can return a shared
@@ -610,13 +608,32 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
610608 np = tuple_alloc (size );
611609 if (np == NULL )
612610 return NULL ;
613- p = np -> ob_item ;
614- items = a -> ob_item ;
615- for (i = 0 ; i < n ; i ++ ) {
616- for (j = 0 ; j < Py_SIZE (a ); j ++ ) {
617- * p = items [j ];
618- Py_INCREF (* p );
619- p ++ ;
611+ PyObject * * dest = np -> ob_item ;
612+ PyObject * * dest_end = dest + size ;
613+ if (Py_SIZE (a ) == 1 ) {
614+ PyObject * elem = a -> ob_item [0 ];
615+ Py_SET_REFCNT (elem , Py_REFCNT (elem ) + n );
616+ #ifdef Py_REF_DEBUG
617+ _Py_RefTotal += n ;
618+ #endif
619+ while (dest < dest_end ) {
620+ * dest ++ = elem ;
621+ }
622+ }
623+ else {
624+ PyObject * * src = a -> ob_item ;
625+ PyObject * * src_end = src + Py_SIZE (a );
626+ while (src < src_end ) {
627+ Py_SET_REFCNT (* src , Py_REFCNT (* src ) + n );
628+ #ifdef Py_REF_DEBUG
629+ _Py_RefTotal += n ;
630+ #endif
631+ * dest ++ = * src ++ ;
632+ }
633+ // Now src chases after dest in the same buffer
634+ src = np -> ob_item ;
635+ while (dest < dest_end ) {
636+ * dest ++ = * src ++ ;
620637 }
621638 }
622639 _PyObject_GC_TRACK (np );
You can’t perform that action at this time.
0 commit comments