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 void
rust_task::reset_stack_limit() { rust_task::reset_stack_limit() {
I(thread, on_rust_stack());
uintptr_t sp = get_sp(); uintptr_t sp = get_sp();
// Have to do the rest on the C stack because it involves // Have to do the rest on the C stack because it involves
// freeing stack segments, logging, etc. // freeing stack segments, logging, etc.

View File

@ -2761,16 +2761,59 @@ 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 { fn invoke(bcx: block, llfn: ValueRef, llargs: [ValueRef]) -> block {
let _icx = bcx.insn_ctxt("invoke_"); 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; } if bcx.unreachable { ret bcx; }
if need_invoke(bcx) {
log(error, "invoking");
let normal_bcx = sub_block(bcx, "normal return"); let normal_bcx = sub_block(bcx, "normal return");
Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx)); Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx));
ret normal_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 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)) { fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
let mut bcx = bcx; let mut bcx = bcx;
loop { loop {
@ -2786,6 +2829,9 @@ fn get_landing_pad(bcx: block) -> BasicBlockRef {
} }
} }
fn get_landing_pad(bcx: block) -> BasicBlockRef {
let _icx = bcx.insn_ctxt("get_landing_pad");
let mut cached = none, pad_bcx = bcx; // Guaranteed to be set below let mut cached = none, pad_bcx = bcx; // Guaranteed to be set below
in_lpad_scope_cx(bcx) {|info| in_lpad_scope_cx(bcx) {|info|
// If there is a valid landing pad still around, use it // If there is a valid landing pad still around, use it