stylo: Add uses of fallible Vec, SmallVec and HashMap facilities.

Bug: 1395064
Reviewed-by: emilio
This commit is contained in:
Julian Seward 2017-09-10 12:25:01 +02:00 committed by Emilio Cobos Álvarez
parent 815fb6b058
commit c85633f48e
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
10 changed files with 125 additions and 57 deletions

View file

@ -2,8 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate hashglobe;
extern crate smallvec;
use hashglobe::FailedAllocationError;
use smallvec::Array;
use smallvec::SmallVec;
use std::mem;
@ -17,8 +19,8 @@ extern "C" {
pub trait FallibleVec<T> {
/// Append |val| to the end of |vec|. Returns Ok(()) on success,
/// Err(()) if it fails, which can only be due to lack of memory.
fn try_push(&mut self, value: T) -> Result<(), ()>;
/// Err(reason) if it fails, with |reason| describing the failure.
fn try_push(&mut self, value: T) -> Result<(), FailedAllocationError>;
}
@ -27,7 +29,7 @@ pub trait FallibleVec<T> {
impl<T> FallibleVec<T> for Vec<T> {
#[inline]
fn try_push(&mut self, val: T) -> Result<(), ()> {
fn try_push(&mut self, val: T) -> Result<(), FailedAllocationError> {
if self.capacity() == self.len() {
try_double_vec(self)?;
debug_assert!(self.capacity() > self.len());
@ -38,19 +40,25 @@ impl<T> FallibleVec<T> for Vec<T> {
}
// Double the capacity of |vec|, or fail to do so due to lack of memory.
// Returns Ok(()) on success, Err(()) on failure.
// Returns Ok(()) on success, Err(..) on failure.
#[inline(never)]
#[cold]
fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), ()> {
fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), FailedAllocationError> {
let old_ptr = vec.as_mut_ptr();
let old_len = vec.len();
let old_cap: usize = vec.capacity();
let new_cap: usize =
if old_cap == 0 { 4 } else { old_cap.checked_mul(2).ok_or(()) ? };
let new_cap: usize = if old_cap == 0 {
4
} else {
old_cap.checked_mul(2).ok_or(FailedAllocationError::new(
"capacity overflow for Vec",
))?
};
let new_size_bytes =
new_cap.checked_mul(mem::size_of::<T>()).ok_or(()) ? ;
let new_size_bytes = new_cap.checked_mul(mem::size_of::<T>()).ok_or(
FailedAllocationError::new("capacity overflow for Vec"),
)?;
let new_ptr = unsafe {
if old_cap == 0 {
@ -61,7 +69,9 @@ fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), ()> {
};
if new_ptr.is_null() {
return Err(());
return Err(FailedAllocationError::new(
"out of memory when allocating Vec",
));
}
let new_vec = unsafe {
@ -78,7 +88,7 @@ fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), ()> {
impl<T: Array> FallibleVec<T::Item> for SmallVec<T> {
#[inline]
fn try_push(&mut self, val: T::Item) -> Result<(), ()> {
fn try_push(&mut self, val: T::Item) -> Result<(), FailedAllocationError> {
if self.capacity() == self.len() {
try_double_small_vec(self)?;
debug_assert!(self.capacity() > self.len());
@ -88,11 +98,12 @@ impl<T: Array> FallibleVec<T::Item> for SmallVec<T> {
}
}
// Double the capacity of |vec|, or fail to do so due to lack of memory.
// Returns Ok(()) on success, Err(()) on failure.
// Double the capacity of |svec|, or fail to do so due to lack of memory.
// Returns Ok(()) on success, Err(..) on failure.
#[inline(never)]
#[cold]
fn try_double_small_vec<T>(svec: &mut SmallVec<T>) -> Result<(), ()>
fn try_double_small_vec<T>(svec: &mut SmallVec<T>)
-> Result<(), FailedAllocationError>
where
T: Array,
{
@ -100,16 +111,23 @@ where
let old_len = svec.len();
let old_cap: usize = svec.capacity();
let new_cap: usize =
if old_cap == 0 { 4 } else { old_cap.checked_mul(2).ok_or(()) ? };
let new_cap: usize = if old_cap == 0 {
4
} else {
old_cap.checked_mul(2).ok_or(FailedAllocationError::new(
"capacity overflow for SmallVec",
))?
};
// This surely shouldn't fail, if |old_cap| was previously accepted as a
// valid value. But err on the side of caution.
let old_size_bytes =
old_cap.checked_mul(mem::size_of::<T>()).ok_or(()) ? ;
let old_size_bytes = old_cap.checked_mul(mem::size_of::<T>()).ok_or(
FailedAllocationError::new("capacity overflow for SmallVec"),
)?;
let new_size_bytes =
new_cap.checked_mul(mem::size_of::<T>()).ok_or(()) ? ;
let new_size_bytes = new_cap.checked_mul(mem::size_of::<T>()).ok_or(
FailedAllocationError::new("capacity overflow for SmallVec"),
)?;
let new_ptr;
if svec.spilled() {
@ -130,7 +148,9 @@ where
}
if new_ptr.is_null() {
return Err(());
return Err(FailedAllocationError::new(
"out of memory when allocating SmallVec",
));
}
let new_vec = unsafe {