Skip to content

[WIP] Make into schedule drop for the destination again #65385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/libcore/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ impl<A, B> Iterator for Chain<A, B> where
{
type Item = A::Item;

#[inline]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With lto (thin or fat), these attributes shouldn't really make much of a difference. Is the performance regression still there when these are present ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These attributes were the cause of the perf regression

Copy link
Contributor

@gnzlbg gnzlbg Oct 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is that possible? The PR that introduced the regression did not add these attributes, so they must have already been there, right ? Without that PR, these attributes were not introducing that regression, so something else in that PR caused it.

fn next(&mut self) -> Option<A::Item> {
match self.state {
ChainState::Both => match self.a.next() {
Expand Down Expand Up @@ -117,7 +116,6 @@ impl<A, B> Iterator for Chain<A, B> where
accum
}

#[inline]
fn nth(&mut self, mut n: usize) -> Option<A::Item> {
match self.state {
ChainState::Both | ChainState::Front => {
Expand Down Expand Up @@ -157,7 +155,6 @@ impl<A, B> Iterator for Chain<A, B> where
}
}

#[inline]
fn last(self) -> Option<A::Item> {
match self.state {
ChainState::Both => {
Expand Down Expand Up @@ -198,7 +195,6 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
A: DoubleEndedIterator,
B: DoubleEndedIterator<Item=A::Item>,
{
#[inline]
fn next_back(&mut self) -> Option<A::Item> {
match self.state {
ChainState::Both => match self.b.next_back() {
Expand All @@ -213,7 +209,6 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
}
}

#[inline]
fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
match self.state {
ChainState::Both | ChainState::Back => {
Expand Down
70 changes: 49 additions & 21 deletions src/librustc_mir/build/block.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use crate::build::ForGuard::OutsideGuard;
use crate::build::matches::ArmHasGuard;
use crate::build::scope::DropKind;
use crate::hair::*;
use rustc::middle::region;
use rustc::mir::*;
use rustc::hir;
use syntax_pos::Span;

impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn ast_block(&mut self,
destination: &Place<'tcx>,
block: BasicBlock,
ast_block: &'tcx hir::Block,
source_info: SourceInfo)
-> BlockAnd<()> {
pub fn ast_block(
&mut self,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
ast_block: &'tcx hir::Block,
source_info: SourceInfo,
) -> BlockAnd<()> {
let Block {
region_scope,
opt_destruction_scope,
Expand All @@ -21,37 +25,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr,
targeted_by_break,
safety_mode
} =
self.hir.mirror(ast_block);
} = self.hir.mirror(ast_block);
self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| {
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
if targeted_by_break {
// This is a `break`-able block
let exit_block = this.cfg.start_new_block();
if let Some(scope) = scope {
// Breakable blocks assign to their destination on each
// `break`, as well as when they exit normally. So we
// can't schedule the drop in the last expression like
// normal blocks do.
let local = destination.as_local()
.expect("cannot schedule drop of non-Local place");
this.schedule_drop(span, scope, local, DropKind::Value);
}
let block_exit = this.in_breakable_scope(
None, exit_block, destination.clone(), |this| {
this.ast_block_stmts(destination, block, span, stmts, expr,
safety_mode)
this.ast_block_stmts(
destination,
None,
block,
span,
stmts,
expr,
safety_mode,
)
});
this.cfg.terminate(unpack!(block_exit), source_info,
TerminatorKind::Goto { target: exit_block });
exit_block.unit()
} else {
this.ast_block_stmts(destination, block, span, stmts, expr,
safety_mode)
this.ast_block_stmts(
destination,
scope,
block,
span,
stmts,
expr,
safety_mode,
)
}
})
})
}

fn ast_block_stmts(&mut self,
destination: &Place<'tcx>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
expr: Option<ExprRef<'tcx>>,
safety_mode: BlockSafety)
-> BlockAnd<()> {
fn ast_block_stmts(
&mut self,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
expr: Option<ExprRef<'tcx>>,
safety_mode: BlockSafety,
) -> BlockAnd<()> {
let this = self;

// This convoluted structure is to avoid using recursion as we walk down a list
Expand Down Expand Up @@ -177,7 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.block_context.currently_ignores_tail_results();
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });

unpack!(block = this.into(destination, block, expr));
unpack!(block = this.into(destination, scope, block, expr));
let popped = this.block_context.pop();

assert!(popped.map_or(false, |bf|bf.is_tail_expr()));
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.cfg
.push_assign(block, source_info, &Place::from(result), box_);

// initialize the box contents:
// Initialize the box contents. No scope is needed since the
// `Box` is already scheduled to be dropped.
unpack!(
block = this.into(
&this.hir.tcx().mk_place_deref(Place::from(result)),
block, value
None,
block,
value,
)
);
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
Expand Down
11 changes: 1 addition & 10 deletions src/librustc_mir/build/expr/as_temp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

unpack!(block = this.into(temp_place, block, expr));

if let Some(temp_lifetime) = temp_lifetime {
this.schedule_drop(
expr_span,
temp_lifetime,
temp,
DropKind::Value,
);
}
unpack!(block = this.into(temp_place, temp_lifetime, block, expr));

block.and(temp)
}
Expand Down
46 changes: 37 additions & 9 deletions src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

use crate::build::expr::category::{Category, RvalueFunc};
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use crate::build::scope::DropKind;
use crate::hair::*;
use rustc::middle::region;
use rustc::mir::*;
use rustc::ty;

Expand All @@ -11,15 +13,18 @@ use rustc_target::spec::abi::Abi;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
/// If a `drop_scope` is provided, `destination` is scheduled to be dropped
/// in `scope` once it has been initialized.
pub fn into_expr(
&mut self,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
mut block: BasicBlock,
expr: Expr<'tcx>,
) -> BlockAnd<()> {
debug!(
"into_expr(destination={:?}, block={:?}, expr={:?})",
destination, block, expr
"into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})",
destination, scope, block, expr
);

// since we frequently have to reference `self` from within a
Expand All @@ -35,6 +40,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
_ => false,
};

let schedule_drop = move |this: &mut Self| {
if let Some(drop_scope) = scope {
let local = destination.as_local()
.expect("cannot schedule drop of non-Local place");
this.schedule_drop(expr_span, drop_scope, local, DropKind::Value);
}
};

if !expr_is_block_or_scope {
this.block_context.push(BlockFrame::SubExpr);
}
Expand All @@ -47,14 +60,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} => {
let region_scope = (region_scope, source_info);
this.in_scope(region_scope, lint_level, |this| {
this.into(destination, block, value)
this.into(destination, scope, block, value)
})
}
ExprKind::Block { body: ast_block } => {
this.ast_block(destination, block, ast_block, source_info)
this.ast_block(destination, scope, block, ast_block, source_info)
}
ExprKind::Match { scrutinee, arms } => {
this.match_expr(destination, expr_span, block, scrutinee, arms)
this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
}
ExprKind::NeverToAny { source } => {
let source = this.hir.mirror(source);
Expand All @@ -67,6 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

// This is an optimization. If the expression was a call then we already have an
// unreachable block. Don't bother to terminate it and create a new one.
schedule_drop(this);
if is_call {
block.unit()
} else {
Expand Down Expand Up @@ -164,6 +178,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Goto { target: loop_block },
);

// Loops assign to their destination on each `break`. Since we
// can't easily unschedule drops, we schedule the drop now.
schedule_drop(this);
this.in_breakable_scope(
Some(loop_block),
exit_block,
Expand All @@ -185,7 +202,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// introduce a unit temporary as the destination for the loop body.
let tmp = this.get_unit_temp();
// Execute the body, branching back to the test.
let body_block_end = unpack!(this.into(&tmp, body_block, body));
// No scope is provided, since we've scheduled the drop above.
let body_block_end = unpack!(this.into(&tmp, None, body_block, body));
this.cfg.terminate(
body_block_end,
source_info,
Expand Down Expand Up @@ -234,8 +252,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
is_block_tail: None,
});
let ptr_temp = Place::from(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), block, val)
// No need for a scope, ptr_temp doesn't need drop
let block = unpack!(this.into(&ptr_temp, None, block, ptr));
// Maybe we should provide a scope here so that
// `move_val_init` wouldn't leak on panic even with an
// arbitrary `val` expression, but `schedule_drop`,
// borrowck and drop elaboration all prevent us from
// dropping `ptr_temp.deref()`.
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), None, block, val)
} else {
let args: Vec<_> = args
.into_iter()
Expand Down Expand Up @@ -265,11 +289,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
from_hir_call,
},
);
schedule_drop(this);
success.unit()
}
}
ExprKind::Use { source } => {
this.into(destination, block, source)
this.into(destination, scope, block, source)
}

// These cases don't actually need a destination
Expand All @@ -296,6 +321,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
this.cfg
.push_assign(block, source_info, destination, rvalue);
schedule_drop(this);
block.unit()
}
ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => {
Expand All @@ -315,6 +341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
this.cfg
.push_assign(block, source_info, destination, rvalue);
schedule_drop(this);
block.unit()
}

Expand Down Expand Up @@ -346,6 +373,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
this.cfg.push_assign(block, source_info, destination, rvalue);
schedule_drop(this);
block.unit()
}
};
Expand Down
25 changes: 16 additions & 9 deletions src/librustc_mir/build/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,31 @@

use crate::build::{BlockAnd, Builder};
use crate::hair::*;
use rustc::middle::region;
use rustc::mir::*;

pub(in crate::build) trait EvalInto<'tcx> {
fn eval_into(
self,
builder: &mut Builder<'_, 'tcx>,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
) -> BlockAnd<()>;
}

impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn into<E>(&mut self,
destination: &Place<'tcx>,
block: BasicBlock,
expr: E)
-> BlockAnd<()>
where E: EvalInto<'tcx>
pub fn into<E>(
&mut self,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
expr: E,
) -> BlockAnd<()>
where
E: EvalInto<'tcx>,
{
expr.eval_into(self, destination, block)
expr.eval_into(self, destination, scope, block)
}
}

Expand All @@ -34,10 +39,11 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
self,
builder: &mut Builder<'_, 'tcx>,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
) -> BlockAnd<()> {
let expr = builder.hir.mirror(self);
builder.into_expr(destination, block, expr)
builder.into_expr(destination, scope, block, expr)
}
}

Expand All @@ -46,8 +52,9 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
self,
builder: &mut Builder<'_, 'tcx>,
destination: &Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
) -> BlockAnd<()> {
builder.into_expr(destination, block, self)
builder.into_expr(destination, scope, block, self)
}
}
Loading