Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/core/src/error/oom.rs
3071 views
1
use crate::error::{Error, OomOrDynError};
2
use core::{fmt, mem, ptr::NonNull};
3
4
/// Out-of-memory error.
5
///
6
/// This error is the sentinel for allocation failure due to memory exhaustion.
7
///
8
/// Constructing an [`Error`] from an `OutOfMemory` does not
9
/// allocate.
10
///
11
/// Allocation failure inside any `Error` method that must allocate
12
/// (e.g. [`Error::context`]) will propagate an `OutOfMemory` error.
13
#[derive(Clone, Copy)]
14
// NB: `OutOfMemory`'s representation must be the same as `OomOrDynError`
15
// (and therefore also `Error`).
16
#[repr(transparent)]
17
pub struct OutOfMemory {
18
inner: NonNull<u8>,
19
}
20
21
// Safety: The `inner` pointer is not a real pointer, it is just bitpacked size
22
// data.
23
unsafe impl Send for OutOfMemory {}
24
25
// Safety: The `inner` pointer is not a real pointer, it is just bitpacked size
26
// data.
27
unsafe impl Sync for OutOfMemory {}
28
29
impl fmt::Debug for OutOfMemory {
30
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31
f.debug_struct("OutOfMemory")
32
.field(
33
"requested_allocation_size",
34
&self.requested_allocation_size(),
35
)
36
.finish()
37
}
38
}
39
40
impl fmt::Display for OutOfMemory {
41
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42
write!(
43
f,
44
"out of memory (failed to allocate {} bytes)",
45
self.requested_allocation_size()
46
)
47
}
48
}
49
50
impl core::error::Error for OutOfMemory {
51
#[inline]
52
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
53
None
54
}
55
}
56
57
impl OutOfMemory {
58
// NB: `OutOfMemory`'s representation must be the same as `OomOrDynError`
59
// (and therefore also `Error`).
60
const _SAME_SIZE_AS_OOM_OR_DYN_ERROR: () =
61
assert!(mem::size_of::<OutOfMemory>() == mem::size_of::<OomOrDynError>());
62
const _SAME_ALIGN_AS_OOM_OR_DYN_ERROR: () =
63
assert!(mem::align_of::<OutOfMemory>() == mem::align_of::<OomOrDynError>());
64
const _SAME_SIZE_AS_ERROR: () =
65
assert!(mem::size_of::<OutOfMemory>() == mem::size_of::<Error>());
66
const _SAME_ALIGN_AS_ERROR: () =
67
assert!(mem::align_of::<OutOfMemory>() == mem::align_of::<Error>());
68
69
/// Construct a new `OutOfMemory` error.
70
///
71
/// The `requested_allocation_size` argument should be the size (in bytes)
72
/// of the associated allocation that was attempted and failed.
73
///
74
/// This operation does not allocate.
75
///
76
/// # Example
77
///
78
/// ```rust
79
/// # use wasmtime_internal_core::error::OutOfMemory;
80
/// # extern crate alloc;
81
/// use alloc::alloc::{Layout, alloc};
82
/// use core::ptr::NonNull;
83
///
84
/// /// Attempt to allocate a block of memory from the global allocator,
85
/// /// returning an `OutOfMemory` error on failure.
86
/// fn try_global_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
87
/// if layout.size() == 0 {
88
/// return Ok(NonNull::dangling());
89
/// }
90
///
91
/// // Safety: the layout's size is non-zero.
92
/// let ptr = unsafe { alloc(layout) };
93
///
94
/// if let Some(ptr) = NonNull::new(ptr) {
95
/// Ok(ptr)
96
/// } else {
97
/// // The allocation failed, so return an `OutOfMemory` error,
98
/// // passing the attempted allocation's size into the `OutOfMemory`
99
/// // constructor.
100
/// Err(OutOfMemory::new(layout.size()))
101
/// }
102
/// }
103
/// ```
104
#[inline]
105
pub const fn new(requested_allocation_size: usize) -> Self {
106
Self {
107
inner: OomOrDynError::new_oom_ptr(requested_allocation_size),
108
}
109
}
110
111
/// Get the size (in bytes) of the associated allocation that was attempted
112
/// and which failed.
113
///
114
/// Very large allocation sizes (near `isize::MAX` and larger) may be capped
115
/// to a maximum value.
116
///
117
/// # Example
118
///
119
/// ```rust
120
/// # use wasmtime_internal_core::error::OutOfMemory;
121
/// let oom = OutOfMemory::new(8192);
122
/// assert_eq!(oom.requested_allocation_size(), 8192);
123
/// ```
124
#[inline]
125
pub fn requested_allocation_size(&self) -> usize {
126
OomOrDynError::oom_size(self.inner)
127
}
128
}
129
130
impl From<OutOfMemory> for OomOrDynError {
131
fn from(oom: OutOfMemory) -> Self {
132
OomOrDynError::new_oom(oom.inner)
133
}
134
}
135
136