Skip to content

Use reserve instead of unchecked math in push #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 7, 2018

Conversation

mbrubeck
Copy link
Collaborator

@mbrubeck mbrubeck commented Aug 6, 2018

push currently uses this line to reserve space in the vector:

self.grow(cmp::max(cap * 2, 1))

This risks overflowing usize. In practice this can't happen currently, because cap can't be larger than isize::MAX because of invariants upheld in liballoc, but this is not easy to see.

Replacing this with self.reserve(1) is clearer, easier to reason about safety (because reserve uses checked arithmetic), and will make it easier to change the growth strategy in the future.

This does not regress any of the push benchmarks. Marking reserve as inline is necessary to prevent insert benchmarks from regressing because of a change in the optimizer's inlining decisions there.


This change is Reviewable

Copy link
Member

@emilio emilio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth pointing out in the commit message that reserve() calls next_power_of_two, so we don't grow one by one? Anyway looks great :)

`push` currently uses this line to reserve space in the vector:

```
self.grow(cmp::max(cap * 2, 1))
```

This risks overflowing `usize`.  In practice this won't lead to any
bugs, because the capacity can't be larger than `isize::MAX` because of
invariants upheld in liballoc, but this is not easy to see.

Replacing this with `self.reserve(1)` is clearer, easier to reason about
safety (because `reserve` uses checked arithmetic), and will make it
easier to change the growth strategy in the future.  (Currently
`reserve(1)` will grow to the next power of 2.)

This does not regress any of the `push` benchmarks.  Marking `reserve`
as inline is necessary to prevent `insert` benchmarks from regressing
because of a change in the optimizer's inlining decisions there.
@mbrubeck
Copy link
Collaborator Author

mbrubeck commented Aug 7, 2018

@bors-servo r=emilio

@bors-servo
Copy link
Contributor

📌 Commit d2b1900 has been approved by emilio

@bors-servo
Copy link
Contributor

⌛ Testing commit d2b1900 with merge feb42bd...

bors-servo pushed a commit that referenced this pull request Aug 7, 2018
Use `reserve` instead of unchecked math in `push`

`push` currently uses this line to reserve space in the vector:

```
self.grow(cmp::max(cap * 2, 1))
```

This risks overflowing `usize`.  In practice this can't happen currently, because `cap` can't be larger than `isize::MAX` because of invariants upheld in liballoc, but this is not easy to see.

Replacing this with `self.reserve(1)` is clearer, easier to reason about safety (because `reserve` uses checked arithmetic), and will make it easier to change the growth strategy in the future.

This does not regress any of the `push` benchmarks.  Marking `reserve` as inline is necessary to prevent `insert` benchmarks from regressing because of a change in the optimizer's inlining decisions there.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/112)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

☀️ Test successful - status-travis
Approved by: emilio
Pushing feb42bd to master...

@bors-servo bors-servo merged commit d2b1900 into servo:master Aug 7, 2018
mbrubeck added a commit to mbrubeck/rust-smallvec that referenced this pull request Aug 22, 2018
Change log:

* servo#118 - optimize `from_slice`
* servo#115 - add `into_inner` method
* Some code cleanup and testing improvements (servo#112, servo#113, servo#114, servo#120)
mbrubeck added a commit to mbrubeck/rust-smallvec that referenced this pull request Aug 22, 2018
Change log:

* servo#115 - add `into_inner` method
* servo#117 - add `from_buf_and_len` and `from_buf_and_len_unchecked`
* servo#118 - optimize `from_slice`
* Some code cleanup and testing improvements (servo#112, servo#113, servo#114, servo#120)
@mbrubeck mbrubeck mentioned this pull request Aug 22, 2018
bors-servo pushed a commit that referenced this pull request Aug 22, 2018
Version 0.6.5

Change log:

* #115 - add `into_inner` method
* #117 - add `from_buf_and_len` and `from_buf_and_len_unchecked`
* #118 - optimize `from_slice`
* Some code cleanup and testing improvements (#112, #113, #114, #120)

cc @llogiq

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/121)
<!-- Reviewable:end -->
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.

3 participants