Skip to content

Commit 6053d5a

Browse files
committed
Add missing reserve assumes for Vec and String
Signed-off-by: Alex Saveau <[email protected]>
1 parent d868bc2 commit 6053d5a

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

library/alloc/src/raw_vec.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ impl<T, A: Allocator> RawVec<T, A> {
308308
if self.needs_to_grow(len, additional) {
309309
do_reserve_and_handle(self, len, additional);
310310
}
311+
unsafe {
312+
// Inform the optimizer that the reservation has succeeded or wasn't needed
313+
intrinsics::assume(!self.needs_to_grow(len, additional));
314+
}
311315
}
312316

313317
/// A specialized version of `reserve()` used only by the hot and
@@ -325,7 +329,7 @@ impl<T, A: Allocator> RawVec<T, A> {
325329
}
326330
unsafe {
327331
// Inform the optimizer that the reservation has succeeded or wasn't needed
328-
core::intrinsics::assume(!self.needs_to_grow(len, additional));
332+
intrinsics::assume(!self.needs_to_grow(len, additional));
329333
}
330334
Ok(())
331335
}
@@ -363,7 +367,7 @@ impl<T, A: Allocator> RawVec<T, A> {
363367
}
364368
unsafe {
365369
// Inform the optimizer that the reservation has succeeded or wasn't needed
366-
core::intrinsics::assume(!self.needs_to_grow(len, additional));
370+
intrinsics::assume(!self.needs_to_grow(len, additional));
367371
}
368372
Ok(())
369373
}
@@ -387,7 +391,7 @@ impl<T, A: Allocator> RawVec<T, A> {
387391
impl<T, A: Allocator> RawVec<T, A> {
388392
/// Returns if the buffer needs to grow to fulfill the needed extra capacity.
389393
/// Mainly used to make inlining reserve-calls possible without inlining `grow`.
390-
fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
394+
pub(crate) fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
391395
additional > self.capacity().wrapping_sub(len)
392396
}
393397

library/alloc/src/string.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
#![stable(feature = "rust1", since = "1.0.0")]
4444

4545
use core::error::Error;
46-
use core::fmt;
4746
use core::hash;
4847
#[cfg(not(no_global_oom_handling))]
4948
use core::iter::from_fn;
@@ -60,6 +59,7 @@ use core::slice;
6059
use core::str::pattern::Pattern;
6160
#[cfg(not(no_global_oom_handling))]
6261
use core::str::Utf8Chunks;
62+
use core::{fmt, intrinsics};
6363

6464
#[cfg(not(no_global_oom_handling))]
6565
use crate::borrow::{Cow, ToOwned};
@@ -1149,7 +1149,11 @@ impl String {
11491149
#[inline]
11501150
#[stable(feature = "rust1", since = "1.0.0")]
11511151
pub fn reserve(&mut self, additional: usize) {
1152-
self.vec.reserve(additional)
1152+
self.vec.reserve(additional);
1153+
unsafe {
1154+
// Inform the optimizer that the reservation has succeeded or wasn't needed
1155+
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1156+
}
11531157
}
11541158

11551159
/// Reserves the minimum capacity for at least `additional` bytes more than
@@ -1199,7 +1203,11 @@ impl String {
11991203
#[inline]
12001204
#[stable(feature = "rust1", since = "1.0.0")]
12011205
pub fn reserve_exact(&mut self, additional: usize) {
1202-
self.vec.reserve_exact(additional)
1206+
self.vec.reserve_exact(additional);
1207+
unsafe {
1208+
// Inform the optimizer that the reservation has succeeded or wasn't needed
1209+
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1210+
}
12031211
}
12041212

12051213
/// Tries to reserve capacity for at least `additional` bytes more than the
@@ -1233,8 +1241,14 @@ impl String {
12331241
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
12341242
/// ```
12351243
#[stable(feature = "try_reserve", since = "1.57.0")]
1244+
#[inline]
12361245
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
1237-
self.vec.try_reserve(additional)
1246+
self.vec.try_reserve(additional)?;
1247+
unsafe {
1248+
// Inform the optimizer that the reservation has succeeded or wasn't needed
1249+
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1250+
}
1251+
Ok(())
12381252
}
12391253

12401254
/// Tries to reserve the minimum capacity for at least `additional` bytes
@@ -1274,8 +1288,14 @@ impl String {
12741288
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
12751289
/// ```
12761290
#[stable(feature = "try_reserve", since = "1.57.0")]
1291+
#[inline]
12771292
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
1278-
self.vec.try_reserve_exact(additional)
1293+
self.vec.try_reserve_exact(additional)?;
1294+
unsafe {
1295+
// Inform the optimizer that the reservation has succeeded or wasn't needed
1296+
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1297+
}
1298+
Ok(())
12791299
}
12801300

12811301
/// Shrinks the capacity of this `String` to match its length.

library/alloc/src/vec/mod.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
#[cfg(not(no_global_oom_handling))]
5757
use core::cmp;
5858
use core::cmp::Ordering;
59-
use core::fmt;
6059
use core::hash::{Hash, Hasher};
6160
#[cfg(not(no_global_oom_handling))]
6261
use core::iter;
@@ -65,6 +64,7 @@ use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
6564
use core::ops::{self, Index, IndexMut, Range, RangeBounds};
6665
use core::ptr::{self, NonNull};
6766
use core::slice::{self, SliceIndex};
67+
use core::{fmt, intrinsics};
6868

6969
use crate::alloc::{Allocator, Global};
7070
use crate::borrow::{Cow, ToOwned};
@@ -907,8 +907,13 @@ impl<T, A: Allocator> Vec<T, A> {
907907
/// ```
908908
#[cfg(not(no_global_oom_handling))]
909909
#[stable(feature = "rust1", since = "1.0.0")]
910+
#[inline]
910911
pub fn reserve(&mut self, additional: usize) {
911912
self.buf.reserve(self.len, additional);
913+
unsafe {
914+
// Inform the optimizer that the reservation has succeeded or wasn't needed
915+
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
916+
}
912917
}
913918

914919
/// Reserves the minimum capacity for at least `additional` more elements to
@@ -937,8 +942,13 @@ impl<T, A: Allocator> Vec<T, A> {
937942
/// ```
938943
#[cfg(not(no_global_oom_handling))]
939944
#[stable(feature = "rust1", since = "1.0.0")]
945+
#[inline]
940946
pub fn reserve_exact(&mut self, additional: usize) {
941947
self.buf.reserve_exact(self.len, additional);
948+
unsafe {
949+
// Inform the optimizer that the reservation has succeeded or wasn't needed
950+
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
951+
}
942952
}
943953

944954
/// Tries to reserve capacity for at least `additional` more elements to be inserted
@@ -974,8 +984,14 @@ impl<T, A: Allocator> Vec<T, A> {
974984
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
975985
/// ```
976986
#[stable(feature = "try_reserve", since = "1.57.0")]
987+
#[inline]
977988
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
978-
self.buf.try_reserve(self.len, additional)
989+
self.buf.try_reserve(self.len, additional)?;
990+
unsafe {
991+
// Inform the optimizer that the reservation has succeeded or wasn't needed
992+
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
993+
}
994+
Ok(())
979995
}
980996

981997
/// Tries to reserve the minimum capacity for at least `additional`
@@ -1017,8 +1033,14 @@ impl<T, A: Allocator> Vec<T, A> {
10171033
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
10181034
/// ```
10191035
#[stable(feature = "try_reserve", since = "1.57.0")]
1036+
#[inline]
10201037
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
1021-
self.buf.try_reserve_exact(self.len, additional)
1038+
self.buf.try_reserve_exact(self.len, additional)?;
1039+
unsafe {
1040+
// Inform the optimizer that the reservation has succeeded or wasn't needed
1041+
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
1042+
}
1043+
Ok(())
10221044
}
10231045

10241046
/// Shrinks the capacity of the vector as much as possible.
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5:
1+
thread 'main' panicked at library/alloc/src/raw_vec.rs:575:5:
22
capacity overflow
33
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

0 commit comments

Comments
 (0)