Skip to content

Commit df39932

Browse files
committed
auto merge of #7452 : dotdash/rust/self_indirection, r=cmr
Currently we pass all "self" arguments by reference, for the pointer variants this means that we end up with double indirection which causes a unnecessary performance hit. The fix itself is pretty straight-forward and just means that "self" needs to be handled like any other argument, except for by-value "self" which still needs to be passed by reference. This is because non-pointer types can't just be stuffed into the environment slot which is used to pass "self". What made things tricky is that there was also a bug in the typechecker where the method map entries are created. For type impls, that stored the base type instead of the actual self-type in the method map, e.g. Foo instead of &Foo for &self. That worked with pass-by-reference, but fails with pass-by-value which needs the real type. Code that makes use of methods seems to be about 10% faster with this change. Also, build times are reduced by about 4%. Fixes #4355, #4402, #5280, #4406 and #7285
2 parents 439b13f + 765a290 commit df39932

File tree

8 files changed

+82
-127
lines changed

8 files changed

+82
-127
lines changed

src/librustc/middle/trans/asm.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
4141
callee::trans_arg_expr(bcx,
4242
expr_ty(bcx, out),
4343
ty::ByCopy,
44-
ast::sty_static,
4544
out,
4645
&mut cleanups,
4746
None,
@@ -57,7 +56,6 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
5756
callee::trans_arg_expr(bcx,
5857
expr_ty(bcx, e),
5958
ty::ByCopy,
60-
ast::sty_static,
6159
e,
6260
&mut cleanups,
6361
None,
@@ -79,7 +77,6 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
7977
callee::trans_arg_expr(bcx,
8078
expr_ty(bcx, in),
8179
ty::ByCopy,
82-
ast::sty_static,
8380
in,
8481
&mut cleanups,
8582
None,

src/librustc/middle/trans/base.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,18 +1626,11 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt,
16261626
let _icx = push_ctxt("create_llargs_for_fn_args");
16271627

16281628
match self_arg {
1629-
impl_self(tt) => {
1629+
impl_self(tt, self_mode) => {
16301630
cx.llself = Some(ValSelfData {
16311631
v: cx.llenv,
16321632
t: tt,
1633-
is_owned: false
1634-
});
1635-
}
1636-
impl_owned_self(tt) => {
1637-
cx.llself = Some(ValSelfData {
1638-
v: cx.llenv,
1639-
t: tt,
1640-
is_owned: true
1633+
is_copy: self_mode == ty::ByCopy
16411634
});
16421635
}
16431636
no_self => ()
@@ -1676,12 +1669,18 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
16761669

16771670
match fcx.llself {
16781671
Some(slf) => {
1679-
let self_val = PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to());
1680-
fcx.llself = Some(ValSelfData {v: self_val, ..slf});
1672+
let self_val = if slf.is_copy
1673+
&& datum::appropriate_mode(slf.t).is_by_value() {
1674+
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
1675+
let alloc = alloc_ty(bcx, slf.t);
1676+
Store(bcx, tmp, alloc);
1677+
alloc
1678+
} else {
1679+
PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to())
1680+
};
16811681

1682-
if slf.is_owned {
1683-
add_clean(bcx, slf.v, slf.t);
1684-
}
1682+
fcx.llself = Some(ValSelfData {v: self_val, ..slf});
1683+
add_clean(bcx, self_val, slf.t);
16851684
}
16861685
_ => {}
16871686
}
@@ -1758,7 +1757,7 @@ pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
17581757
}
17591758
}
17601759

1761-
pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, }
1760+
pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
17621761

17631762
// trans_closure: Builds an LLVM function out of a source function.
17641763
// If the function closes over its environment a closure will be

src/librustc/middle/trans/callee.rs

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ pub struct FnData {
6262
pub struct MethodData {
6363
llfn: ValueRef,
6464
llself: ValueRef,
65+
temp_cleanup: Option<ValueRef>,
6566
self_ty: ty::t,
6667
self_mode: ty::SelfMode,
67-
explicit_self: ast::explicit_self_
6868
}
6969

7070
pub enum CalleeData {
@@ -615,10 +615,7 @@ pub fn trans_call_inner(in_cx: block,
615615
}
616616
Method(d) => {
617617
// Weird but true: we pass self in the *environment* slot!
618-
let llself = PointerCast(bcx,
619-
d.llself,
620-
Type::opaque_box(ccx).ptr_to());
621-
(d.llfn, llself)
618+
(d.llfn, d.llself)
622619
}
623620
Closure(d) => {
624621
// Closures are represented as (llfn, llclosure) pair:
@@ -647,11 +644,12 @@ pub fn trans_call_inner(in_cx: block,
647644

648645

649646
// Now that the arguments have finished evaluating, we need to revoke
650-
// the cleanup for the self argument, if it exists
647+
// the cleanup for the self argument
651648
match callee.data {
652-
Method(d) if d.self_mode == ty::ByCopy ||
653-
d.explicit_self == ast::sty_value => {
654-
revoke_clean(bcx, d.llself);
649+
Method(d) => {
650+
for d.temp_cleanup.iter().advance |&v| {
651+
revoke_clean(bcx, v);
652+
}
655653
}
656654
_ => {}
657655
}
@@ -772,7 +770,6 @@ pub fn trans_args(cx: block,
772770
trans_arg_expr(bcx,
773771
arg_tys[i],
774772
ty::ByCopy,
775-
ast::sty_static,
776773
*arg_expr,
777774
&mut temp_cleanups,
778775
if i == last { ret_flag } else { None },
@@ -806,18 +803,16 @@ pub enum AutorefArg {
806803
pub fn trans_arg_expr(bcx: block,
807804
formal_arg_ty: ty::t,
808805
self_mode: ty::SelfMode,
809-
ex_self: ast::explicit_self_,
810806
arg_expr: @ast::expr,
811807
temp_cleanups: &mut ~[ValueRef],
812808
ret_flag: Option<ValueRef>,
813809
autoref_arg: AutorefArg) -> Result {
814810
let _icx = push_ctxt("trans_arg_expr");
815811
let ccx = bcx.ccx();
816812

817-
debug!("trans_arg_expr(formal_arg_ty=(%s), explicit_self=%? self_mode=%?, arg_expr=%s, \
813+
debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s, \
818814
ret_flag=%?)",
819815
formal_arg_ty.repr(bcx.tcx()),
820-
ex_self,
821816
self_mode,
822817
arg_expr.repr(bcx.tcx()),
823818
ret_flag.map(|v| bcx.val_to_str(*v)));
@@ -877,9 +872,15 @@ pub fn trans_arg_expr(bcx: block,
877872
val = arg_datum.to_ref_llval(bcx);
878873
}
879874
DontAutorefArg => {
880-
match (self_mode, ex_self) {
881-
(ty::ByRef, ast::sty_value) => {
882-
debug!("by value self with type %s, storing to scratch",
875+
match self_mode {
876+
ty::ByRef => {
877+
// This assertion should really be valid, but because
878+
// the explicit self code currently passes by-ref, it
879+
// does not hold.
880+
//
881+
//assert !bcx.ccx().maps.moves_map.contains_key(
882+
// &arg_expr.id);
883+
debug!("by ref arg with type %s, storing to scratch",
883884
bcx.ty_to_str(arg_datum.ty));
884885
let scratch = scratch_datum(bcx, arg_datum.ty, false);
885886

@@ -896,18 +897,7 @@ pub fn trans_arg_expr(bcx: block,
896897

897898
val = scratch.to_ref_llval(bcx);
898899
}
899-
(ty::ByRef, _) => {
900-
// This assertion should really be valid, but because
901-
// the explicit self code currently passes by-ref, it
902-
// does not hold.
903-
//
904-
//assert !bcx.ccx().maps.moves_map.contains_key(
905-
// &arg_expr.id);
906-
debug!("by ref arg with type %s",
907-
bcx.ty_to_str(arg_datum.ty));
908-
val = arg_datum.to_ref_llval(bcx);
909-
}
910-
(ty::ByCopy, _) => {
900+
ty::ByCopy => {
911901
if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
912902
arg_datum.appropriate_mode().is_by_ref() {
913903
debug!("by copy arg with type %s, storing to scratch",
@@ -930,7 +920,7 @@ pub fn trans_arg_expr(bcx: block,
930920
ByRef(_) => val = scratch.val,
931921
}
932922
} else {
933-
debug!("by copy arg with type %s");
923+
debug!("by copy arg with type %s", bcx.ty_to_str(arg_datum.ty));
934924
match arg_datum.mode {
935925
ByRef(_) => val = Load(bcx, arg_datum.val),
936926
ByValue => val = arg_datum.val,
@@ -944,10 +934,6 @@ pub fn trans_arg_expr(bcx: block,
944934
if formal_arg_ty != arg_datum.ty {
945935
// this could happen due to e.g. subtyping
946936
let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, &formal_arg_ty);
947-
let llformal_arg_ty = match self_mode {
948-
ty::ByRef => llformal_arg_ty.ptr_to(),
949-
ty::ByCopy => llformal_arg_ty,
950-
};
951937
debug!("casting actual type (%s) to match formal (%s)",
952938
bcx.val_to_str(val), bcx.llty_str(llformal_arg_ty));
953939
val = PointerCast(bcx, val, llformal_arg_ty);

src/librustc/middle/trans/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub type ExternMap = HashMap<@str, ValueRef>;
125125
pub struct ValSelfData {
126126
v: ValueRef,
127127
t: ty::t,
128-
is_owned: bool
128+
is_copy: bool,
129129
}
130130

131131
// Here `self_ty` is the real type of the self parameter to this method. It

src/librustc/middle/trans/glue.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,7 @@ pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast:
425425
// just consist of the environment (self)
426426
assert_eq!(params.len(), 1);
427427

428-
// Take a reference to the class (because it's using the Drop trait),
429-
// do so now.
430-
let llval = alloca(bcx, val_ty(v0));
431-
Store(bcx, v0, llval);
432-
433-
let self_arg = PointerCast(bcx, llval, params[0]);
428+
let self_arg = PointerCast(bcx, v0, params[0]);
434429
let args = ~[self_arg];
435430

436431
Call(bcx, dtor_addr, args);
@@ -465,12 +460,7 @@ pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::
465460
// just consist of the environment (self)
466461
assert_eq!(params.len(), 1);
467462

468-
// Take a reference to the class (because it's using the Drop trait),
469-
// do so now.
470-
let llval = alloca(bcx, val_ty(v0));
471-
Store(bcx, v0, llval);
472-
473-
let self_arg = PointerCast(bcx, llval, params[0]);
463+
let self_arg = PointerCast(bcx, v0, params[0]);
474464
let args = ~[self_arg];
475465

476466
Call(bcx, dtor_addr, args);

src/librustc/middle/trans/inline.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core::prelude::*;
1212

1313
use metadata::csearch;
1414
use middle::astencode;
15-
use middle::trans::base::{push_ctxt,impl_owned_self, impl_self, no_self};
15+
use middle::trans::base::{push_ctxt, impl_self, no_self};
1616
use middle::trans::base::{trans_item, get_item_val, trans_fn};
1717
use middle::trans::common::*;
1818
use middle::ty;
@@ -114,8 +114,8 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
114114
debug!("calling inline trans_fn with self_ty %s",
115115
ty_to_str(ccx.tcx, self_ty));
116116
match mth.explicit_self.node {
117-
ast::sty_value => impl_owned_self(self_ty),
118-
_ => impl_self(self_ty),
117+
ast::sty_value => impl_self(self_ty, ty::ByRef),
118+
_ => impl_self(self_ty, ty::ByCopy),
119119
}
120120
}
121121
};

0 commit comments

Comments
 (0)