(index<- ) ./libstd/mem.rs
git branch: * master c7553ea auto merge of #13609 : richo/rust/str-type-vim, r=alexcrichton
modified: Sat Apr 19 11:22:39 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 #![allow(missing_doc)] // FIXME
17
18 use cast;
19 use ptr;
20 use intrinsics;
21 use intrinsics::{bswap16, bswap32, bswap64};
22
23 /// Returns the size of a type in bytes.
24 #[inline]
25 pub fn size_of<T>() -> uint {
26 unsafe { intrinsics::size_of::<T>() }
27 }
28
29 /// Returns the size of the type that `_val` points to in bytes.
30 #[inline]
31 pub fn size_of_val<T>(_val: &T) -> uint {
32 size_of::<T>()
33 }
34
35 /// Returns the size of a type in bytes, or 1 if the actual size is zero.
36 ///
37 /// Useful for building structures containing variable-length arrays.
38 #[inline]
39 pub fn nonzero_size_of<T>() -> uint {
40 let s = size_of::<T>();
41 if s == 0 { 1 } else { s }
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 /**
227 * Swap the values at two mutable locations of the same type, without
228 * deinitialising or copying either one.
229 */
230 #[inline]
231 pub fn swap<T>(x: &mut T, y: &mut T) {
232 unsafe {
233 // Give ourselves some scratch space to work with
234 let mut t: T = uninit();
235
236 // Perform the swap, `&mut` pointers never alias
237 ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
238 ptr::copy_nonoverlapping_memory(x, &*y, 1);
239 ptr::copy_nonoverlapping_memory(y, &t, 1);
240
241 // y and t now point to the same thing, but we need to completely forget `tmp`
242 // because it's no longer relevant.
243 cast::forget(t);
244 }
245 }
246
247 /**
248 * Replace the value at a mutable location with a new one, returning the old
249 * value, without deinitialising or copying either one.
250 */
251 #[inline]
252 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
253 swap(dest, &mut src);
254 src
255 }
256
257 /// Disposes of a value.
258 #[inline]
259 pub fn drop<T>(_x: T) { }
260
261 #[cfg(test)]
262 mod tests {
263 use mem::*;
264 use option::{Some,None};
265 use str::StrSlice;
266
267 #[test]
268 fn size_of_basic() {
269 assert_eq!(size_of::<u8>(), 1u);
270 assert_eq!(size_of::<u16>(), 2u);
271 assert_eq!(size_of::<u32>(), 4u);
272 assert_eq!(size_of::<u64>(), 8u);
273 }
274
275 #[test]
276 #[cfg(target_arch = "x86")]
277 #[cfg(target_arch = "arm")]
278 #[cfg(target_arch = "mips")]
279 fn size_of_32() {
280 assert_eq!(size_of::<uint>(), 4u);
281 assert_eq!(size_of::<*uint>(), 4u);
282 }
283
284 #[test]
285 #[cfg(target_arch = "x86_64")]
286 fn size_of_64() {
287 assert_eq!(size_of::<uint>(), 8u);
288 assert_eq!(size_of::<*uint>(), 8u);
289 }
290
291 #[test]
292 fn size_of_val_basic() {
293 assert_eq!(size_of_val(&1u8), 1);
294 assert_eq!(size_of_val(&1u16), 2);
295 assert_eq!(size_of_val(&1u32), 4);
296 assert_eq!(size_of_val(&1u64), 8);
297 }
298
299 #[test]
300 fn nonzero_size_of_basic() {
301 type Z = [i8, ..0];
302 assert_eq!(size_of::<Z>(), 0u);
303 assert_eq!(nonzero_size_of::<Z>(), 1u);
304 assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
305 }
306
307 #[test]
308 fn nonzero_size_of_val_basic() {
309 let z = [0u8, ..0];
310 assert_eq!(size_of_val(&z), 0u);
311 assert_eq!(nonzero_size_of_val(&z), 1u);
312 assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
313 }
314
315 #[test]
316 fn align_of_basic() {
317 assert_eq!(pref_align_of::<u8>(), 1u);
318 assert_eq!(pref_align_of::<u16>(), 2u);
319 assert_eq!(pref_align_of::<u32>(), 4u);
320 }
321
322 #[test]
323 #[cfg(target_arch = "x86")]
324 #[cfg(target_arch = "arm")]
325 #[cfg(target_arch = "mips")]
326 fn align_of_32() {
327 assert_eq!(pref_align_of::<uint>(), 4u);
328 assert_eq!(pref_align_of::<*uint>(), 4u);
329 }
330
331 #[test]
332 #[cfg(target_arch = "x86_64")]
333 fn align_of_64() {
334 assert_eq!(pref_align_of::<uint>(), 8u);
335 assert_eq!(pref_align_of::<*uint>(), 8u);
336 }
337
338 #[test]
339 fn align_of_val_basic() {
340 assert_eq!(pref_align_of_val(&1u8), 1u);
341 assert_eq!(pref_align_of_val(&1u16), 2u);
342 assert_eq!(pref_align_of_val(&1u32), 4u);
343 }
344
345 #[test]
346 fn test_swap() {
347 let mut x = 31337;
348 let mut y = 42;
349 swap(&mut x, &mut y);
350 assert_eq!(x, 42);
351 assert_eq!(y, 31337);
352 }
353
354 #[test]
355 fn test_replace() {
356 let mut x = Some("test".to_owned());
357 let y = replace(&mut x, None);
358 assert!(x.is_none());
359 assert!(y.is_some());
360 }
361 }
362
363 /// Completely miscellaneous language-construct benchmarks.
364 #[cfg(test)]
365 mod bench {
366 extern crate test;
367 use self::test::Bencher;
368 use option::{Some,None};
369
370 // Static/dynamic method dispatch
371
372 struct Struct {
373 field: int
374 }
375
376 trait Trait {
377 fn method(&self) -> int;
378 }
379
380 impl Trait for Struct {
381 fn method(&self) -> int {
382 self.field
383 }
384 }
385
386 #[bench]
387 fn trait_vtable_method_call(b: &mut Bencher) {
388 let s = Struct { field: 10 };
389 let t = &s as &Trait;
390 b.iter(|| {
391 t.method()
392 });
393 }
394
395 #[bench]
396 fn trait_static_method_call(b: &mut Bencher) {
397 let s = Struct { field: 10 };
398 b.iter(|| {
399 s.method()
400 });
401 }
402
403 // Overhead of various match forms
404
405 #[bench]
406 fn match_option_some(b: &mut Bencher) {
407 let x = Some(10);
408 b.iter(|| {
409 match x {
410 Some(y) => y,
411 None => 11
412 }
413 });
414 }
415
416 #[bench]
417 fn match_vec_pattern(b: &mut Bencher) {
418 let x = [1,2,3,4,5,6];
419 b.iter(|| {
420 match x {
421 [1,2,3,..] => 10,
422 _ => 11
423 }
424 });
425 }
426 }
libstd/mem.rs:258:10-258:10 -fn- definition:
pub fn drop<T>(_x: T) { }
mod tests {
use mem::*;
references:- 16libstd/rt/task.rs:
165: drop(task);
166: drop(storage_map);
libstd/rt/unwind.rs:
430: Local::put(task);
431: drop(prev);
432: task = Local::take();
libstd/comm/sync.rs:
352: };
353: mem::drop((state, guard));
libstd/io/process.rs:
379: pub fn wait(&mut self) -> ProcessExit {
380: drop(self.stdin.take());
381: self.handle.wait()
--
389: pub fn wait_with_output(&mut self) -> ProcessOutput {
390: drop(self.stdin.take());
391: fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
--
417: drop(self.stdin.take());
418: drop(self.stdout.take());
419: drop(self.stderr.take());
420: drop(mem::replace(&mut self.extra_io, ~[]));
libstd/io/signal.rs:
143: match self.handles.iter().position(|&(i, _)| i == signum) {
144: Some(i) => drop(self.handles.remove(i)),
145: None => {}
libstd/io/stdio.rs:
233: let prev = replace(&mut Local::borrow(None::<Task>).stdout, my_stdout);
234: drop(prev);
235: ret
libstd/rt/task.rs:
164: };
165: drop(task);
166: drop(storage_map);
libstd/mem.rs:38:10-38:10 -fn- definition:
pub fn nonzero_size_of<T>() -> uint {
let s = size_of::<T>();
if s == 0 { 1 } else { s }
references:- 546: pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
47: nonzero_size_of::<T>()
48: }
libstd/slice.rs:
2062: let diff = (self.end as uint) - (self.ptr as uint);
2063: let exact = diff / mem::nonzero_size_of::<T>();
2064: (exact, Some(exact))
--
2304: (*ret).fill = len * mem::nonzero_size_of::<A>();
2305: (*ret).alloc = len * mem::nonzero_size_of::<A>();
2306: ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
libstd/mem.rs:251:10-251:10 -fn- definition:
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
swap(dest, &mut src);
src
references:- 30libstd/rt/unwind.rs:
libstd/rt/args.rs:
libstd/rt/at_exit_imp.rs:
libstd/slice.rs:
libstd/option.rs:
libstd/comm/oneshot.rs:
libstd/comm/sync.rs:
libstd/local_data.rs:
libstd/io/process.rs:
libstd/io/stdio.rs:
libstd/comm/sync.rs:
libstd/mem.rs:24:10-24:10 -fn- definition:
pub fn size_of<T>() -> uint {
unsafe { intrinsics::size_of::<T>() }
}
references:- 135libstd/reflect.rs:
libstd/rt/global_heap.rs:
libstd/rt/local_heap.rs:
libstd/slice.rs:
libstd/vec.rs:
libstd/num/mod.rs:
libstd/sync/deque.rs:
libstd/cast.rs:
libstd/num/mod.rs:
libstd/mem.rs:83:10-83:10 -fn- definition:
pub unsafe fn init<T>() -> T {
intrinsics::init()
}
references:- 2libstd/unstable/mutex.rs:
392: let m = Mutex {
393: lock: Unsafe::new(mem::init()),
394: cond: Unsafe::new(mem::init()),
395: };
libstd/mem.rs:89:10-89:10 -fn- definition:
pub unsafe fn uninit<T>() -> T {
intrinsics::uninit()
}
references:- 7233: // Give ourselves some scratch space to work with
234: let mut t: T = uninit();
libstd/rt/thread.rs:
227: let mut native: libc::pthread_t = mem::uninit();
228: let mut attr: libc::pthread_attr_t = mem::uninit();
229: assert_eq!(pthread_attr_init(&mut attr), 0);
libstd/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);
libstd/c_str.rs:
349: if v.len() < BUF_LEN {
350: let mut buf: [u8, .. BUF_LEN] = mem::uninit();
351: slice::bytes::copy_memory(buf, v);
libstd/cast.rs:
19: pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
20: let mut dest: U = mem::uninit();
21: let dest_ptr: *mut u8 = transmute(&mut dest);
libstd/rt/thread.rs:
226: pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
227: let mut native: libc::pthread_t = mem::uninit();
228: let mut attr: libc::pthread_attr_t = mem::uninit();
libstd/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:- 7libstd/slice.rs:
670: |i, ()| while *i < len {
671: mem::move_val_init(
672: &mut(*p.offset(*i as int)),
--
1780: unsafe fn init_elem(self, i: uint, val: T) {
1781: mem::move_val_init(&mut (*self.as_mut_ptr().offset(i as int)), val);
1782: }
libstd/vec.rs:
921: // element.
922: move_val_init(&mut *p, element);
923: }
libstd/mem.rs:230:10-230:10 -fn- definition:
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
references:- 13252: pub fn replace<T>(dest: &mut T, mut src: T) -> T {
253: swap(dest, &mut src);
254: src
libstd/slice.rs:
1758: for (a, b) in self.mut_iter().zip(src.mut_slice(start, end).mut_iter()) {
1759: mem::swap(a, b);
1760: }
libstd/vec.rs:
1342: let p_w = p_wm1.offset(1);
1343: mem::swap(&mut *p_r, &mut *p_w);
1344: }
libstd/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
libstd/comm/mod.rs:
601: let mut tmp = Sender::new(Shared(packet.clone()));
602: mem::swap(&mut cast::transmute_mut(self).inner, &mut tmp.inner);
603: }
--
876: unsafe {
877: mem::swap(&mut cast::transmute_mut(self).inner,
878: &mut new_port.inner);
--
908: unsafe {
909: mem::swap(&mut cast::transmute_mut(self).inner,
910: &mut new_port.inner);
--
932: unsafe {
933: mem::swap(&mut cast::transmute_mut(self).inner,
934: &mut new_port.inner);
libstd/iter.rs:
688: match (self.next(), self.next_back()) {
689: (Some(x), Some(y)) => mem::swap(x, y),
690: _ => break
libstd/mem.rs:54:10-54:10 -fn- definition:
pub fn min_align_of<T>() -> uint {
unsafe { intrinsics::min_align_of::<T>() }
}
references:- 262: pub fn min_align_of_val<T>(_val: &T) -> uint {
63: min_align_of::<T>()
64: }
libstd/reflect.rs:
60: pub fn align_to<T>(&mut self) {
61: self.align(mem::min_align_of::<T>());
62: }