rustc: Only invoke when there are cleanups

This commit is contained in:
Brian Anderson 2012-03-26 13:30:56 -07:00
parent 8780db2e0b
commit 7f9ed39040
2 changed files with 65 additions and 20 deletions

View File

@ -571,7 +571,6 @@ when unwinding through __morestack).
*/
void
rust_task::reset_stack_limit() {
I(thread, on_rust_stack());
uintptr_t sp = get_sp();
// Have to do the rest on the C stack because it involves
// freeing stack segments, logging, etc.

View File

@ -2761,30 +2761,76 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t, ret_ty: ty::t,
fn invoke(bcx: block, llfn: ValueRef, llargs: [ValueRef]) -> block {
let _icx = bcx.insn_ctxt("invoke_");
// FIXME: May be worth turning this into a plain call when there are no
// cleanups to run
if bcx.unreachable { ret bcx; }
let normal_bcx = sub_block(bcx, "normal return");
Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx));
ret normal_bcx;
if need_invoke(bcx) {
log(error, "invoking");
let normal_bcx = sub_block(bcx, "normal return");
Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx));
ret normal_bcx;
} else {
log(error, "calling");
Call(bcx, llfn, llargs);
ret bcx;
}
}
fn need_invoke(bcx: block) -> bool {
if have_cached_lpad(bcx) {
ret true;
}
// Walk the scopes to look for cleanups
let mut cur = bcx;
loop {
alt cur.kind {
block_scope(info) {
for cleanup in info.cleanups {
alt cleanup {
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) {
if cleanup_type == normal_exit_and_unwind {
ret true;
}
}
}
}
}
_ { }
}
cur = alt cur.parent {
parent_some(next) { next }
parent_none { ret false; }
}
}
}
fn have_cached_lpad(bcx: block) -> bool {
let mut res = false;
in_lpad_scope_cx(bcx) {|info|
alt info.landing_pad {
some(_) { res = true; }
none { res = false; }
}
}
ret res;
}
fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
let mut bcx = bcx;
loop {
alt bcx.kind {
block_scope(info) {
if info.cleanups.len() > 0u || bcx.parent == parent_none {
f(info); ret;
}
}
_ {}
}
bcx = block_parent(bcx);
}
}
fn get_landing_pad(bcx: block) -> BasicBlockRef {
let _icx = bcx.insn_ctxt("get_landing_pad");
fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
let mut bcx = bcx;
loop {
alt bcx.kind {
block_scope(info) {
if info.cleanups.len() > 0u || bcx.parent == parent_none {
f(info); ret;
}
}
_ {}
}
bcx = block_parent(bcx);
}
}
let mut cached = none, pad_bcx = bcx; // Guaranteed to be set below
in_lpad_scope_cx(bcx) {|info|