From 5070dea2366104fb0b5c344ce7f2a5cf8af176b0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Apr 2018 08:56:27 +1000 Subject: [PATCH] Lazily evaluate EvalErrorKind::*.into() calls. eval_context.rs calls `ok_or` in multiple places with an eagerly evaluated `EvalErrorKind::*.into()` argument, which calls EvalError::from(), which calls env::var("MIRI_BACKTRACE"), which allocates a String. This code is hot enough for this to have a measurable effect on some benchmarks. This patch changes the `ok_or` calls into `ok_or_else`, thus avoiding the evaluations when they're not needed. As a result, most of the rustc-perf benchmarks get a measurable speedup, particularly the shorter-running ones, where the improvement is as high as 6%. --- src/librustc_mir/interpret/eval_context.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 03785f9623b8..c75f112b9e82 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M self.param_env, def_id, substs, - ).ok_or(EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue + ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue } pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { @@ -279,9 +279,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M trace!("load mir {:?}", instance); match instance { ty::InstanceDef::Item(def_id) => { - self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| { + self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into() - }) + ) } _ => Ok(self.tcx.instance_mir(instance)), } @@ -691,7 +691,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M self.param_env, def_id, substs, - ).ok_or(EvalErrorKind::TypeckError.into()); + ).ok_or_else(|| EvalErrorKind::TypeckError.into()); let fn_ptr = self.memory.create_fn_alloc(instance?); let valty = ValTy { value: Value::ByVal(PrimVal::Ptr(fn_ptr)), @@ -1699,7 +1699,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M impl<'mir, 'tcx> Frame<'mir, 'tcx> { pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> { - self.locals[local].ok_or(EvalErrorKind::DeadLocal.into()) + self.locals[local].ok_or_else(|| EvalErrorKind::DeadLocal.into()) } fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> {