Skip to content

Simplify svector::grow - #2963

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:simplify-svector-grow
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:simplify-svector-grow

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026

Copy link
Copy Markdown
Member

Checklist

  • The title and commit message(s) are descriptive.
  • Small commits made to fix your PR have been squashed to avoid history pollution.
  • Tests have been added for new features or bug fixes.
  • API of new functions and classes are documented (no public API changes).

Description

Both branches of svector::grow() allocated the new buffer and copied the elements into it; only the heap branch released the old buffer. grow() now allocates and copies once, then releases the old buffer when it is on the heap. The copy uses current_size, the value that already sizes the new buffer and sets the new end. The XTENSOR_ASSERT(new_alloc) that came after the buffer had been written is gone: allocate() throws on failure.

The inline branch was also where GCC 15 at -O3 replaced m_begin with the inline array and, unable to bound the size, warned that the copy reads past it (-Warray-bounds, test_xstorage.cpp). The size is at most N there, so the read was never out of bounds; the same pattern in a short standalone program warns with GCC 13 and 15 and runs clean under AddressSanitizer. The warning goes away with the duplicated branch. Copying current_size elements instead of recomputing the count from m_end also keeps GCC 13 from pairing a one-element buffer with a non-empty copy when grow() is inlined into push_back(), which it did once combined with #2947 and #2951.

No behavior change, so no new test; test_xstorage passes. This merges cleanly with #2947 and #2949.

Both branches of grow() allocated the new buffer and copied the
elements into it, and only the heap branch released the old buffer.
grow() now does the allocation and the copy once, then releases the old
buffer when it is on the heap. The copy uses current_size, the value
that sizes the new buffer and sets the new end. The XTENSOR_ASSERT on
the result of allocate(), which came after the buffer had been written
to, is removed: allocate() throws on failure.

The branch taken when the elements are inline was also where GCC 15 at
-O3 replaced m_begin with the inline array and, unable to bound the
size, warned that the copy reads past it (-Warray-bounds). The size is
at most N there, so the read was never out of bounds; the warning goes
away with the duplicated branch. Copying current_size elements, rather
than recomputing the count from m_end, also keeps GCC 13 from pairing a
one-element buffer with a non-empty copy when grow() is inlined into
push_back().
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

✅ 255 untouched benchmarks


Comparing gouarin:simplify-svector-grow (f216c5a) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant