about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2020-02-19 07:59:21 -0500
committerWesley Wiser <wwiser@gmail.com>2020-02-19 18:28:37 -0500
commit9f3bc82fe40fd38fadfd24b7968548929abc9d4c (patch)
treeb3e01662a61cb256a36713f5fed3c15068a8afea
parentae5467826d1e677aff4662fc0481ace33761fc90 (diff)
downloadrust-9f3bc82fe40fd38fadfd24b7968548929abc9d4c.tar.gz
rust-9f3bc82fe40fd38fadfd24b7968548929abc9d4c.zip
Check `RUSTC_CTFE_BACKTRACE` much less by generating fewer errors
Before this change, `get_size_and_align()`  calls `get_fn_alloc()` *a
lot* in CTFE heavy code. This previously returned an `Error` which would
check if `RUSTC_CTFE_BACKTRACE` was set on construction. Doing this
turned out to be a performance hotspot as @nnethercote discovered in
#68792.

This is an alternate take on that PR which resolves the performance
issue by generating *many* fewer errors. Previously, `ctfe-stress-4`
would generate over 5,000,000 errors each of which would check for the
presence of the environment variable. With these changes, that number is
reduced to 30.
-rw-r--r--src/librustc_mir/interpret/memory.rs12
1 files changed, 6 insertions, 6 deletions
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 0bcdf9ae3c1..1df389d9c8b 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -560,7 +560,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
-        if let Ok(_) = self.get_fn_alloc(id) {
+        if let Some(_) = self.get_fn_alloc(id) {
             return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
                 throw_unsup!(DerefFunctionPointer)
@@ -602,14 +602,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         }
     }
 
-    fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
+    fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
         trace!("reading fn ptr: {}", id);
         if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
-            Ok(FnVal::Other(*extra))
+            Some(FnVal::Other(*extra))
         } else {
             match self.tcx.alloc_map.lock().get(id) {
-                Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
-                _ => throw_unsup!(ExecuteMemory),
+                Some(GlobalAlloc::Function(instance)) => Some(FnVal::Instance(instance)),
+                _ => None,
             }
         }
     }
@@ -622,7 +622,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         if ptr.offset.bytes() != 0 {
             throw_unsup!(InvalidFunctionPointer)
         }
-        self.get_fn_alloc(ptr.alloc_id)
+        self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {