Skip to content
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

Use `reserve` instead of unchecked math in `push` #112

Merged
merged 1 commit into from Aug 7, 2018

Conversation

@mbrubeck
Copy link
Contributor

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

@emilio
emilio approved these changes Aug 7, 2018
Copy link
Member

emilio left a comment

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 mbrubeck force-pushed the mbrubeck:reserve branch from c111e89 to d2b1900 Aug 7, 2018
@mbrubeck
Copy link
Contributor Author

mbrubeck commented Aug 7, 2018

@bors-servo r=emilio

@bors-servo
Copy link
Contributor

bors-servo commented Aug 7, 2018

📌 Commit d2b1900 has been approved by emilio

@bors-servo
Copy link
Contributor

bors-servo commented Aug 7, 2018

Testing commit d2b1900 with merge feb42bd...

bors-servo added 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

bors-servo commented Aug 7, 2018

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

@bors-servo bors-servo merged commit d2b1900 into servo:master Aug 7, 2018
1 of 2 checks passed
1 of 2 checks passed
continuous-integration/travis-ci/pr The Travis CI build is in progress
Details
homu Test successful
Details
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 added 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
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

3 participants
You can’t perform that action at this time.