From 892012e5d904ae7afab21bedf695830c10c2baae Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 2 Sep 2024 18:54:59 +0200 Subject: [PATCH] QDirListing: Extract Method next() from const_iterator::op++() Having the actual const_iterator::operator++() as an out-of-line member function means that the implicit this pointer forces the object onto the stack (registers don't have addresses that could be passed). Since const_iterator is now merely a thinly-disguised pointer, that would cause terrible codegen. So, apply a technique originally developed for QStringView and make the operator an inline function that re-sets the member dirEntry using a call to a QDirListing static function that takes and returns by value. Passing by value enables passing in registers, which means the iterator object can now be a register value and doesn't require spilling to the stack to call the function. Found in API-review. Change-Id: I9f4d5be5b72249b368ef3dea9d857178ca7e16aa Reviewed-by: Thiago Macieira (cherry picked from commit aec8398d71d351e956683a695af51317fe65097e) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/io/qdirlisting.cpp | 15 ++++++++++++--- src/corelib/io/qdirlisting.h | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp index 075672e39b9..6b9741a472b 100644 --- a/src/corelib/io/qdirlisting.cpp +++ b/src/corelib/io/qdirlisting.cpp @@ -723,14 +723,23 @@ QDirListing::const_iterator QDirListing::begin() const */ /*! + \fn QDirListing::const_iterator::operator++() + Advances the iterator and returns a reference to it. */ -QDirListing::const_iterator &QDirListing::const_iterator::operator++() + +/*! + \internal + + Implements the actual advancing. Not a member function to avoid forcing + DirEntry objects (and therefore const_iterator ones) onto the stack. +*/ +auto QDirListing::next(DirEntry dirEntry) -> DirEntry { dirEntry.dirListPtr->advance(); if (!dirEntry.dirListPtr->hasIterators()) - *this = {}; // All done, make `this` equal to the end() iterator - return *this; + return {}; // All done, make `this` equal to the end() iterator + return dirEntry; } /*! diff --git a/src/corelib/io/qdirlisting.h b/src/corelib/io/qdirlisting.h index 2a460676d28..74487f83bd3 100644 --- a/src/corelib/io/qdirlisting.h +++ b/src/corelib/io/qdirlisting.h @@ -119,7 +119,7 @@ public: reference operator*() const { return dirEntry; } pointer operator->() const { return &dirEntry; } - Q_CORE_EXPORT const_iterator &operator++(); + const_iterator &operator++() { dirEntry = next(dirEntry); return *this; } void operator++(int) { ++*this; }; // [iterator.concept.winc]/14 not required to return sth private: bool atEnd() const noexcept { return dirEntry.dirListPtr == nullptr; } @@ -146,6 +146,8 @@ public: private: Q_DISABLE_COPY(QDirListing) + Q_CORE_EXPORT static DirEntry next(DirEntry); + // Private constructor that is used in deprecated code paths. // `uint` instead of QDir::Filters and QDirIterator::IteratorFlags // because qdir.h can't be included here; qdiriterator.h can't included