bump_scope/alloc/
system.rs1use core::{
2 alloc::{GlobalAlloc, Layout},
3 hint,
4 ptr::{self, NonNull},
5};
6use std::alloc::System;
7
8use crate::polyfill;
9
10use super::{AllocError, Allocator};
11
12unsafe impl Allocator for System {
15 #[inline]
16 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
17 alloc_impl(layout, false)
18 }
19
20 #[inline]
21 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
22 alloc_impl(layout, true)
23 }
24
25 #[inline]
26 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
27 if layout.size() != 0 {
28 unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) }
31 }
32 }
33
34 #[inline]
35 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
36 unsafe { grow_impl(ptr, old_layout, new_layout, false) }
38 }
39
40 #[inline]
41 unsafe fn grow_zeroed(
42 &self,
43 ptr: NonNull<u8>,
44 old_layout: Layout,
45 new_layout: Layout,
46 ) -> Result<NonNull<[u8]>, AllocError> {
47 unsafe { grow_impl(ptr, old_layout, new_layout, true) }
49 }
50
51 #[inline]
52 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
53 debug_assert!(
54 new_layout.size() <= old_layout.size(),
55 "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
56 );
57
58 match new_layout.size() {
59 0 => unsafe {
61 Allocator::deallocate(self, ptr, old_layout);
62 Ok(NonNull::slice_from_raw_parts(polyfill::layout::dangling(new_layout), 0))
63 },
64
65 new_size if old_layout.align() == new_layout.align() => unsafe {
67 hint::assert_unchecked(new_size <= old_layout.size());
69
70 let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
71 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
72 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
73 },
74
75 new_size => unsafe {
81 let new_ptr = Allocator::allocate(self, new_layout)?;
82 ptr::copy_nonoverlapping(ptr.as_ptr(), polyfill::non_null::as_mut_ptr(new_ptr), new_size);
83 Allocator::deallocate(self, ptr, old_layout);
84 Ok(new_ptr)
85 },
86 }
87 }
88}
89
90#[inline]
91fn alloc_impl(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
92 match layout.size() {
93 0 => Ok(NonNull::slice_from_raw_parts(polyfill::layout::dangling(layout), 0)),
94 size => unsafe {
96 let raw_ptr = if zeroed {
97 GlobalAlloc::alloc_zeroed(&System, layout)
98 } else {
99 GlobalAlloc::alloc(&System, layout)
100 };
101 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
102 Ok(NonNull::slice_from_raw_parts(ptr, size))
103 },
104 }
105}
106
107#[inline]
109unsafe fn grow_impl(
110 ptr: NonNull<u8>,
111 old_layout: Layout,
112 new_layout: Layout,
113 zeroed: bool,
114) -> Result<NonNull<[u8]>, AllocError> {
115 debug_assert!(
116 new_layout.size() >= old_layout.size(),
117 "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
118 );
119
120 match old_layout.size() {
121 0 => alloc_impl(new_layout, zeroed),
122
123 old_size if old_layout.align() == new_layout.align() => unsafe {
127 let new_size = new_layout.size();
128
129 hint::assert_unchecked(new_size >= old_layout.size());
131
132 let raw_ptr = GlobalAlloc::realloc(&System, ptr.as_ptr(), old_layout, new_size);
133 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
134 if zeroed {
135 raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
136 }
137 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
138 },
139
140 old_size => unsafe {
146 let new_ptr = alloc_impl(new_layout, zeroed)?;
147 ptr::copy_nonoverlapping(ptr.as_ptr(), polyfill::non_null::as_mut_ptr(new_ptr), old_size);
148 Allocator::deallocate(&System, ptr, old_layout);
149 Ok(new_ptr)
150 },
151 }
152}