+ #[inline]
+ unsafe fn alloc_zeroed(&mut self, layout: Layout)
+ -> Result<*mut u8, AllocErr>
+ {
+ if layout.align() <= MIN_ALIGN {
+ let ptr = libc::calloc(layout.size(), 1) as *mut u8;
+ if !ptr.is_null() {
+ Ok(ptr)
+ } else {
+ Err(AllocErr::Exhausted { request: layout })
+ }
+ } else {
+ let ret = self.alloc(layout.clone());
+ if let Ok(ptr) = ret {
+ ptr::write_bytes(ptr, 0, layout.size());
+ }
+ ret
+ }
+ }
+
+ #[inline]
+ unsafe fn dealloc(&mut self, ptr: *mut u8, _layout: Layout) {
+ libc::free(ptr as *mut libc::c_void)
+ }
+
+ #[inline]
+ unsafe fn realloc(&mut self,
+ ptr: *mut u8,
+ old_layout: Layout,
+ new_layout: Layout) -> Result<*mut u8, AllocErr> {
+ if old_layout.align() != new_layout.align() {
+ return Err(AllocErr::Unsupported {
+ details: "cannot change alignment on `realloc`",
+ })
+ }
+
+ if new_layout.align() <= MIN_ALIGN {
+ let ptr = libc::realloc(ptr as *mut libc::c_void, new_layout.size());
+ if !ptr.is_null() {
+ Ok(ptr as *mut u8)
+ } else {
+ Err(AllocErr::Exhausted { request: new_layout })
+ }
+ } else {
+ let res = self.alloc(new_layout.clone());
+ if let Ok(new_ptr) = res {
+ let size = cmp::min(old_layout.size(), new_layout.size());
+ ptr::copy_nonoverlapping(ptr, new_ptr, size);
+ self.dealloc(ptr, old_layout);
+ }
+ res
+ }
+ }
+
+ fn oom(&mut self, err: AllocErr) -> ! {
+ use core::fmt::{self, Write};
+
+ // Print a message to stderr before aborting to assist with
+ // debugging. It is critical that this code does not allocate any
+ // memory since we are in an OOM situation. Any errors are ignored
+ // while printing since there's nothing we can do about them and we
+ // are about to exit anyways.
+ drop(writeln!(Stderr, "fatal runtime error: {}", err));
+ unsafe {
+ ::core::intrinsics::abort();
+ }
+
+ struct Stderr;
+
+ impl Write for Stderr {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ unsafe {
+ libc::write(libc::STDERR_FILENO,
+ s.as_ptr() as *const libc::c_void,
+ s.len());
+ }
+ Ok(())
+ }
+ }