Skip to content

Commit 9dca534

Browse files
committed
---
yaml --- r: 77021 b: refs/heads/snap-stage3 c: 6b23d20 h: refs/heads/master i: 77019: a8ad3e5 v: v3
1 parent 7d91f4c commit 9dca534

File tree

236 files changed

+6690
-3767
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

236 files changed

+6690
-3767
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: f1132496dddbdd88f321a7919eec3d65136b3f75
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 0f6dd539488039cacef9646786039eb5213e6444
4+
refs/heads/snap-stage3: 6b23d20452ef7c2d2eb79baf074bcda04fad9a66
55
refs/heads/try: ebfe63cd1c0b5d23f7ea60c69b4fde2e30cfd42a
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/doc/rust.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ a referencing source file, or by the name of the crate itself.
582582

583583
Each source file contains a sequence of zero or more `item` definitions,
584584
and may optionally begin with any number of `attributes` that apply to the containing module.
585-
Atributes on the anonymous crate module define important metadata that influences
585+
Attributes on the anonymous crate module define important metadata that influences
586586
the behavior of the compiler.
587587

588588
~~~~~~~~
@@ -1273,7 +1273,7 @@ since the typechecker checks that any type with an implementation of `Circle` al
12731273

12741274
In type-parameterized functions,
12751275
methods of the supertrait may be called on values of subtrait-bound type parameters.
1276-
Refering to the previous example of `trait Circle : Shape`:
1276+
Referring to the previous example of `trait Circle : Shape`:
12771277

12781278
~~~
12791279
# trait Shape { fn area(&self) -> float; }
@@ -1914,7 +1914,7 @@ A field access on a record is an [lvalue](#lvalues-rvalues-and-temporaries) refe
19141914
When the field is mutable, it can be [assigned](#assignment-expressions) to.
19151915

19161916
When the type of the expression to the left of the dot is a pointer to a record or structure,
1917-
it is automatically derferenced to make the field access possible.
1917+
it is automatically dereferenced to make the field access possible.
19181918

19191919

19201920
### Vector expressions

branches/snap-stage3/doc/tutorial-ffi.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern {
1919
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
2020
}
2121
22+
#[fixed_stack_segment]
2223
fn main() {
2324
let x = unsafe { snappy_max_compressed_length(100) };
2425
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
@@ -35,6 +36,11 @@ interfaces that aren't thread-safe, and almost any function that takes a pointer
3536
valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of
3637
Rust's safe memory model.
3738

39+
Finally, the `#[fixed_stack_segment]` annotation that appears on
40+
`main()` instructs the Rust compiler that when `main()` executes, it
41+
should request a "very large" stack segment. More details on
42+
stack management can be found in the following sections.
43+
3844
When declaring the argument types to a foreign function, the Rust compiler will not check if the
3945
declaration is correct, so specifying it correctly is part of keeping the binding correct at
4046
runtime.
@@ -75,6 +81,8 @@ length is number of elements currently contained, and the capacity is the total
7581
the allocated memory. The length is less than or equal to the capacity.
7682

7783
~~~~ {.xfail-test}
84+
#[fixed_stack_segment]
85+
#[inline(never)]
7886
pub fn validate_compressed_buffer(src: &[u8]) -> bool {
7987
unsafe {
8088
snappy_validate_compressed_buffer(vec::raw::to_ptr(src), src.len() as size_t) == 0
@@ -86,6 +94,36 @@ The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, b
8694
guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
8795
signature.
8896

97+
The `validate_compressed_buffer` wrapper is also annotated with two
98+
attributes `#[fixed_stack_segment]` and `#[inline(never)]`. The
99+
purpose of these attributes is to guarantee that there will be
100+
sufficient stack for the C function to execute. This is necessary
101+
because Rust, unlike C, does not assume that the stack is allocated in
102+
one continuous chunk. Instead, we rely on a *segmented stack* scheme,
103+
in which the stack grows and shrinks as necessary. C code, however,
104+
expects one large stack, and so callers of C functions must request a
105+
large stack segment to ensure that the C routine will not run off the
106+
end of the stack.
107+
108+
The compiler includes a lint mode that will report an error if you
109+
call a C function without a `#[fixed_stack_segment]` attribute. More
110+
details on the lint mode are given in a later section.
111+
112+
You may be wondering why we include a `#[inline(never)]` directive.
113+
This directive informs the compiler never to inline this function.
114+
While not strictly necessary, it is usually a good idea to use an
115+
`#[inline(never)]` directive in concert with `#[fixed_stack_segment]`.
116+
The reason is that if a fn annotated with `fixed_stack_segment` is
117+
inlined, then its caller also inherits the `fixed_stack_segment`
118+
annotation. This means that rather than requesting a large stack
119+
segment only for the duration of the call into C, the large stack
120+
segment would be used for the entire duration of the caller. This is
121+
not necessarily *bad* -- it can for example be more efficient,
122+
particularly if `validate_compressed_buffer()` is called multiple
123+
times in a row -- but it does work against the purpose of the
124+
segmented stack scheme, which is to keep stacks small and thus
125+
conserve address space.
126+
89127
The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
90128
allocated to hold the output too.
91129

@@ -96,6 +134,8 @@ the true length after compression for setting the length.
96134

97135
~~~~ {.xfail-test}
98136
pub fn compress(src: &[u8]) -> ~[u8] {
137+
#[fixed_stack_segment]; #[inline(never)];
138+
99139
unsafe {
100140
let srclen = src.len() as size_t;
101141
let psrc = vec::raw::to_ptr(src);
@@ -116,6 +156,8 @@ format and `snappy_uncompressed_length` will retrieve the exact buffer size requ
116156

117157
~~~~ {.xfail-test}
118158
pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
159+
#[fixed_stack_segment]; #[inline(never)];
160+
119161
unsafe {
120162
let srclen = src.len() as size_t;
121163
let psrc = vec::raw::to_ptr(src);
@@ -139,6 +181,99 @@ pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
139181
For reference, the examples used here are also available as an [library on
140182
GitHub](https://github.com/thestinger/rust-snappy).
141183

184+
# Automatic wrappers
185+
186+
Sometimes writing Rust wrappers can be quite tedious. For example, if
187+
function does not take any pointer arguments, often there is no need
188+
for translating types. In such cases, it is usually still a good idea
189+
to have a Rust wrapper so as to manage the segmented stacks, but you
190+
can take advantage of the (standard) `externfn!` macro to remove some
191+
of the tedium.
192+
193+
In the initial section, we showed an extern block that added a call
194+
to a specific snappy API:
195+
196+
~~~~ {.xfail-test}
197+
use std::libc::size_t;
198+
199+
#[link_args = "-lsnappy"]
200+
extern {
201+
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
202+
}
203+
204+
#[fixed_stack_segment]
205+
fn main() {
206+
let x = unsafe { snappy_max_compressed_length(100) };
207+
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
208+
}
209+
~~~~
210+
211+
To avoid the need to create a wrapper fn for `snappy_max_compressed_length()`,
212+
and also to avoid the need to think about `#[fixed_stack_segment]`, we
213+
could simply use the `externfn!` macro instead, as shown here:
214+
215+
~~~~ {.xfail-test}
216+
use std::libc::size_t;
217+
218+
externfn!(#[link_args = "-lsnappy"]
219+
fn snappy_max_compressed_length(source_length: size_t) -> size_t)
220+
221+
fn main() {
222+
let x = unsafe { snappy_max_compressed_length(100) };
223+
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
224+
}
225+
~~~~
226+
227+
As you can see from the example, `externfn!` replaces the extern block
228+
entirely. After macro expansion, it will create something like this:
229+
230+
~~~~ {.xfail-test}
231+
use std::libc::size_t;
232+
233+
// Automatically generated by
234+
// externfn!(#[link_args = "-lsnappy"]
235+
// fn snappy_max_compressed_length(source_length: size_t) -> size_t)
236+
unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t {
237+
#[fixed_stack_segment]; #[inline(never)];
238+
return snappy_max_compressed_length(source_length);
239+
240+
#[link_args = "-lsnappy"]
241+
extern {
242+
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
243+
}
244+
}
245+
246+
fn main() {
247+
let x = unsafe { snappy_max_compressed_length(100) };
248+
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
249+
}
250+
~~~~
251+
252+
# Segmented stacks and the linter
253+
254+
By default, whenever you invoke a non-Rust fn, the `cstack` lint will
255+
check that one of the following conditions holds:
256+
257+
1. The call occurs inside of a fn that has been annotated with
258+
`#[fixed_stack_segment]`;
259+
2. The call occurs inside of an `extern fn`;
260+
3. The call occurs within a stack closure created by some other
261+
safe fn.
262+
263+
All of these conditions ensure that you are running on a large stack
264+
segmented. However, they are sometimes too strict. If your application
265+
will be making many calls into C, it is often beneficial to promote
266+
the `#[fixed_stack_segment]` attribute higher up the call chain. For
267+
example, the Rust compiler actually labels main itself as requiring a
268+
`#[fixed_stack_segment]`. In such cases, the linter is just an
269+
annoyance, because all C calls that occur from within the Rust
270+
compiler are made on a large stack. Another situation where this
271+
frequently occurs is on a 64-bit architecture, where large stacks are
272+
the default. In cases, you can disable the linter by including a
273+
`#[allow(cstack)]` directive somewhere, which permits violations of
274+
the "cstack" rules given above (you can also use `#[warn(cstack)]` to
275+
convert the errors into warnings, if you prefer).
276+
142277
# Destructors
143278

144279
Foreign libraries often hand off ownership of resources to the calling code,
@@ -161,6 +296,9 @@ pub struct Unique<T> {
161296
162297
impl<T: Send> Unique<T> {
163298
pub fn new(value: T) -> Unique<T> {
299+
#[fixed_stack_segment];
300+
#[inline(never)];
301+
164302
unsafe {
165303
let ptr = malloc(std::sys::size_of::<T>() as size_t) as *mut T;
166304
assert!(!ptr::is_null(ptr));
@@ -184,6 +322,9 @@ impl<T: Send> Unique<T> {
184322
#[unsafe_destructor]
185323
impl<T: Send> Drop for Unique<T> {
186324
fn drop(&self) {
325+
#[fixed_stack_segment];
326+
#[inline(never)];
327+
187328
unsafe {
188329
let x = intrinsics::init(); // dummy value to swap in
189330
// moving the object out is needed to call the destructor

branches/snap-stage3/mk/rt.mk

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ RUNTIME_CXXS_$(1)_$(2) := \
6868
rt/sync/rust_thread.cpp \
6969
rt/rust_builtin.cpp \
7070
rt/rust_run_program.cpp \
71-
rt/rust_env.cpp \
7271
rt/rust_rng.cpp \
73-
rt/rust_stack.cpp \
7472
rt/rust_upcall.cpp \
7573
rt/rust_uv.cpp \
7674
rt/rust_crate_map.cpp \

branches/snap-stage3/src/etc/cmathconsts.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <math.h>
1414
#include <stdio.h>
1515

16-
// must match core::ctypes
16+
// must match std::ctypes
1717

1818
#define C_FLT(x) (float)x
1919
#define C_DBL(x) (double)x

branches/snap-stage3/src/etc/ziggurat_tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# xfail-license
33

44
# This creates the tables used for distributions implemented using the
5-
# ziggurat algorithm in `core::rand::distributions;`. They are
5+
# ziggurat algorithm in `std::rand::distributions;`. They are
66
# (basically) the tables as used in the ZIGNOR variant (Doornik 2005).
77
# They are changed rarely, so the generated file should be checked in
88
# to git.

branches/snap-stage3/src/etc/zsh/_rust

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ _rustc_opts_lint=(
3636
'path-statement[path statements with no effect]'
3737
'missing-trait-doc[detects missing documentation for traits]'
3838
'missing-struct-doc[detects missing documentation for structs]'
39-
'ctypes[proper use of core::libc types in foreign modules]'
39+
'ctypes[proper use of std::libc types in foreign modules]'
4040
"unused-mut[detect mut variables which don't need to be mutable]"
4141
'unused-imports[imports that are never used]'
4242
'heap-memory[use of any (~ type or @ type) heap memory]'

branches/snap-stage3/src/libextra/arc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ mod tests {
762762
do 10.times {
763763
let tmp = *num;
764764
*num = -1;
765-
task::yield();
765+
task::deschedule();
766766
*num = tmp + 1;
767767
}
768768
c.send(());
@@ -913,17 +913,17 @@ mod tests {
913913
do read_mode.read |state| {
914914
// if writer mistakenly got in, make sure it mutates state
915915
// before we assert on it
916-
do 5.times { task::yield(); }
916+
do 5.times { task::deschedule(); }
917917
// make sure writer didn't get in.
918918
assert!(*state);
919919
}
920920
}
921921
}
922922
#[test]
923923
fn test_rw_write_cond_downgrade_read_race() {
924-
// Ideally the above test case would have yield statements in it that
924+
// Ideally the above test case would have deschedule statements in it that
925925
// helped to expose the race nearly 100% of the time... but adding
926-
// yields in the intuitively-right locations made it even less likely,
926+
// deschedules in the intuitively-right locations made it even less likely,
927927
// and I wasn't sure why :( . This is a mediocre "next best" option.
928928
do 8.times { test_rw_write_cond_downgrade_read_race_helper() }
929929
}

branches/snap-stage3/src/libextra/c_vec.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,20 @@ mod tests {
155155
use std::libc;
156156

157157
fn malloc(n: size_t) -> CVec<u8> {
158+
#[fixed_stack_segment];
159+
#[inline(never)];
160+
158161
unsafe {
159162
let mem = libc::malloc(n);
160163

161164
assert!(mem as int != 0);
162165

163-
c_vec_with_dtor(mem as *mut u8, n as uint, || free(mem))
166+
return c_vec_with_dtor(mem as *mut u8, n as uint, || f(mem));
167+
}
168+
169+
fn f(mem: *c_void) {
170+
#[fixed_stack_segment]; #[inline(never)];
171+
unsafe { libc::free(mem) }
164172
}
165173
}
166174

branches/snap-stage3/src/libextra/crypto/cryptoutil.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ pub fn add_bytes_to_bits_tuple
176176
/// method that modifies the buffer directory or provides the caller with bytes that can be modifies
177177
/// results in those bytes being marked as used by the buffer.
178178
pub trait FixedBuffer {
179-
/// Input a vector of bytes. If the buffer becomes full, proccess it with the provided
179+
/// Input a vector of bytes. If the buffer becomes full, process it with the provided
180180
/// function and then clear the buffer.
181181
fn input(&mut self, input: &[u8], func: &fn(&[u8]));
182182

branches/snap-stage3/src/libextra/crypto/digest.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ pub trait Digest {
4747
fn output_bits(&self) -> uint;
4848

4949
/**
50-
* Convenience functon that feeds a string into a digest
50+
* Convenience function that feeds a string into a digest.
5151
*
5252
* # Arguments
5353
*
54-
* * in The string to feed into the digest
54+
* * `input` The string to feed into the digest
5555
*/
5656
fn input_str(&mut self, input: &str) {
5757
self.input(input.as_bytes());
5858
}
5959

6060
/**
61-
* Convenience functon that retrieves the result of a digest as a
61+
* Convenience function that retrieves the result of a digest as a
6262
* ~str in hexadecimal format.
6363
*/
6464
fn result_str(&mut self) -> ~str {

branches/snap-stage3/src/libextra/enum_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct EnumSet<E> {
1818
priv bits: uint
1919
}
2020

21-
/// An iterface for casting C-like enum to uint and back.
21+
/// An interface for casting C-like enum to uint and back.
2222
pub trait CLike {
2323
/// Converts C-like enum to uint.
2424
fn to_uint(&self) -> uint;

branches/snap-stage3/src/libextra/fileinput.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl FileInput {
156156
/**
157157
Create a `FileInput` object from a vec of files. An empty
158158
vec means lines are read from `stdin` (use `from_vec_raw` to stop
159-
this behaviour). Any occurence of `None` represents `stdin`.
159+
this behaviour). Any occurrence of `None` represents `stdin`.
160160
*/
161161
pub fn from_vec(files: ~[Option<Path>]) -> FileInput {
162162
FileInput::from_vec_raw(

branches/snap-stage3/src/libextra/flate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adle
4747
static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
4848

4949
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
50+
#[fixed_stack_segment]; #[inline(never)];
51+
5052
do bytes.as_imm_buf |b, len| {
5153
unsafe {
5254
let mut outsz : size_t = 0;
@@ -73,6 +75,8 @@ pub fn deflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
7375
}
7476

7577
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
78+
#[fixed_stack_segment]; #[inline(never)];
79+
7680
do bytes.as_imm_buf |b, len| {
7781
unsafe {
7882
let mut outsz : size_t = 0;

0 commit comments

Comments
 (0)