Skip to content

Commit fe0d0f1

Browse files
committed
---
yaml --- r: 91647 b: refs/heads/auto c: e348343 h: refs/heads/master i: 91645: 353b747 91643: 223bf40 91639: 3dcdcce 91631: 26ff522 91615: dc284a8 91583: ddc07b9 91519: 356bc58 91391: 19b8f95 91135: bad86df v: v3
1 parent c7c53c9 commit fe0d0f1

File tree

340 files changed

+10652
-9370
lines changed

Some content is hidden

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

340 files changed

+10652
-9370
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: 23746ae9904b8b1a08d4dde46f3a9b3acb8d9868
16+
refs/heads/auto: e34834375db649a16d45c902f7f0209a44c7e42e
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
*.cps
3131
*.log
3232
*.pdf
33-
*.epub
3433
*.html
3534
*.pg
3635
*.toc

branches/auto/Makefile.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ ifdef TRACE
125125
CFG_RUSTC_FLAGS += -Z trace
126126
endif
127127
ifndef DEBUG_BORROWS
128-
RUSTFLAGS_STAGE0 += -Z no-debug-borrows
129128
RUSTFLAGS_STAGE1 += -Z no-debug-borrows
130129
RUSTFLAGS_STAGE2 += -Z no-debug-borrows
131130
endif

branches/auto/doc/tutorial-conditions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ The `raise` method maps a value of the condition's input type to its output type
351351
The input type should therefore convey all relevant information to the condition handler.
352352
The output type should convey all relevant information _for continuing execution at the site of error_.
353353
When the error site raises a condition handler,
354-
the `Condition::raise` method searches task-local storage (TLS) for the innermost installed _handler_,
354+
the `Condition::raise` method searches for the innermost installed task-local condition _handler_,
355355
and if any such handler is found, calls it with the provided input value.
356356
If no handler is found, `Condition::raise` will fail the task with an appropriate error message.
357357

branches/auto/doc/tutorial-ffi.md

Lines changed: 146 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ 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) };
24-
println!("max compressed length of a 100 byte buffer: {}", x);
25+
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
2526
}
2627
~~~~
2728

@@ -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,28 +181,98 @@ 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

142-
# Stack management
143-
144-
Rust tasks by default run on a "large stack". This is actually implemented as a
145-
reserving a large segment of the address space and then lazily mapping in pages
146-
as they are needed. When calling an external C function, the code is invoked on
147-
the same stack as the rust stack. This means that there is no extra
148-
stack-switching mechanism in place because it is assumed that the large stack
149-
for the rust task is plenty for the C function to have.
150-
151-
A planned future improvement (net yet implemented at the time of this writing)
152-
is to have a guard page at the end of every rust stack. No rust function will
153-
hit this guard page (due to rust's usage of LLVM's __morestack). The intention
154-
for this unmapped page is to prevent infinite recursion in C from overflowing
155-
onto other rust stacks. If the guard page is hit, then the process will be
156-
terminated with a message saying that the guard page was hit.
157-
158-
For normal external function usage, this all means that there shouldn't be any
159-
need for any extra effort on a user's perspective. The C stack naturally
160-
interleaves with the rust stack, and it's "large enough" for both to
161-
interoperate. If, however, it is determined that a larger stack is necessary,
162-
there are appropriate functions in the task spawning API to control the size of
163-
the stack of the task which is spawned.
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+
segment. 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).
164276

165277
# Destructors
166278

@@ -184,6 +296,9 @@ pub struct Unique<T> {
184296
185297
impl<T: Send> Unique<T> {
186298
pub fn new(value: T) -> Unique<T> {
299+
#[fixed_stack_segment];
300+
#[inline(never)];
301+
187302
unsafe {
188303
let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
189304
assert!(!ptr::is_null(ptr));
@@ -207,6 +322,9 @@ impl<T: Send> Unique<T> {
207322
#[unsafe_destructor]
208323
impl<T: Send> Drop for Unique<T> {
209324
fn drop(&mut self) {
325+
#[fixed_stack_segment];
326+
#[inline(never)];
327+
210328
unsafe {
211329
let x = intrinsics::init(); // dummy value to swap in
212330
// moving the object out is needed to call the destructor
@@ -266,8 +384,8 @@ extern {
266384
}
267385
268386
fn main() {
269-
println!("You have readline version {} installed.",
270-
rl_readline_version as int);
387+
println(fmt!("You have readline version %d installed.",
388+
rl_readline_version as int));
271389
}
272390
~~~
273391

@@ -300,32 +418,15 @@ calling foreign functions. Some foreign functions, most notably the Windows API,
300418
conventions. Rust provides a way to tell the compiler which convention to use:
301419

302420
~~~~
303-
#[cfg(target_os = "win32", target_arch = "x86")]
421+
#[cfg(target_os = "win32")]
304422
#[link_name = "kernel32"]
305423
extern "stdcall" {
306424
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
307425
}
308426
~~~~
309427

310-
This applies to the entire `extern` block. The list of supported ABI constraints
311-
are:
312-
313-
* `stdcall`
314-
* `aapcs`
315-
* `cdecl`
316-
* `fastcall`
317-
* `Rust`
318-
* `rust-intrinsic`
319-
* `system`
320-
* `C`
321-
322-
Most of the abis in this list are self-explanatory, but the `system` abi may
323-
seem a little odd. This constraint selects whatever the appropriate ABI is for
324-
interoperating with the target's libraries. For example, on win32 with a x86
325-
architecture, this means that the abi used would be `stdcall`. On x86_64,
326-
however, windows uses the `C` calling convention, so `C` would be used. This
327-
means that in our previous example, we could have used `extern "system" { ... }`
328-
to define a block for all windows systems, not just x86 ones.
428+
This applies to the entire `extern` block, and must be either `"cdecl"` or
429+
`"stdcall"`. The compiler may eventually support other calling conventions.
329430

330431
# Interoperability with foreign code
331432

branches/auto/mk/clean.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ clean-misc:
5353
$(Q)rm -Rf tmp/*
5454
$(Q)rm -Rf rust-stage0-*.tar.bz2 $(PKG_NAME)-*.tar.gz dist
5555
$(Q)rm -Rf $(foreach ext, \
56-
html aux cp fn ky log pdf pg toc tp vr cps epub, \
56+
html aux cp fn ky log pdf pg toc tp vr cps, \
5757
$(wildcard doc/*.$(ext)))
5858
$(Q)find doc/std doc/extra -mindepth 1 | xargs rm -Rf
5959
$(Q)rm -Rf doc/version.md

branches/auto/mk/docs.mk

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,6 @@ doc/rust.tex: rust.md doc/version.md
6464
--from=markdown --to=latex \
6565
--output=$@
6666

67-
DOCS += doc/rust.epub
68-
doc/rust.epub: rust.md doc/version_info.html doc/rust.css doc/manual.inc
69-
@$(call E, pandoc: $@)
70-
$(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
71-
"$(CFG_PANDOC)" \
72-
--standalone --toc \
73-
--section-divs \
74-
--number-sections \
75-
--from=markdown --to=epub \
76-
--css=rust.css --include-in-header=doc/manual.inc \
77-
--include-before-body=doc/version_info.html \
78-
--output=$@
79-
80-
8167
DOCS += doc/tutorial.tex
8268
doc/tutorial.tex: tutorial.md doc/version.md
8369
@$(call E, pandoc: $@)
@@ -112,17 +98,6 @@ doc/tutorial.html: tutorial.md doc/version_info.html doc/rust.css
11298
--include-before-body=doc/version_info.html \
11399
--output=$@
114100

115-
DOCS += doc/tutorial.epub
116-
doc/tutorial.epub: tutorial.md doc/version_info.html doc/rust.css
117-
@$(call E, pandoc: $@)
118-
$(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
119-
$(CFG_PANDOC) --standalone --toc \
120-
--section-divs --number-sections \
121-
--from=markdown --to=epub --css=rust.css \
122-
--include-before-body=doc/version_info.html \
123-
--output=$@
124-
125-
126101
DOCS_L10N += doc/l10n/ja/tutorial.html
127102
doc/l10n/ja/tutorial.html: doc/l10n/ja/tutorial.md doc/version_info.html doc/rust.css
128103
@$(call E, pandoc: $@)

branches/auto/mk/rt.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ LIBUV_MAKEFILE_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv/Makefile
207207

208208
$$(LIBUV_MAKEFILE_$(1)): $$(LIBUV_DEPS)
209209
(cd $(S)src/libuv/ && \
210-
$$(CFG_PYTHON) ./gyp_uv.py -f make -Dtarget_arch=$$(LIBUV_ARCH_$(1)) \
210+
$$(CFG_PYTHON) ./gyp_uv -f make -Dtarget_arch=$$(LIBUV_ARCH_$(1)) \
211211
-D ninja \
212212
-DOS=$$(LIBUV_OSTYPE_$(1)) \
213213
-Goutput_dir=$$(@D) --generator-output $$(@D))
@@ -218,7 +218,7 @@ $$(LIBUV_MAKEFILE_$(1)): $$(LIBUV_DEPS)
218218
ifdef CFG_WINDOWSY_$(1)
219219
$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS)
220220
$$(Q)$$(MAKE) -C $$(S)src/libuv -f Makefile.mingw \
221-
CC="$$(CC) $$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
221+
CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
222222
AR="$$(AR_$(1))" \
223223
V=$$(VERBOSE)
224224
$$(Q)cp $$(S)src/libuv/libuv.a $$@

0 commit comments

Comments
 (0)