use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
use rustc::mir::mono::{InstantiationMode, MonoItem};
use rustc::mir::visit::Visitor as MirVisitor;
-use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
+use rustc::mir::{self, Local, Location};
use rustc::session::config::EntryFnType;
use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
use rustc::ty::print::obsolete::DefPathBasedNames;
-use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_index::bit_set::GrowableBitSet;
-
+use smallvec::SmallVec;
use std::iter;
#[derive(PartialEq)]
}
}
- fn record_accesses<I>(&mut self, source: MonoItem<'tcx>, new_targets: I)
- where
- I: Iterator<Item = (MonoItem<'tcx>, bool)> + ExactSizeIterator,
- {
- assert!(!self.index.contains_key(&source));
-
+ fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) {
let start_index = self.targets.len();
let new_items_count = new_targets.len();
let new_items_count_total = new_items_count + self.targets.len();
self.targets.reserve(new_items_count);
self.inlines.ensure(new_items_count_total);
- for (i, (target, inline)) in new_targets.enumerate() {
- self.targets.push(target);
- if inline {
+ for (i, (target, inline)) in new_targets.iter().enumerate() {
+ self.targets.push(*target);
+ if *inline {
self.inlines.insert(i + start_index);
}
}
let end_index = self.targets.len();
- self.index.insert(source, (start_index, end_index));
+ assert!(self.index.insert(source, (start_index, end_index)).is_none());
}
// Internally iterate over all items referenced by `source` which will be
mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
};
- let accesses =
- callees.into_iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)));
+ // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
+ // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
+ // instead to avoid creating this `SmallVec`.
+ let accesses: SmallVec<[_; 128]> = callees
+ .into_iter()
+ .map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)))
+ .collect();
- inlining_map.lock_mut().record_accesses(caller, accesses);
+ inlining_map.lock_mut().record_accesses(caller, &accesses);
}
fn check_recursion_limit<'tcx>(
let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
debug!(" => recursion depth={}", recursion_depth);
- let recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+ let adjusted_recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
// HACK: drop_in_place creates tight monomorphization loops. Give
// it more margin.
recursion_depth / 4
// Code that needs to instantiate the same function recursively
// more than the recursion limit is assumed to be causing an
// infinite expansion.
- if recursion_depth > *tcx.sess.recursion_limit.get() {
+ if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() {
let error = format!("reached the recursion limit while instantiating `{}`", instance);
if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
tcx.sess.span_fatal(tcx.hir().span(hir_id), &error);
fn visit_place_base(
&mut self,
- place_base: &mir::PlaceBase<'tcx>,
+ _place_local: &Local,
_context: mir::visit::PlaceContext,
- location: Location,
+ _location: Location,
) {
- match place_base {
- PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
- debug!("visiting static {:?} @ {:?}", def_id, location);
-
- let tcx = self.tcx;
- let instance = Instance::mono(tcx, *def_id);
- if should_monomorphize_locally(tcx, &instance) {
- self.output.push(MonoItem::Static(*def_id));
- }
- }
- PlaceBase::Static(box Static {
- kind: StaticKind::Promoted(promoted, substs),
- def_id,
- ..
- }) => {
- let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs));
- match self.tcx.const_eval_promoted(instance, *promoted) {
- Ok(val) => collect_const(self.tcx, val, substs, self.output),
- Err(ErrorHandled::Reported) => {}
- Err(ErrorHandled::TooGeneric) => {
- let span = self.tcx.promoted_mir(*def_id)[*promoted].span;
- span_bug!(span, "collection encountered polymorphic constant")
- }
- }
- }
- PlaceBase::Local(_) => {
- // Locals have no relevance for collector.
- }
- }
}
}
// need a mono item.
fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
let def_id = match instance.def {
- ty::InstanceDef::Item(def_id) => def_id,
+ ty::InstanceDef::Item(def_id) | ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+
ty::InstanceDef::VtableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::ClosureOnceShim { .. }
};
if tcx.is_foreign_item(def_id) {
- // We can always link to foreign items.
+ // Foreign items are always linked against, there's no way of
+ // instantiating them.
return false;
}
if def_id.is_local() {
- // Local items cannot be referred to locally without monomorphizing them locally.
+ // Local items cannot be referred to locally without
+ // monomorphizing them locally.
return true;
}
if !tcx.is_mir_available(def_id) {
bug!("cannot create local mono-item for {:?}", def_id)
}
+
return true;
fn is_available_upstream_generic<'tcx>(
// Nothing to do, just keep recursing.
}
- hir::ItemKind::Impl(..) => {
+ hir::ItemKind::Impl { .. } => {
if self.mode == MonoItemCollectionMode::Eager {
create_mono_items_for_default_impls(self.tcx, item, self.output);
}
output: &mut Vec<MonoItem<'tcx>>,
) {
match item.kind {
- hir::ItemKind::Impl(_, _, _, ref generics, .., ref impl_item_refs) => {
+ hir::ItemKind::Impl { ref generics, ref items, .. } => {
for param in generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
let param_env = ty::ParamEnv::reveal_all();
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
let overridden_methods: FxHashSet<_> =
- impl_item_refs.iter().map(|iiref| iiref.ident.modern()).collect();
+ items.iter().map(|iiref| iiref.ident.modern()).collect();
for method in tcx.provided_trait_methods(trait_ref.def_id) {
if overridden_methods.contains(&method.ident.modern()) {
continue;
collect_miri(tcx, id, output);
}
}
- ty::ConstKind::Unevaluated(def_id, substs) => {
- match tcx.const_eval_resolve(param_env, def_id, substs, None) {
+ ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
+ match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
Ok(val) => collect_const(tcx, val, param_substs, output),
Err(ErrorHandled::Reported) => {}
Err(ErrorHandled::TooGeneric) => {