1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Basic functions for dealing with memory
13 //! This module contains functions for querying the size and alignment of
14 //! types, initializing and manipulating memory.
18 use intrinsics::{bswap16, bswap32, bswap64};
20 pub use intrinsics::transmute;
22 /// Returns the size of a type in bytes.
25 pub fn size_of<T>() -> uint {
26 unsafe { intrinsics::size_of::<T>() }
29 /// Returns the size of the type that `_val` points to in bytes.
32 pub fn size_of_val<T>(_val: &T) -> uint {
36 /// Deprecated, this function will be removed soon
38 #[deprecated = "this function will be removed soon"]
39 pub fn nonzero_size_of<T>() -> uint {
40 match size_of::<T>() {
46 /// Deprecated, this function will be removed soon
48 #[deprecated = "this function will be removed soon"]
49 pub fn nonzero_size_of_val<T>(val: &T) -> uint {
50 match size_of_val::<T>(val) {
56 /// Returns the ABI-required minimum alignment of a type
58 /// This is the alignment used for struct fields. It may be smaller
59 /// than the preferred alignment.
62 pub fn min_align_of<T>() -> uint {
63 unsafe { intrinsics::min_align_of::<T>() }
66 /// Returns the ABI-required minimum alignment of the type of the value that
70 pub fn min_align_of_val<T>(_val: &T) -> uint {
74 /// Returns the alignment in memory for a type.
76 /// This function will return the alignment, in bytes, of a type in memory. If
77 /// the alignment returned is adhered to, then the type is guaranteed to
78 /// function properly.
81 pub fn align_of<T>() -> uint {
82 // We use the preferred alignment as the default alignment for a type. This
83 // appears to be what clang migrated towards as well:
85 // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
86 unsafe { intrinsics::pref_align_of::<T>() }
89 /// Returns the alignment of the type of the value that `_val` points to.
91 /// This is similar to `align_of`, but function will properly handle types such
92 /// as trait objects (in the future), returning the alignment for an arbitrary
96 pub fn align_of_val<T>(_val: &T) -> uint {
100 /// Deprecated, this function has been renamed to align_of
102 #[deprecated = "use mem::align_of instead"]
103 pub fn pref_align_of<T>() -> uint { align_of::<T>() }
105 /// Deprecated, this function has been renamed to align_of_val
107 #[deprecated = "use mem::align_of_val instead"]
108 pub fn pref_align_of_val<T>(val: &T) -> uint { align_of_val(val) }
110 /// Create a value initialized to zero.
112 /// This function is similar to allocating space for a a local variable and
113 /// zeroing it out (an unsafe operation).
115 /// Care must be taken when using this function, if the type `T` has a
116 /// destructor and the value falls out of scope (due to unwinding or returning)
117 /// before being initialized, then the destructor will run on zeroed
118 /// data, likely leading to crashes.
120 /// This is useful for FFI functions sometimes, but should generally be avoided.
123 pub unsafe fn zeroed<T>() -> T {
127 /// Deprecated, use zeroed() instead
129 #[deprecated = "this function has been renamed to zeroed()"]
130 pub unsafe fn init<T>() -> T { zeroed() }
132 /// Create an uninitialized value.
134 /// Care must be taken when using this function, if the type `T` has a
135 /// destructor and the value falls out of scope (due to unwinding or returning)
136 /// before being initialized, then the destructor will run on uninitialized
137 /// data, likely leading to crashes.
139 /// This is useful for FFI functions sometimes, but should generally be avoided.
142 pub unsafe fn uninitialized<T>() -> T {
146 /// Deprecated, use `uninitialized` instead.
148 #[deprecated = "this function has been renamed to `uninitialized`"]
149 pub unsafe fn uninit<T>() -> T {
153 /// Unsafely overwrite a memory location with the given value without destroying
156 /// This operation is unsafe because it does not destroy the previous value
157 /// contained at the location `dst`. This could leak allocations or resources,
158 /// so care must be taken to previously deallocate the value at `dst`.
160 #[deprecated = "use ptr::write"]
161 pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
162 intrinsics::move_val_init(&mut *dst, src)
165 /// Deprecated, use `overwrite` instead
167 #[deprecated = "use ptr::write"]
168 pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
172 /// Convert an u16 to little endian from the target's endianness.
174 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
175 #[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x }
177 /// Convert an u16 to little endian from the target's endianness.
179 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
180 #[cfg(target_endian = "big")] #[inline] #[stable]
181 pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
183 /// Convert an u32 to little endian from the target's endianness.
185 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
186 #[cfg(target_endian = "little")] #[inline] #[stable]
187 pub fn to_le32(x: u32) -> u32 { x }
189 /// Convert an u32 to little endian from the target's endianness.
191 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
192 #[cfg(target_endian = "big")] #[inline] #[stable]
193 pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
195 /// Convert an u64 to little endian from the target's endianness.
197 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
198 #[cfg(target_endian = "little")] #[inline] #[stable]
199 pub fn to_le64(x: u64) -> u64 { x }
201 /// Convert an u64 to little endian from the target's endianness.
203 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
204 #[cfg(target_endian = "big")] #[inline] #[stable]
205 pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
208 /// Convert an u16 to big endian from the target's endianness.
210 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
211 #[cfg(target_endian = "little")] #[inline] #[stable]
212 pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
214 /// Convert an u16 to big endian from the target's endianness.
216 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
217 #[cfg(target_endian = "big")] #[inline] #[stable]
218 pub fn to_be16(x: u16) -> u16 { x }
220 /// Convert an u32 to big endian from the target's endianness.
222 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
223 #[cfg(target_endian = "little")] #[inline] #[stable]
224 pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
226 /// Convert an u32 to big endian from the target's endianness.
228 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
229 #[cfg(target_endian = "big")] #[inline] #[stable]
230 pub fn to_be32(x: u32) -> u32 { x }
232 /// Convert an u64 to big endian from the target's endianness.
234 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
235 #[cfg(target_endian = "little")] #[inline] #[stable]
236 pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
238 /// Convert an u64 to big endian from the target's endianness.
240 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
241 #[cfg(target_endian = "big")] #[inline] #[stable]
242 pub fn to_be64(x: u64) -> u64 { x }
245 /// Convert an u16 from little endian to the target's endianness.
247 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
248 #[cfg(target_endian = "little")] #[inline] #[stable]
249 pub fn from_le16(x: u16) -> u16 { x }
251 /// Convert an u16 from little endian to the target's endianness.
253 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
254 #[cfg(target_endian = "big")] #[inline] #[stable]
255 pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
257 /// Convert an u32 from little endian to the target's endianness.
259 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
260 #[cfg(target_endian = "little")] #[inline] #[stable]
261 pub fn from_le32(x: u32) -> u32 { x }
263 /// Convert an u32 from little endian to the target's endianness.
265 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
266 #[cfg(target_endian = "big")] #[inline] #[stable]
267 pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
269 /// Convert an u64 from little endian to the target's endianness.
271 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
272 #[cfg(target_endian = "little")] #[inline] #[stable]
273 pub fn from_le64(x: u64) -> u64 { x }
275 /// Convert an u64 from little endian to the target's endianness.
277 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
278 #[cfg(target_endian = "big")] #[inline] #[stable]
279 pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
282 /// Convert an u16 from big endian to the target's endianness.
284 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
285 #[cfg(target_endian = "little")] #[inline] #[stable]
286 pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
288 /// Convert an u16 from big endian to the target's endianness.
290 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
291 #[cfg(target_endian = "big")] #[inline] #[stable]
292 pub fn from_be16(x: u16) -> u16 { x }
294 /// Convert an u32 from big endian to the target's endianness.
296 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
297 #[cfg(target_endian = "little")] #[inline] #[stable]
298 pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
300 /// Convert an u32 from big endian to the target's endianness.
302 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
303 #[cfg(target_endian = "big")] #[inline] #[stable]
304 pub fn from_be32(x: u32) -> u32 { x }
306 /// Convert an u64 from big endian to the target's endianness.
308 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
309 #[cfg(target_endian = "little")] #[inline] #[stable]
310 pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
312 /// Convert an u64 from big endian to the target's endianness.
314 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
315 #[cfg(target_endian = "big")] #[inline] #[stable]
316 pub fn from_be64(x: u64) -> u64 { x }
319 * Swap the values at two mutable locations of the same type, without
320 * deinitialising or copying either one.
324 pub fn swap<T>(x: &mut T, y: &mut T) {
326 // Give ourselves some scratch space to work with
327 let mut t: T = uninitialized();
329 // Perform the swap, `&mut` pointers never alias
330 ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
331 ptr::copy_nonoverlapping_memory(x, &*y, 1);
332 ptr::copy_nonoverlapping_memory(y, &t, 1);
334 // y and t now point to the same thing, but we need to completely forget `t`
335 // because it's no longer relevant.
341 * Replace the value at a mutable location with a new one, returning the old
342 * value, without deinitialising or copying either one.
344 * This is primarily used for transferring and swapping ownership of a value
345 * in a mutable location. For example, this function allows consumption of
346 * one field of a struct by replacing it with another value. The normal approach
347 * doesn't always work:
350 * struct Buffer<T> { buf: Vec<T> }
352 * impl<T> Buffer<T> {
353 * fn get_and_reset(&mut self) -> Vec<T> {
354 * // error: cannot move out of dereference of `&mut`-pointer
355 * let buf = self.buf;
356 * self.buf = Vec::new();
362 * Note that `T` does not necessarily implement `Clone`, so it can't even
363 * clone and reset `self.buf`. But `replace` can be used to disassociate
364 * the original value of `self.buf` from `self`, allowing it to be returned:
367 * # struct Buffer<T> { buf: Vec<T> }
368 * impl<T> Buffer<T> {
369 * fn get_and_reset(&mut self) -> Vec<T> {
370 * use std::mem::replace;
371 * replace(&mut self.buf, Vec::new())
378 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
379 swap(dest, &mut src);
383 /// Disposes of a value.
385 /// This function can be used to destroy any value by allowing `drop` to take
386 /// ownership of its argument.
391 /// use std::cell::RefCell;
393 /// let x = RefCell::new(1);
395 /// let mut mutable_borrow = x.borrow_mut();
396 /// *mutable_borrow = 1;
397 /// drop(mutable_borrow); // relinquish the mutable borrow on this slot
399 /// let borrow = x.borrow();
400 /// println!("{}", *borrow);
404 pub fn drop<T>(_x: T) { }
406 /// Moves a thing into the void.
408 /// The forget function will take ownership of the provided value but neglect
409 /// to run any required cleanup or memory management operations on it.
411 /// This function is the unsafe version of the `drop` function because it does
412 /// not run any destructors.
415 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing) }
417 /// Interprets `src` as `&U`, and then reads `src` without moving the contained
420 /// This function will unsafely assume the pointer `src` is valid for
421 /// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
422 /// will also unsafely create a copy of the contained value instead of moving
425 /// It is not a compile-time error if `T` and `U` have different sizes, but it
426 /// is highly encouraged to only invoke this function where `T` and `U` have the
427 /// same size. This function triggers undefined behavior if `U` is larger than
431 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
432 ptr::read(src as *T as *U)
435 /// Transforms lifetime of the second pointer to match the first.
437 #[unstable = "this function may be removed in the future due to its \
438 questionable utility"]
439 pub unsafe fn copy_lifetime<'a, S, T>(_ptr: &'a S, ptr: &T) -> &'a T {
443 /// Transforms lifetime of the second mutable pointer to match the first.
445 #[unstable = "this function may be removed in the future due to its \
446 questionable utility"]
447 pub unsafe fn copy_mut_lifetime<'a, S, T>(_ptr: &'a mut S,
448 ptr: &mut T) -> &'a mut T {
455 use option::{Some,None};
456 use realstd::str::StrAllocating;
457 use realstd::owned::Box;
458 use realstd::vec::Vec;
463 assert_eq!(size_of::<u8>(), 1u);
464 assert_eq!(size_of::<u16>(), 2u);
465 assert_eq!(size_of::<u32>(), 4u);
466 assert_eq!(size_of::<u64>(), 8u);
470 #[cfg(target_arch = "x86")]
471 #[cfg(target_arch = "arm")]
472 #[cfg(target_arch = "mips")]
474 assert_eq!(size_of::<uint>(), 4u);
475 assert_eq!(size_of::<*uint>(), 4u);
479 #[cfg(target_arch = "x86_64")]
481 assert_eq!(size_of::<uint>(), 8u);
482 assert_eq!(size_of::<*uint>(), 8u);
486 fn size_of_val_basic() {
487 assert_eq!(size_of_val(&1u8), 1);
488 assert_eq!(size_of_val(&1u16), 2);
489 assert_eq!(size_of_val(&1u32), 4);
490 assert_eq!(size_of_val(&1u64), 8);
494 fn align_of_basic() {
495 assert_eq!(align_of::<u8>(), 1u);
496 assert_eq!(align_of::<u16>(), 2u);
497 assert_eq!(align_of::<u32>(), 4u);
501 #[cfg(target_arch = "x86")]
502 #[cfg(target_arch = "arm")]
503 #[cfg(target_arch = "mips")]
505 assert_eq!(align_of::<uint>(), 4u);
506 assert_eq!(align_of::<*uint>(), 4u);
510 #[cfg(target_arch = "x86_64")]
512 assert_eq!(align_of::<uint>(), 8u);
513 assert_eq!(align_of::<*uint>(), 8u);
517 fn align_of_val_basic() {
518 assert_eq!(align_of_val(&1u8), 1u);
519 assert_eq!(align_of_val(&1u16), 2u);
520 assert_eq!(align_of_val(&1u32), 4u);
527 swap(&mut x, &mut y);
529 assert_eq!(y, 31337);
534 let mut x = Some("test".to_string());
535 let y = replace(&mut x, None);
536 assert!(x.is_none());
537 assert!(y.is_some());
541 fn test_transmute_copy() {
542 assert_eq!(1u, unsafe { ::mem::transmute_copy(&1) });
546 fn test_transmute() {
550 let a = box 100 as Box<Foo>;
552 let x: raw::TraitObject = transmute(a);
553 assert!(*(x.data as *int) == 100);
554 let _x: Box<Foo> = transmute(x);
558 assert!(Vec::from_slice([76u8]) == transmute("L".to_string()));
563 // FIXME #13642 (these benchmarks should be in another place)
564 /// Completely miscellaneous language-construct benchmarks.
568 use self::test::Bencher;
569 use option::{Some,None};
571 // Static/dynamic method dispatch
578 fn method(&self) -> int;
581 impl Trait for Struct {
582 fn method(&self) -> int {
588 fn trait_vtable_method_call(b: &mut Bencher) {
589 let s = Struct { field: 10 };
590 let t = &s as &Trait;
597 fn trait_static_method_call(b: &mut Bencher) {
598 let s = Struct { field: 10 };
604 // Overhead of various match forms
607 fn match_option_some(b: &mut Bencher) {
618 fn match_vec_pattern(b: &mut Bencher) {
619 let x = [1,2,3,4,5,6];