-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Remove slow HashSet during miri stack frame creation #49274
Changes from 2 commits
9839e5f
9fa14e4
bf8e4f2
b18b776
4ea4dd2
f9019ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use std::collections::HashSet; | ||
use std::fmt::Write; | ||
|
||
use rustc::hir::def_id::DefId; | ||
use rustc::hir::def::Def; | ||
use rustc::hir::map::definitions::DefPathData; | ||
use rustc::middle::const_val::{ConstVal, ErrKind}; | ||
use rustc::mir; | ||
|
@@ -383,40 +383,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M | |
) -> EvalResult<'tcx> { | ||
::log_settings::settings().indentation += 1; | ||
|
||
/// Return the set of locals that have a storage annotation anywhere | ||
fn collect_storage_annotations<'mir, 'tcx>(mir: &'mir mir::Mir<'tcx>) -> HashSet<mir::Local> { | ||
use rustc::mir::StatementKind::*; | ||
|
||
let mut set = HashSet::new(); | ||
for block in mir.basic_blocks() { | ||
for stmt in block.statements.iter() { | ||
match stmt.kind { | ||
StorageLive(local) | | ||
StorageDead(local) => { | ||
set.insert(local); | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
set | ||
} | ||
|
||
// Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local | ||
// `Value` for that. | ||
let num_locals = mir.local_decls.len() - 1; | ||
|
||
let locals = { | ||
let annotated_locals = collect_storage_annotations(mir); | ||
let mut locals = vec![None; num_locals]; | ||
for i in 0..num_locals { | ||
let local = mir::Local::new(i + 1); | ||
if !annotated_locals.contains(&local) { | ||
locals[i] = Some(Value::ByVal(PrimVal::Undef)); | ||
let mut locals = vec![Some(Value::ByVal(PrimVal::Undef)); num_locals]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason we didn't use that is theat we don't actually use the return pointer local at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed, the waste of one space is massively outweighted by the many There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure? Now you have to allocate something on the heap even if it's never used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For truly trivial constants ( I added a fast path for trivial constants There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
match self.tcx.describe_def(instance.def_id()) { | ||
// statics and constants don't have `Storage*` statements, no need to look for them | ||
Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}, | ||
_ => { | ||
trace!("push_stack_frame: {:?}: num_bbs: {}", span, mir.basic_blocks().len()); | ||
for block in mir.basic_blocks() { | ||
for stmt in block.statements.iter() { | ||
use rustc::mir::StatementKind::{StorageDead, StorageLive}; | ||
match stmt.kind { | ||
StorageLive(local) | StorageDead(local) => if local.index() > 0 { | ||
locals[local.index() - 1] = None; | ||
}, | ||
_ => {} | ||
} | ||
} | ||
} | ||
} | ||
locals | ||
}; | ||
}, | ||
} | ||
|
||
self.stack.push(Frame { | ||
mir, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be a good idea to check for
Hash{Map,Set}
used by miri code: if it needs to be a hash map/set, it should beFxHash{Map,Set}
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, found a few in
interpret::memory