Skip to content

Commit 4989799

Browse files
committed
auto merge of #7986 : alexcrichton/rust/raw-repr, r=brson
This moves the raw struct layout of closures, vectors, boxes, and strings into a new `unstable::raw` module. This is meant to be a centralized location to find information for the layout of these values. As safe method, `unwrap`, is provided to convert a rust value to its raw representation. Unsafe methods to convert back are not provided because they are rarely used and too numerous to write an implementation for each (not much of a common pattern). This is progress on #6790. I tried to get a nice interface for a trait to implement in the raw module, but I was unable to come up with one. The hard part is that there are so many different directions to go from one way to another that it's difficult to find a pattern to follow to implement a trait with. Someone else might have some better luck though.
2 parents 5c4cd30 + 5aaaca0 commit 4989799

19 files changed

+254
-255
lines changed

src/libstd/at_vec.rs

+27-32
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010

1111
//! Managed vectors
1212
13-
use cast::transmute;
1413
use clone::Clone;
1514
use container::Container;
1615
use iterator::IteratorUtil;
1716
use option::Option;
1817
use sys;
1918
use uint;
19+
use unstable::raw::Repr;
2020
use vec::{ImmutableVector, OwnedVector};
2121

2222
/// Code for dealing with @-vectors. This is pretty incomplete, and
@@ -26,8 +26,8 @@ use vec::{ImmutableVector, OwnedVector};
2626
#[inline]
2727
pub fn capacity<T>(v: @[T]) -> uint {
2828
unsafe {
29-
let repr: **raw::VecRepr = transmute(&v);
30-
(**repr).unboxed.alloc / sys::size_of::<T>()
29+
let box = v.repr();
30+
(*box).data.alloc / sys::size_of::<T>()
3131
}
3232
}
3333

@@ -45,10 +45,10 @@ pub fn capacity<T>(v: @[T]) -> uint {
4545
*/
4646
#[inline]
4747
pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] {
48-
let mut vec: @[A] = @[];
48+
let mut vec = @[];
4949
unsafe { raw::reserve(&mut vec, size); }
5050
builder(|x| unsafe { raw::push(&mut vec, x) });
51-
return unsafe { transmute(vec) };
51+
vec
5252
}
5353

5454
/**
@@ -151,7 +151,7 @@ pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
151151
for v.consume_iter().advance |x| {
152152
raw::push(&mut av, x);
153153
}
154-
transmute(av)
154+
av
155155
}
156156
}
157157

@@ -195,13 +195,9 @@ pub mod raw {
195195
use ptr;
196196
use sys;
197197
use uint;
198-
use unstable::intrinsics;
199198
use unstable::intrinsics::{move_val_init, TyDesc};
200-
use vec;
201-
use vec::UnboxedVecRepr;
202-
203-
pub type VecRepr = vec::raw::VecRepr;
204-
pub type SliceRepr = vec::raw::SliceRepr;
199+
use unstable::intrinsics;
200+
use unstable::raw::{Box, Vec};
205201

206202
/**
207203
* Sets the length of a vector
@@ -211,19 +207,21 @@ pub mod raw {
211207
* the vector is actually the specified size.
212208
*/
213209
#[inline]
214-
pub unsafe fn set_len<T>(v: @[T], new_len: uint) {
215-
let repr: **mut VecRepr = transmute(&v);
216-
(**repr).unboxed.fill = new_len * sys::size_of::<T>();
210+
pub unsafe fn set_len<T>(v: &mut @[T], new_len: uint) {
211+
let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
212+
(*repr).data.fill = new_len * sys::size_of::<T>();
217213
}
218214

219215
/**
220216
* Pushes a new value onto this vector.
221217
*/
222218
#[inline]
223219
pub unsafe fn push<T>(v: &mut @[T], initval: T) {
224-
let repr: **VecRepr = transmute_copy(&v);
225-
let fill = (**repr).unboxed.fill;
226-
if (**repr).unboxed.alloc > fill {
220+
let full = {
221+
let repr: *Box<Vec<T>> = cast::transmute_copy(v);
222+
(*repr).data.alloc > (*repr).data.fill
223+
};
224+
if full {
227225
push_fast(v, initval);
228226
} else {
229227
push_slow(v, initval);
@@ -232,16 +230,15 @@ pub mod raw {
232230

233231
#[inline] // really pretty please
234232
unsafe fn push_fast<T>(v: &mut @[T], initval: T) {
235-
let repr: **mut VecRepr = ::cast::transmute(v);
236-
let fill = (**repr).unboxed.fill;
237-
(**repr).unboxed.fill += sys::size_of::<T>();
238-
let p = &((**repr).unboxed.data);
239-
let p = ptr::offset(p, fill) as *mut T;
233+
let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
234+
let amt = v.len();
235+
(*repr).data.fill += sys::size_of::<T>();
236+
let p = ptr::offset(&(*repr).data.data as *T, amt) as *mut T;
240237
move_val_init(&mut(*p), initval);
241238
}
242239

243240
unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
244-
reserve_at_least(&mut *v, v.len() + 1u);
241+
reserve_at_least(v, v.len() + 1u);
245242
push_fast(v, initval);
246243
}
247244

@@ -259,7 +256,7 @@ pub mod raw {
259256
pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
260257
// Only make the (slow) call into the runtime if we have to
261258
if capacity(*v) < n {
262-
let ptr: *mut *mut VecRepr = transmute(v);
259+
let ptr: *mut *mut Box<Vec<()>> = transmute(v);
263260
let ty = intrinsics::get_tydesc::<T>();
264261
// XXX transmute shouldn't be necessary
265262
let ty = cast::transmute(ty);
@@ -269,16 +266,14 @@ pub mod raw {
269266

270267
// Implementation detail. Shouldn't be public
271268
#[allow(missing_doc)]
272-
pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut VecRepr, n: uint) {
269+
pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
273270

274271
unsafe {
275272
let size_in_bytes = n * (*ty).size;
276-
if size_in_bytes > (**ptr).unboxed.alloc {
277-
let total_size = size_in_bytes + sys::size_of::<UnboxedVecRepr>();
278-
// XXX: UnboxedVecRepr has an extra u8 at the end
279-
let total_size = total_size - sys::size_of::<u8>();
280-
(*ptr) = local_realloc(*ptr as *(), total_size) as *mut VecRepr;
281-
(**ptr).unboxed.alloc = size_in_bytes;
273+
if size_in_bytes > (**ptr).data.alloc {
274+
let total_size = size_in_bytes + sys::size_of::<Vec<()>>();
275+
(*ptr) = local_realloc(*ptr as *(), total_size) as *mut Box<Vec<()>>;
276+
(**ptr).data.alloc = size_in_bytes;
282277
}
283278
}
284279

src/libstd/cast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
133133
#[cfg(test)]
134134
mod tests {
135135
use cast::{bump_box_refcount, transmute};
136+
use unstable::raw;
136137

137138
#[test]
138139
fn test_transmute_copy() {
@@ -156,10 +157,9 @@ mod tests {
156157
157158
#[test]
158159
fn test_transmute() {
159-
use managed::raw::BoxRepr;
160160
unsafe {
161161
let x = @100u8;
162-
let x: *BoxRepr = transmute(x);
162+
let x: *raw::Box<u8> = transmute(x);
163163
assert!((*x).data == 100);
164164
let _x: @int = transmute(x);
165165
}

src/libstd/cleanup.rs

+14-17
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212

1313
use libc::c_void;
1414
use ptr::{mut_null};
15-
use repr::BoxRepr;
16-
use cast::transmute;
1715
use unstable::intrinsics::TyDesc;
16+
use unstable::raw;
1817

1918
type DropGlue<'self> = &'self fn(**TyDesc, *c_void);
2019

@@ -31,27 +30,25 @@ struct AnnihilateStats {
3130
}
3231

3332
unsafe fn each_live_alloc(read_next_before: bool,
34-
f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) -> bool {
33+
f: &fn(box: *mut raw::Box<()>, uniq: bool) -> bool) -> bool {
3534
//! Walks the internal list of allocations
3635
3736
use managed;
3837
use rt::local_heap;
3938

40-
let box = local_heap::live_allocs();
41-
let mut box: *mut BoxRepr = transmute(box);
39+
let mut box = local_heap::live_allocs();
4240
while box != mut_null() {
43-
let next_before = transmute((*box).header.next);
44-
let uniq =
45-
(*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;
41+
let next_before = (*box).next;
42+
let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE;
4643

47-
if !f(box, uniq) {
44+
if !f(box as *mut raw::Box<()>, uniq) {
4845
return false;
4946
}
5047

5148
if read_next_before {
5249
box = next_before;
5350
} else {
54-
box = transmute((*box).header.next);
51+
box = (*box).next;
5552
}
5653
}
5754
return true;
@@ -102,7 +99,7 @@ pub unsafe fn annihilate() {
10299
if uniq {
103100
stats.n_unique_boxes += 1;
104101
} else {
105-
(*box).header.ref_count = managed::raw::RC_IMMORTAL;
102+
(*box).ref_count = managed::RC_IMMORTAL;
106103
}
107104
}
108105

@@ -113,9 +110,9 @@ pub unsafe fn annihilate() {
113110
// callback, as the original value may have been freed.
114111
for each_live_alloc(false) |box, uniq| {
115112
if !uniq {
116-
let tydesc: *TyDesc = transmute((*box).header.type_desc);
117-
let data = transmute(&(*box).data);
118-
((*tydesc).drop_glue)(data);
113+
let tydesc = (*box).type_desc;
114+
let data = &(*box).data as *();
115+
((*tydesc).drop_glue)(data as *i8);
119116
}
120117
}
121118

@@ -128,9 +125,9 @@ pub unsafe fn annihilate() {
128125
for each_live_alloc(true) |box, uniq| {
129126
if !uniq {
130127
stats.n_bytes_freed +=
131-
(*((*box).header.type_desc)).size
132-
+ sys::size_of::<BoxRepr>();
133-
local_free(transmute(box));
128+
(*((*box).type_desc)).size
129+
+ sys::size_of::<raw::Box<()>>();
130+
local_free(box as *i8);
134131
}
135132
}
136133

src/libstd/gc.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ pub mod rustrt {
7474
}
7575

7676
unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
77-
return cast::transmute(ptr::offset(ptr, count));
77+
return ptr::offset(ptr, count) as *U;
7878
}
7979

8080
unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
8181
let align = sys::min_align_of::<*T>();
82-
let ptr: uint = cast::transmute(ptr);
82+
let ptr = ptr as uint;
8383
let ptr = (ptr + (align - 1)) & -align;
84-
return cast::transmute(ptr);
84+
return ptr as *T;
8585
}
8686

8787
unsafe fn get_safe_point_count() -> uint {
@@ -126,8 +126,8 @@ type Visitor<'self> = &'self fn(root: **Word, tydesc: *TyDesc) -> bool;
126126
// Walks the list of roots for the given safe point, and calls visitor
127127
// on each root.
128128
unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
129-
let fp_bytes: *u8 = cast::transmute(fp);
130-
let sp_meta: *u32 = cast::transmute(sp.sp_meta);
129+
let fp_bytes = fp as *u8;
130+
let sp_meta = sp.sp_meta as *u32;
131131

132132
let num_stack_roots = *sp_meta as uint;
133133
let num_reg_roots = *ptr::offset(sp_meta, 1) as uint;
@@ -173,9 +173,9 @@ unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
173173

174174
// Is fp contained in segment?
175175
unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
176-
let begin: Word = cast::transmute(segment);
177-
let end: Word = cast::transmute((*segment).end);
178-
let frame: Word = cast::transmute(fp);
176+
let begin = segment as Word;
177+
let end = (*segment).end as Word;
178+
let frame = fp as Word;
179179

180180
return begin <= frame && frame <= end;
181181
}

src/libstd/managed.rs

+2-21
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,8 @@ use ptr::to_unsafe_ptr;
1414

1515
#[cfg(not(test))] use cmp::{Eq, Ord};
1616

17-
pub mod raw {
18-
use std::unstable::intrinsics::TyDesc;
19-
20-
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
21-
pub static RC_IMMORTAL : uint = 0x77777777;
22-
23-
#[allow(missing_doc)]
24-
pub struct BoxHeaderRepr {
25-
ref_count: uint,
26-
type_desc: *TyDesc,
27-
prev: *BoxRepr,
28-
next: *BoxRepr,
29-
}
30-
31-
#[allow(missing_doc)]
32-
pub struct BoxRepr {
33-
header: BoxHeaderRepr,
34-
data: u8
35-
}
36-
37-
}
17+
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
18+
pub static RC_IMMORTAL : uint = 0x77777777;
3819

3920
/// Determine if two shared boxes point to the same object
4021
#[inline]

src/libstd/reflect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Runtime type reflection
1919
use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
2020
use libc::c_void;
2121
use sys;
22-
use vec;
22+
use unstable::raw;
2323

2424
/**
2525
* Trait for visitor that wishes to reflect on data. To use this, create a
@@ -260,7 +260,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
260260
}
261261

262262
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
263-
self.align_to::<vec::UnboxedVecRepr>();
263+
self.align_to::<raw::Vec<()>>();
264264
if ! self.inner.visit_vec(mtbl, inner) { return false; }
265265
true
266266
}

0 commit comments

Comments
 (0)