Skip to content

Commit 8e45122

Browse files
committed
---
yaml --- r: 101803 b: refs/heads/master c: 8d6fef6 h: refs/heads/master i: 101801: 3e3765c 101799: 9b84d1a v: v3
1 parent 7c94020 commit 8e45122

File tree

40 files changed

+287
-455
lines changed

40 files changed

+287
-455
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 67841793522889a9cbcb93ab066ff3b744499e7d
2+
refs/heads/master: 8d6fef674dccae39f52aabfe0f77503f2d7fe464
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 6e7f170fedd3c526a643c0b2d13863acd982be02
55
refs/heads/try: a97642026c18a624ff6ea01075dd9550f8ed07ff

trunk/mk/crates.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ TOOLS := compiletest rustdoc rustc
5757

5858
DEPS_std := native:rustrt native:compiler-rt
5959
DEPS_extra := std term sync serialize getopts collections
60-
DEPS_green := std
60+
DEPS_green := std native:context_switch
6161
DEPS_rustuv := std native:uv native:uv_support
6262
DEPS_native := std
6363
DEPS_syntax := std extra term serialize collections

trunk/mk/rt.mk

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
# that's per-target so you're allowed to conditionally add files based on the
3636
# target.
3737
################################################################################
38-
NATIVE_LIBS := rustrt sundown uv_support morestack miniz
38+
NATIVE_LIBS := rustrt sundown uv_support morestack miniz context_switch
3939

4040
# $(1) is the target triple
4141
define NATIVE_LIBRARIES
@@ -54,9 +54,10 @@ NATIVE_DEPS_rustrt_$(1) := rust_builtin.c \
5454
rust_android_dummy.c \
5555
rust_test_helpers.c \
5656
rust_try.ll \
57-
arch/$$(HOST_$(1))/_context.S \
5857
arch/$$(HOST_$(1))/record_sp.S
5958
NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
59+
NATIVE_DEPS_context_switch_$(1) := \
60+
arch/$$(HOST_$(1))/_context.S
6061

6162
################################################################################
6263
# You shouldn't find it that necessary to edit anything below this line.

trunk/src/libarena/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::cast::{transmute, transmute_mut, transmute_mut_region};
3333
use std::cast;
3434
use std::cell::{Cell, RefCell};
3535
use std::mem;
36+
use std::cmp;
3637
use std::num;
3738
use std::kinds::marker;
3839
use std::rc::Rc;
@@ -183,7 +184,7 @@ impl Arena {
183184
// Functions for the POD part of the arena
184185
fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 {
185186
// Allocate a new chunk.
186-
let new_min_chunk_size = num::max(n_bytes, self.chunk_size());
187+
let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
187188
self.chunks.set(@Cons(self.pod_head.clone(), self.chunks.get()));
188189
self.pod_head =
189190
chunk(num::next_power_of_two(new_min_chunk_size + 1u), true);
@@ -223,7 +224,7 @@ impl Arena {
223224
fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint)
224225
-> (*u8, *u8) {
225226
// Allocate a new chunk.
226-
let new_min_chunk_size = num::max(n_bytes, self.chunk_size());
227+
let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
227228
self.chunks.set(@Cons(self.head.clone(), self.chunks.get()));
228229
self.head =
229230
chunk(num::next_power_of_two(new_min_chunk_size + 1u), false);

trunk/src/libcollections/bitv.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use std::cmp;
1515
use std::iter::RandomAccessIterator;
1616
use std::iter::{Rev, Enumerate, Repeat, Map, Zip};
17-
use std::num;
1817
use std::ops;
1918
use std::uint;
2019
use std::vec;
@@ -846,7 +845,7 @@ impl MutableSet<uint> for BitvSet {
846845
}
847846
let nbits = self.capacity();
848847
if value >= nbits {
849-
let newsize = num::max(value, nbits * 2) / uint::BITS + 1;
848+
let newsize = cmp::max(value, nbits * 2) / uint::BITS + 1;
850849
assert!(newsize > self.bitv.storage.len());
851850
self.bitv.storage.grow(newsize, &0);
852851
}
@@ -881,7 +880,7 @@ impl BitvSet {
881880
fn commons<'a>(&'a self, other: &'a BitvSet)
882881
-> Map<'static, ((uint, &'a uint), &'a ~[uint]), (uint, uint, uint),
883882
Zip<Enumerate<vec::Items<'a, uint>>, Repeat<&'a ~[uint]>>> {
884-
let min = num::min(self.bitv.storage.len(), other.bitv.storage.len());
883+
let min = cmp::min(self.bitv.storage.len(), other.bitv.storage.len());
885884
self.bitv.storage.slice(0, min).iter().enumerate()
886885
.zip(Repeat::new(&other.bitv.storage))
887886
.map(|((i, &w), o_store)| (i * uint::BITS, w, o_store[i]))

trunk/src/libcollections/ringbuf.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! RingBuf implements the trait Deque. It should be imported with `use
1414
//! extra::container::Deque`.
1515
16-
use std::num;
16+
use std::cmp;
1717
use std::vec;
1818
use std::iter::{Rev, RandomAccessIterator};
1919

@@ -120,7 +120,7 @@ impl<T> RingBuf<T> {
120120
/// Create an empty RingBuf with space for at least `n` elements.
121121
pub fn with_capacity(n: uint) -> RingBuf<T> {
122122
RingBuf{nelts: 0, lo: 0,
123-
elts: vec::from_fn(num::max(MINIMUM_CAPACITY, n), |_| None)}
123+
elts: vec::from_fn(cmp::max(MINIMUM_CAPACITY, n), |_| None)}
124124
}
125125

126126
/// Retrieve an element in the RingBuf by index

trunk/src/libextra/test.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use time::precise_time_ns;
2727
use collections::TreeMap;
2828

2929
use std::clone::Clone;
30+
use std::cmp;
3031
use std::io;
3132
use std::io::File;
3233
use std::io::Writer;
@@ -1003,7 +1004,7 @@ impl MetricMap {
10031004
if delta.abs() <= noise {
10041005
LikelyNoise
10051006
} else {
1006-
let pct = delta.abs() / (vold.value).max(&f64::EPSILON) * 100.0;
1007+
let pct = delta.abs() / cmp::max(vold.value, f64::EPSILON) * 100.0;
10071008
if vold.noise < 0.0 {
10081009
// When 'noise' is negative, it means we want
10091010
// to see deltas that go up over time, and can
@@ -1126,7 +1127,7 @@ impl BenchHarness {
11261127
if self.iterations == 0 {
11271128
0
11281129
} else {
1129-
self.ns_elapsed() / self.iterations.max(&1)
1130+
self.ns_elapsed() / cmp::max(self.iterations, 1)
11301131
}
11311132
}
11321133
@@ -1149,7 +1150,7 @@ impl BenchHarness {
11491150
if self.ns_per_iter() == 0 {
11501151
n = 1_000_000;
11511152
} else {
1152-
n = 1_000_000 / self.ns_per_iter().max(&1);
1153+
n = 1_000_000 / cmp::max(self.ns_per_iter(), 1);
11531154
}
11541155
// if the first run took more than 1ms we don't want to just
11551156
// be left doing 0 iterations on every loop. The unfortunate
@@ -1215,6 +1216,7 @@ impl BenchHarness {
12151216
}
12161217
12171218
pub mod bench {
1219+
use std::cmp;
12181220
use test::{BenchHarness, BenchSamples};
12191221
12201222
pub fn benchmark(f: |&mut BenchHarness|) -> BenchSamples {
@@ -1227,7 +1229,7 @@ pub mod bench {
12271229
12281230
let ns_iter_summ = bs.auto_bench(f);
12291231
1230-
let ns_iter = (ns_iter_summ.median as u64).max(&1);
1232+
let ns_iter = cmp::max(ns_iter_summ.median as u64, 1);
12311233
let iter_s = 1_000_000_000 / ns_iter;
12321234
let mb_s = (bs.bytes * iter_s) / 1_000_000;
12331235

trunk/src/libglob/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#[license = "MIT/ASL2"];
3030

3131
use std::cell::Cell;
32-
use std::{os, path};
32+
use std::{cmp, os, path};
3333
use std::io::fs;
3434
use std::path::is_sep;
3535

@@ -106,7 +106,7 @@ pub fn glob_with(pattern: &str, options: MatchOptions) -> Paths {
106106
}
107107

108108
let root_len = pat_root.map_or(0u, |p| p.as_vec().len());
109-
let dir_patterns = pattern.slice_from(root_len.min(&pattern.len()))
109+
let dir_patterns = pattern.slice_from(cmp::min(root_len, pattern.len()))
110110
.split_terminator(is_sep).map(|s| Pattern::new(s)).to_owned_vec();
111111

112112
let todo = list_dir_sorted(&root).move_iter().map(|x|(x,0u)).to_owned_vec();

trunk/src/libgreen/context.rs

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::libc::c_void;
1211
use std::uint;
1312
use std::cast::{transmute, transmute_mut_unsafe,
1413
transmute_region, transmute_mut_region};
1514
use stack::Stack;
1615
use std::unstable::stack;
16+
use std::unstable::raw;
1717

1818
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
1919
// SSE regs. It would be marginally better not to do this. In C++ we
@@ -22,47 +22,33 @@ use std::unstable::stack;
2222
// the registers are sometimes empty, but the discriminant would
2323
// then misalign the regs again.
2424
pub struct Context {
25-
/// The context entry point, saved here for later destruction
26-
priv start: Option<~proc()>,
2725
/// Hold the registers while the task or scheduler is suspended
2826
priv regs: ~Registers,
2927
/// Lower bound and upper bound for the stack
3028
priv stack_bounds: Option<(uint, uint)>,
3129
}
3230

31+
pub type InitFn = extern "C" fn(uint, *(), *()) -> !;
32+
3333
impl Context {
3434
pub fn empty() -> Context {
3535
Context {
36-
start: None,
3736
regs: new_regs(),
3837
stack_bounds: None,
3938
}
4039
}
4140

4241
/// Create a new context that will resume execution by running proc()
43-
pub fn new(start: proc(), stack: &mut Stack) -> Context {
44-
// The C-ABI function that is the task entry point
45-
//
46-
// Note that this function is a little sketchy. We're taking a
47-
// procedure, transmuting it to a stack-closure, and then calling to
48-
// closure. This leverages the fact that the representation of these two
49-
// types is the same.
50-
//
51-
// The reason that we're doing this is that this procedure is expected
52-
// to never return. The codegen which frees the environment of the
53-
// procedure occurs *after* the procedure has completed, and this means
54-
// that we'll never actually free the procedure.
55-
//
56-
// To solve this, we use this transmute (to not trigger the procedure
57-
// deallocation here), and then store a copy of the procedure in the
58-
// `Context` structure returned. When the `Context` is deallocated, then
59-
// the entire procedure box will be deallocated as well.
60-
extern fn task_start_wrapper(f: &proc()) {
61-
unsafe {
62-
let f: &|| = transmute(f);
63-
(*f)()
64-
}
65-
}
42+
///
43+
/// The `init` function will be run with `arg` and the `start` procedure
44+
/// split up into code and env pointers. It is required that the `init`
45+
/// function never return.
46+
///
47+
/// FIXME: this is basically an awful the interface. The main reason for
48+
/// this is to reduce the number of allocations made when a green
49+
/// task is spawned as much as possible
50+
pub fn new(init: InitFn, arg: uint, start: proc(),
51+
stack: &mut Stack) -> Context {
6652

6753
let sp: *uint = stack.end();
6854
let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
@@ -74,14 +60,10 @@ impl Context {
7460
transmute_region(&*regs));
7561
};
7662

77-
// FIXME #7767: Putting main into a ~ so it's a thin pointer and can
78-
// be passed to the spawn function. Another unfortunate
79-
// allocation
80-
let start = ~start;
81-
8263
initialize_call_frame(&mut *regs,
83-
task_start_wrapper as *c_void,
84-
unsafe { transmute(&*start) },
64+
init,
65+
arg,
66+
unsafe { transmute(start) },
8567
sp);
8668

8769
// Scheduler tasks don't have a stack in the "we allocated it" sense,
@@ -96,7 +78,6 @@ impl Context {
9678
Some((stack_base as uint, sp as uint))
9779
};
9880
return Context {
99-
start: Some(start),
10081
regs: regs,
10182
stack_bounds: bounds,
10283
}
@@ -138,7 +119,7 @@ impl Context {
138119
}
139120
}
140121

141-
#[link(name = "rustrt", kind = "static")]
122+
#[link(name = "context_switch", kind = "static")]
142123
extern {
143124
fn rust_swap_registers(out_regs: *mut Registers, in_regs: *Registers);
144125
}
@@ -185,13 +166,17 @@ fn new_regs() -> ~Registers {
185166
}
186167

187168
#[cfg(target_arch = "x86")]
188-
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
189-
sp: *mut uint) {
169+
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
170+
procedure: raw::Procedure, sp: *mut uint) {
190171

172+
// x86 has interesting stack alignment requirements, so do some alignment
173+
// plus some offsetting to figure out what the actual stack should be.
191174
let sp = align_down(sp);
192175
let sp = mut_offset(sp, -4);
193176

194-
unsafe { *sp = arg as uint };
177+
unsafe { *mut_offset(sp, 2) = procedure.env as uint };
178+
unsafe { *mut_offset(sp, 1) = procedure.code as uint };
179+
unsafe { *mut_offset(sp, 0) = arg as uint };
195180
let sp = mut_offset(sp, -1);
196181
unsafe { *sp = 0 }; // The final return address
197182

@@ -215,14 +200,18 @@ fn new_regs() -> ~Registers { ~([0, .. 34]) }
215200
fn new_regs() -> ~Registers { ~([0, .. 22]) }
216201

217202
#[cfg(target_arch = "x86_64")]
218-
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
219-
sp: *mut uint) {
203+
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
204+
procedure: raw::Procedure, sp: *mut uint) {
205+
extern { fn rust_bootstrap_green_task(); }
220206

221207
// Redefinitions from rt/arch/x86_64/regs.h
222-
static RUSTRT_ARG0: uint = 3;
223208
static RUSTRT_RSP: uint = 1;
224209
static RUSTRT_IP: uint = 8;
225210
static RUSTRT_RBP: uint = 2;
211+
static RUSTRT_R12: uint = 4;
212+
static RUSTRT_R13: uint = 5;
213+
static RUSTRT_R14: uint = 6;
214+
static RUSTRT_R15: uint = 7;
226215

227216
let sp = align_down(sp);
228217
let sp = mut_offset(sp, -1);
@@ -231,13 +220,23 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
231220
unsafe { *sp = 0; }
232221

233222
rtdebug!("creating call frame");
234-
rtdebug!("fptr {}", fptr);
235-
rtdebug!("arg {}", arg);
223+
rtdebug!("fptr {:#x}", fptr as uint);
224+
rtdebug!("arg {:#x}", arg);
236225
rtdebug!("sp {}", sp);
237226

238-
regs[RUSTRT_ARG0] = arg as uint;
227+
// These registers are frobbed by rust_bootstrap_green_task into the right
228+
// location so we can invoke the "real init function", `fptr`.
229+
regs[RUSTRT_R12] = arg as uint;
230+
regs[RUSTRT_R13] = procedure.code as uint;
231+
regs[RUSTRT_R14] = procedure.env as uint;
232+
regs[RUSTRT_R15] = fptr as uint;
233+
234+
// These registers are picked up by the regulard context switch paths. These
235+
// will put us in "mostly the right context" except for frobbing all the
236+
// arguments to the right place. We have the small trampoline code inside of
237+
// rust_bootstrap_green_task to do that.
239238
regs[RUSTRT_RSP] = sp as uint;
240-
regs[RUSTRT_IP] = fptr as uint;
239+
regs[RUSTRT_IP] = rust_bootstrap_green_task as uint;
241240

242241
// Last base pointer on the stack should be 0
243242
regs[RUSTRT_RBP] = 0;
@@ -250,18 +249,26 @@ type Registers = [uint, ..32];
250249
fn new_regs() -> ~Registers { ~([0, .. 32]) }
251250

252251
#[cfg(target_arch = "arm")]
253-
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
254-
sp: *mut uint) {
252+
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
253+
procedure: raw::Procedure, sp: *mut uint) {
254+
extern { fn rust_bootstrap_green_task(); }
255+
255256
let sp = align_down(sp);
256257
// sp of arm eabi is 8-byte aligned
257258
let sp = mut_offset(sp, -2);
258259

259260
// The final return address. 0 indicates the bottom of the stack
260261
unsafe { *sp = 0; }
261262

262-
regs[0] = arg as uint; // r0
263-
regs[13] = sp as uint; // #53 sp, r13
264-
regs[14] = fptr as uint; // #60 pc, r15 --> lr
263+
// ARM uses the same technique as x86_64 to have a landing pad for the start
264+
// of all new green tasks. Neither r1/r2 are saved on a context switch, so
265+
// the shim will copy r3/r4 into r1/r2 and then execute the function in r5
266+
regs[0] = arg as uint; // r0
267+
regs[3] = procedure.code as uint; // r3
268+
regs[4] = procedure.env as uint; // r4
269+
regs[5] = fptr as uint; // r5
270+
regs[13] = sp as uint; // #52 sp, r13
271+
regs[14] = rust_bootstrap_green_task as uint; // #56 pc, r14 --> lr
265272
}
266273

267274
#[cfg(target_arch = "mips")]
@@ -271,8 +278,8 @@ type Registers = [uint, ..32];
271278
fn new_regs() -> ~Registers { ~([0, .. 32]) }
272279

273280
#[cfg(target_arch = "mips")]
274-
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
275-
sp: *mut uint) {
281+
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
282+
procedure: raw::Procedure, sp: *mut uint) {
276283
let sp = align_down(sp);
277284
// sp of mips o32 is 8-byte aligned
278285
let sp = mut_offset(sp, -2);

0 commit comments

Comments
 (0)