(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, src: T) {
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 t: T = 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 src: T) -> T {
284 swap(dest, &mut src);
285 src
286 }
287
288 /// Disposes of a value.
289 #[inline]
290 pub fn drop<T>(_x: T) { }
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:- 122libcore/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:- 3283: 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:- 7libcore/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:- 4libcore/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:- 2libcore/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:- 5libcore/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: }