Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/core/src/alloc.rs
3071 views
1
//! Low-level allocation and OOM-handling utilities.
2
3
mod arc;
4
mod boxed;
5
mod string;
6
mod try_clone;
7
mod try_collect;
8
mod try_new;
9
mod vec;
10
11
pub use boxed::{
12
BoxedSliceFromFallibleIterError, TooFewItemsOrOom, boxed_slice_write_iter,
13
new_boxed_slice_from_fallible_iter, new_boxed_slice_from_iter,
14
new_boxed_slice_from_iter_with_len, new_uninit_boxed_slice,
15
};
16
pub use string::String;
17
pub use try_clone::TryClone;
18
pub use try_collect::{TryCollect, TryExtend, TryFromIterator};
19
pub use try_new::{TryNew, try_new};
20
pub use vec::Vec;
21
22
use crate::error::OutOfMemory;
23
use core::{alloc::Layout, ptr::NonNull};
24
25
/// Try to allocate a block of memory that fits the given layout, or return an
26
/// `OutOfMemory` error.
27
///
28
/// # Safety
29
///
30
/// Same as `alloc::alloc::alloc`: layout must have non-zero size.
31
#[inline]
32
unsafe fn try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
33
// Safety: same as our safety conditions.
34
debug_assert!(layout.size() > 0);
35
let ptr = unsafe { std_alloc::alloc::alloc(layout) };
36
37
if let Some(ptr) = NonNull::new(ptr) {
38
Ok(ptr)
39
} else {
40
Err(OutOfMemory::new(layout.size()))
41
}
42
}
43
44
/// Tries to reallocate a block of memory, returning `OutOfMemory` on failure.
45
///
46
/// Analogue of [`alloc::alloc::realloc`].
47
///
48
/// # Safety
49
///
50
/// Same as `alloc::alloc::realloc`: `ptr` must be allocated with `layout`,
51
/// `layout` must be nonzero in size, and `new_size` must be nonzero and valid.
52
#[inline]
53
unsafe fn try_realloc(
54
ptr: *mut u8,
55
layout: Layout,
56
new_size: usize,
57
) -> Result<NonNull<u8>, OutOfMemory> {
58
// Safety: same as our safety conditions.
59
debug_assert!(layout.size() > 0);
60
debug_assert!(new_size > 0);
61
let ptr = unsafe { std_alloc::alloc::realloc(ptr, layout, new_size) };
62
63
if let Some(ptr) = NonNull::new(ptr) {
64
Ok(ptr)
65
} else {
66
Err(OutOfMemory::new(new_size))
67
}
68
}
69
70
/// An extension trait for ignoring `OutOfMemory` errors.
71
///
72
/// Use this to unwrap a `Result<T, OutOfMemory>` into its inner `T` or
73
/// otherwise panic, leveraging the type system to be sure that you aren't ever
74
/// accidentally unwrapping non-`OutOfMemory` errors.
75
pub trait PanicOnOom {
76
/// The non-`OutOfMemory` result of calling `panic_on_oom`.
77
type Result;
78
79
/// Panic on `OutOfMemory` errors, returning the non-`OutOfMemory` result.
80
fn panic_on_oom(self) -> Self::Result;
81
}
82
83
impl<T> PanicOnOom for Result<T, OutOfMemory> {
84
type Result = T;
85
86
#[track_caller]
87
fn panic_on_oom(self) -> Self::Result {
88
match self {
89
Ok(x) => x,
90
Err(oom) => panic!("unhandled out-of-memory error: {oom}"),
91
}
92
}
93
}
94
95
/// Create a `*mut str` from a pointer and length pair.
96
///
97
/// NB: This function is safe, but dereferencing it or otherwise using the
98
/// resulting `str` pointer's contents is unsafe and requires that the pointer
99
/// be valid for accessing and points to a valid utf8 sequence of `len` bytes.
100
fn str_ptr_from_raw_parts(ptr: *mut u8, len: usize) -> *mut str {
101
let ptr: *mut [u8] = core::ptr::slice_from_raw_parts_mut(ptr, len);
102
str_ptr_from_slice_ptr(ptr)
103
}
104
105
/// Create a `*mut str` from a slice pointer.
106
///
107
/// NB: This function is safe, but dereferencing it or otherwise using the
108
/// resulting `str` pointer's contents is unsafe and requires that the pointer
109
/// be valid for accessing and points to a valid utf8 sequence of `len` bytes.
110
fn str_ptr_from_slice_ptr(ptr: *mut [u8]) -> *mut str {
111
// SAFETY: `str` is a newtype of `[u8]`.
112
let ptr: *mut str = unsafe { core::mem::transmute(ptr) };
113
ptr
114
}
115
116