(index<- )        ./libcore/mem.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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.
   4  //
   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.
  10  
  11  //! Basic functions for dealing with memory
  12  //!
  13  //! This module contains functions for querying the size and alignment of
  14  //! types, initializing and manipulating memory.
  15  
  16  use cast;
  17  use ptr;
  18  use intrinsics;
  19  use intrinsics::{bswap16, bswap32, bswap64};
  20  
  21  /// Returns the size of a type in bytes.
  22  #[inline]
  23  pub fn size_of<T>() -> uint {
  24      unsafe { intrinsics::size_of::<T>() }
  25  }
  26  
  27  /// Returns the size of the type that `_val` points to in bytes.
  28  #[inline]
  29  pub fn size_of_val<T>(_val: &T) -> uint {
  30      size_of::<T>()
  31  }
  32  
  33  /// Returns the size of a type in bytes, or 1 if the actual size is zero.
  34  ///
  35  /// Useful for building structures containing variable-length arrays.
  36  #[inline]
  37  pub fn nonzero_size_of<T>() -> uint {
  38      match size_of::<T>() {
  39          0 => 1,
  40          x => x
  41      }
  42  }
  43  
  44  /// Returns the size in bytes of the type of the value that `_val` points to.
  45  #[inline]
  46  pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
  47      nonzero_size_of::<T>()
  48  }
  49  
  50  /// Returns the ABI-required minimum alignment of a type
  51  ///
  52  /// This is the alignment used for struct fields. It may be smaller
  53  /// than the preferred alignment.
  54  #[inline]
  55  pub fn min_align_of<T>() -> uint {
  56      unsafe { intrinsics::min_align_of::<T>() }
  57  }
  58  
  59  /// Returns the ABI-required minimum alignment of the type of the value that
  60  /// `_val` points to
  61  #[inline]
  62  pub fn min_align_of_val<T>(_val: &T) -> uint {
  63      min_align_of::<T>()
  64  }
  65  
  66  /// Returns the preferred alignment of a type
  67  #[inline]
  68  pub fn pref_align_of<T>() -> uint {
  69      unsafe { intrinsics::pref_align_of::<T>() }
  70  }
  71  
  72  /// Returns the preferred alignment of the type of the value that
  73  /// `_val` points to
  74  #[inline]
  75  pub fn pref_align_of_val<T>(_val: &T) -> uint {
  76      pref_align_of::<T>()
  77  }
  78  
  79  /// Create a value initialized to zero.
  80  ///
  81  /// `init` is unsafe because it returns a zeroed-out datum,
  82  /// which is unsafe unless T is Copy.
  83  #[inline]
  84  pub unsafe fn init<T>() -> T {
  85      intrinsics::init()
  86  }
  87  
  88  /// Create an uninitialized value.
  89  #[inline]
  90  pub unsafe fn uninit<T>() -> T {
  91      intrinsics::uninit()
  92  }
  93  
  94  /// Move a value to an uninitialized memory location.
  95  ///
  96  /// Drop glue is not run on the destination.
  97  #[inline]
  98  pub unsafe fn move_val_init<T>(dst: &mut T, srcT) {
  99      intrinsics::move_val_init(dst, src)
 100  }
 101  
 102  /// Convert an u16 to little endian from the target's endianness.
 103  ///
 104  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 105  #[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x }
 106  
 107  /// Convert an u16 to little endian from the target's endianness.
 108  ///
 109  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 110  #[cfg(target_endian = "big")]    #[inline] pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
 111  
 112  /// Convert an u32 to little endian from the target's endianness.
 113  ///
 114  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 115  #[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: u32) -> u32 { x }
 116  
 117  /// Convert an u32 to little endian from the target's endianness.
 118  ///
 119  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 120  #[cfg(target_endian = "big")]    #[inline] pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
 121  
 122  /// Convert an u64 to little endian from the target's endianness.
 123  ///
 124  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 125  #[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: u64) -> u64 { x }
 126  
 127  /// Convert an u64 to little endian from the target's endianness.
 128  ///
 129  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 130  #[cfg(target_endian = "big")]    #[inline] pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
 131  
 132  
 133  /// Convert an u16 to big endian from the target's endianness.
 134  ///
 135  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 136  #[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
 137  
 138  /// Convert an u16 to big endian from the target's endianness.
 139  ///
 140  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 141  #[cfg(target_endian = "big")]    #[inline] pub fn to_be16(x: u16) -> u16 { x }
 142  
 143  /// Convert an u32 to big endian from the target's endianness.
 144  ///
 145  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 146  #[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
 147  
 148  /// Convert an u32 to big endian from the target's endianness.
 149  ///
 150  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 151  #[cfg(target_endian = "big")]    #[inline] pub fn to_be32(x: u32) -> u32 { x }
 152  
 153  /// Convert an u64 to big endian from the target's endianness.
 154  ///
 155  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 156  #[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
 157  
 158  /// Convert an u64 to big endian from the target's endianness.
 159  ///
 160  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 161  #[cfg(target_endian = "big")]    #[inline] pub fn to_be64(x: u64) -> u64 { x }
 162  
 163  
 164  /// Convert an u16 from little endian to the target's endianness.
 165  ///
 166  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 167  #[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: u16) -> u16 { x }
 168  
 169  /// Convert an u16 from little endian to the target's endianness.
 170  ///
 171  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 172  #[cfg(target_endian = "big")]    #[inline] pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
 173  
 174  /// Convert an u32 from little endian to the target's endianness.
 175  ///
 176  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 177  #[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: u32) -> u32 { x }
 178  
 179  /// Convert an u32 from little endian to the target's endianness.
 180  ///
 181  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 182  #[cfg(target_endian = "big")]    #[inline] pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
 183  
 184  /// Convert an u64 from little endian to the target's endianness.
 185  ///
 186  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 187  #[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: u64) -> u64 { x }
 188  
 189  /// Convert an u64 from little endian to the target's endianness.
 190  ///
 191  /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
 192  #[cfg(target_endian = "big")]    #[inline] pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
 193  
 194  
 195  /// Convert an u16 from big endian to the target's endianness.
 196  ///
 197  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 198  #[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
 199  
 200  /// Convert an u16 from big endian to the target's endianness.
 201  ///
 202  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 203  #[cfg(target_endian = "big")]    #[inline] pub fn from_be16(x: u16) -> u16 { x }
 204  
 205  /// Convert an u32 from big endian to the target's endianness.
 206  ///
 207  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 208  #[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
 209  
 210  /// Convert an u32 from big endian to the target's endianness.
 211  ///
 212  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 213  #[cfg(target_endian = "big")]    #[inline] pub fn from_be32(x: u32) -> u32 { x }
 214  
 215  /// Convert an u64 from big endian to the target's endianness.
 216  ///
 217  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 218  #[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
 219  
 220  /// Convert an u64 from big endian to the target's endianness.
 221  ///
 222  /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
 223  #[cfg(target_endian = "big")]    #[inline] pub fn from_be64(x: u64) -> u64 { x }
 224  
 225  /**
 226   * Swap the values at two mutable locations of the same type, without
 227   * deinitialising or copying either one.
 228   */
 229  #[inline]
 230  pub fn swap<T>(x: &mut T, y: &mut T) {
 231      unsafe {
 232          // Give ourselves some scratch space to work with
 233          let mut tT = uninit();
 234  
 235          // Perform the swap, `&mut` pointers never alias
 236          ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
 237          ptr::copy_nonoverlapping_memory(x, &*y, 1);
 238          ptr::copy_nonoverlapping_memory(y, &t, 1);
 239  
 240          // y and t now point to the same thing, but we need to completely forget `t`
 241          // because it's no longer relevant.
 242          cast::forget(t);
 243      }
 244  }
 245  
 246  /**
 247   * Replace the value at a mutable location with a new one, returning the old
 248   * value, without deinitialising or copying either one.
 249   *
 250   * This is primarily used for transferring and swapping ownership of a value
 251   * in a mutable location. For example, this function allows consumption of
 252   * one field of a struct by replacing it with another value. The normal approach
 253   * doesn't always work:
 254   *
 255   * ```rust,ignore
 256   * struct Buffer<T> { buf: Vec<T> }
 257   *
 258   * impl<T> Buffer<T> {
 259   *     fn get_and_reset(&mut self) -> Vec<T> {
 260   *         // error: cannot move out of dereference of `&mut`-pointer
 261   *         let buf = self.buf;
 262   *         self.buf = Vec::new();
 263   *         buf
 264   *     }
 265   * }
 266   * ```
 267   *
 268   * Note that `T` does not necessarily implement `Clone`, so it can't even
 269   * clone and reset `self.buf`. But `replace` can be used to disassociate
 270   * the original value of `self.buf` from `self`, allowing it to be returned:
 271   *
 272   * ```rust
 273   * # struct Buffer<T> { buf: Vec<T> }
 274   * impl<T> Buffer<T> {
 275   *     fn get_and_reset(&mut self) -> Vec<T> {
 276   *         use std::mem::replace;
 277   *         replace(&mut self.buf, Vec::new())
 278   *     }
 279   * }
 280   * ```
 281   */
 282  #[inline]
 283  pub fn replace<T>(dest: &mut T, mut srcT) -> T {
 284      swap(dest, &mut src);
 285      src
 286  }
 287  
 288  /// Disposes of a value.
 289  #[inline]
 290  pub fn drop<T>(_xT) { }
 291  
 292  #[cfg(test)]
 293  mod tests {
 294      use mem::*;
 295      use option::{Some,None};
 296      use realstd::str::StrAllocating;
 297  
 298      #[test]
 299      fn size_of_basic() {
 300          assert_eq!(size_of::<u8>(), 1u);
 301          assert_eq!(size_of::<u16>(), 2u);
 302          assert_eq!(size_of::<u32>(), 4u);
 303          assert_eq!(size_of::<u64>(), 8u);
 304      }
 305  
 306      #[test]
 307      #[cfg(target_arch = "x86")]
 308      #[cfg(target_arch = "arm")]
 309      #[cfg(target_arch = "mips")]
 310      fn size_of_32() {
 311          assert_eq!(size_of::<uint>(), 4u);
 312          assert_eq!(size_of::<*uint>(), 4u);
 313      }
 314  
 315      #[test]
 316      #[cfg(target_arch = "x86_64")]
 317      fn size_of_64() {
 318          assert_eq!(size_of::<uint>(), 8u);
 319          assert_eq!(size_of::<*uint>(), 8u);
 320      }
 321  
 322      #[test]
 323      fn size_of_val_basic() {
 324          assert_eq!(size_of_val(&1u8), 1);
 325          assert_eq!(size_of_val(&1u16), 2);
 326          assert_eq!(size_of_val(&1u32), 4);
 327          assert_eq!(size_of_val(&1u64), 8);
 328      }
 329  
 330      #[test]
 331      fn nonzero_size_of_basic() {
 332          type Z = [i8, ..0];
 333          assert_eq!(size_of::<Z>(), 0u);
 334          assert_eq!(nonzero_size_of::<Z>(), 1u);
 335          assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
 336      }
 337  
 338      #[test]
 339      fn nonzero_size_of_val_basic() {
 340          let z = [0u8, ..0];
 341          assert_eq!(size_of_val(&z), 0u);
 342          assert_eq!(nonzero_size_of_val(&z), 1u);
 343          assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
 344      }
 345  
 346      #[test]
 347      fn align_of_basic() {
 348          assert_eq!(pref_align_of::<u8>(), 1u);
 349          assert_eq!(pref_align_of::<u16>(), 2u);
 350          assert_eq!(pref_align_of::<u32>(), 4u);
 351      }
 352  
 353      #[test]
 354      #[cfg(target_arch = "x86")]
 355      #[cfg(target_arch = "arm")]
 356      #[cfg(target_arch = "mips")]
 357      fn align_of_32() {
 358          assert_eq!(pref_align_of::<uint>(), 4u);
 359          assert_eq!(pref_align_of::<*uint>(), 4u);
 360      }
 361  
 362      #[test]
 363      #[cfg(target_arch = "x86_64")]
 364      fn align_of_64() {
 365          assert_eq!(pref_align_of::<uint>(), 8u);
 366          assert_eq!(pref_align_of::<*uint>(), 8u);
 367      }
 368  
 369      #[test]
 370      fn align_of_val_basic() {
 371          assert_eq!(pref_align_of_val(&1u8), 1u);
 372          assert_eq!(pref_align_of_val(&1u16), 2u);
 373          assert_eq!(pref_align_of_val(&1u32), 4u);
 374      }
 375  
 376      #[test]
 377      fn test_swap() {
 378          let mut x = 31337;
 379          let mut y = 42;
 380          swap(&mut x, &mut y);
 381          assert_eq!(x, 42);
 382          assert_eq!(y, 31337);
 383      }
 384  
 385      #[test]
 386      fn test_replace() {
 387          let mut x = Some("test".to_owned());
 388          let y = replace(&mut x, None);
 389          assert!(x.is_none());
 390          assert!(y.is_some());
 391      }
 392  }
 393  
 394  // FIXME #13642 (these benchmarks should be in another place)
 395  /// Completely miscellaneous language-construct benchmarks.
 396  #[cfg(test)]
 397  mod bench {
 398      extern crate test;
 399      use self::test::Bencher;
 400      use option::{Some,None};
 401  
 402      // Static/dynamic method dispatch
 403  
 404      struct Struct {
 405          field: int
 406      }
 407  
 408      trait Trait {
 409          fn method(&self) -> int;
 410      }
 411  
 412      impl Trait for Struct {
 413          fn method(&self) -> int {
 414              self.field
 415          }
 416      }
 417  
 418      #[bench]
 419      fn trait_vtable_method_call(b: &mut Bencher) {
 420          let s = Struct { field: 10 };
 421          let t = &s as &Trait;
 422          b.iter(|| {
 423              t.method()
 424          });
 425      }
 426  
 427      #[bench]
 428      fn trait_static_method_call(b: &mut Bencher) {
 429          let s = Struct { field: 10 };
 430          b.iter(|| {
 431              s.method()
 432          });
 433      }
 434  
 435      // Overhead of various match forms
 436  
 437      #[bench]
 438      fn match_option_some(b: &mut Bencher) {
 439          let x = Some(10);
 440          b.iter(|| {
 441              match x {
 442                  Some(y) => y,
 443                  None => 11
 444              }
 445          });
 446      }
 447  
 448      #[bench]
 449      fn match_vec_pattern(b: &mut Bencher) {
 450          let x = [1,2,3,4,5,6];
 451          b.iter(|| {
 452              match x {
 453                  [1,2,3,..] => 10,
 454                  _ => 11
 455              }
 456          });
 457      }
 458  }


libcore/mem.rs:22:10-22:10 -fn- definition:
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}
references:- 122
libcore/slice.rs:
libcore/should_not_exist.rs:
libcore/num/mod.rs:
libcore/cast.rs:
libcore/num/mod.rs:


libcore/mem.rs:229:10-229:10 -fn- definition:
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
references:- 3
283: pub fn replace<T>(dest: &mut T, mut src: T) -> T {
284:     swap(dest, &mut src);
285:     src
libcore/iter.rs:
688:             match (self.next(), self.next_back()) {
689:                 (Some(x), Some(y)) => mem::swap(x, y),
690:                 _ => break
libcore/ptr.rs:
265: pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
266:     mem::swap(cast::transmute(dest), &mut src); // cannot overlap
267:     src


libcore/mem.rs:282:10-282:10 -fn- definition:
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
references:- 7
libcore/option.rs:
387:     pub fn take(&mut self) -> Option<T> {
388:         mem::replace(self, None)
389:     }
libcore/slice.rs:
1467:             let sz = if remainder != 0 { remainder } else { self.chunk_size };
1468:             let tmp = mem::replace(&mut self.v, &mut []);
1469:             let tmp_len = tmp.len();


libcore/mem.rs:89:10-89:10 -fn- definition:
pub unsafe fn uninit<T>() -> T {
    intrinsics::uninit()
}
references:- 4
libcore/ptr.rs:
272: pub unsafe fn read<T>(src: *T) -> T {
273:     let mut tmp: T = mem::uninit();
274:     copy_nonoverlapping_memory(&mut tmp, src, 1);
libcore/cast.rs:
46: pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
47:     let mut dest: U = mem::uninit();
48:     let dest_ptr: *mut u8 = transmute(&mut dest);
libcore/mem.rs:
232:         // Give ourselves some scratch space to work with
233:         let mut t: T = uninit();


libcore/mem.rs:97:10-97:10 -fn- definition:
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
    intrinsics::move_val_init(dst, src)
}
references:- 2
libcore/slice.rs:
1117:     unsafe fn init_elem(self, i: uint, val: T) {
1118:         mem::move_val_init(&mut (*self.as_mut_ptr().offset(i as int)), val);
1119:     }
libcore/should_not_exist.rs:
164:                 |i, ()| while *i < len {
165:                     mem::move_val_init(
166:                         &mut(*p.offset(*i as int)),


libcore/mem.rs:36:10-36:10 -fn- definition:
pub fn nonzero_size_of<T>() -> uint {
    match size_of::<T>() {
        0 => 1,
references:- 5
libcore/slice.rs:
1298:                 let diff = (self.end as uint) - (self.ptr as uint);
1299:                 let exact = diff / mem::nonzero_size_of::<T>();
1300:                 (exact, Some(exact))
libcore/should_not_exist.rs:
157:             (*ret).fill = len * mem::nonzero_size_of::<A>();
158:             (*ret).alloc = len * mem::nonzero_size_of::<A>();
libcore/mem.rs:
46: pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
47:     nonzero_size_of::<T>()
48: }