about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/base.rs1
-rw-r--r--src/common.rs29
-rw-r--r--src/debuginfo/line_info.rs99
-rw-r--r--src/debuginfo/mod.rs7
4 files changed, 58 insertions, 78 deletions
diff --git a/src/base.rs b/src/base.rs
index 4e60f820594..9c66fa6d9cc 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -95,7 +95,6 @@ pub(crate) fn codegen_fn<'tcx>(
         caller_location: None, // set by `codegen_fn_prelude`
 
         clif_comments,
-        last_source_file: None,
         next_ssa_var: 0,
     };
 
diff --git a/src/common.rs b/src/common.rs
index a7c3d68ff8c..b038c7194cd 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -1,12 +1,9 @@
 use cranelift_codegen::isa::TargetFrontendConfig;
-use gimli::write::FileId;
-use rustc_data_structures::sync::Lrc;
 use rustc_index::IndexVec;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
 };
 use rustc_span::source_map::Spanned;
-use rustc_span::SourceFile;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
 use rustc_target::spec::{HasTargetSpec, Target};
@@ -305,11 +302,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
 
     pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
 
-    /// Last accessed source file and it's debuginfo file id.
-    ///
-    /// For optimization purposes only
-    pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,
-
     /// This should only be accessed by `CPlace::new_var`.
     pub(crate) next_ssa_var: u32,
 }
@@ -419,25 +411,8 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
 
     pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
         if let Some(debug_context) = &mut self.cx.debug_context {
-            let (file, line, column) =
-                DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);
-
-            // add_source_file is very slow.
-            // Optimize for the common case of the current file not being changed.
-            let mut cached_file_id = None;
-            if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
-                // If the allocations are not equal, the files may still be equal, but that
-                // doesn't matter, as this is just an optimization.
-                if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
-                    cached_file_id = Some(last_file_id);
-                }
-            }
-
-            let file_id = if let Some(file_id) = cached_file_id {
-                file_id
-            } else {
-                debug_context.add_source_file(&file)
-            };
+            let (file_id, line, column) =
+                debug_context.get_span_loc(self.tcx, self.mir.span, source_info.span);
 
             let source_loc =
                 self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);
diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs
index d1b21d0a0b6..916abf31869 100644
--- a/src/debuginfo/line_info.rs
+++ b/src/debuginfo/line_info.rs
@@ -8,7 +8,6 @@ use cranelift_codegen::MachSrcLoc;
 use gimli::write::{
     Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
 };
-use rustc_data_structures::sync::Lrc;
 use rustc_span::{
     FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
 };
@@ -60,10 +59,11 @@ fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
 
 impl DebugContext {
     pub(crate) fn get_span_loc(
+        &mut self,
         tcx: TyCtxt<'_>,
         function_span: Span,
         span: Span,
-    ) -> (Lrc<SourceFile>, u64, u64) {
+    ) -> (FileId, u64, u64) {
         // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
         // In order to have a good line stepping behavior in debugger, we overwrite debug
         // locations of macro expansions with that of the outermost expansion site (when the macro is
@@ -71,61 +71,66 @@ impl DebugContext {
         let span = tcx.collapsed_debuginfo(span, function_span);
         match tcx.sess.source_map().lookup_line(span.lo()) {
             Ok(SourceFileAndLine { sf: file, line }) => {
+                let file_id = self.add_source_file(&file);
                 let line_pos = file.lines()[line];
                 let col = file.relative_position(span.lo()) - line_pos;
 
-                (file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
+                (file_id, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
             }
-            Err(file) => (file, 0, 0),
+            Err(file) => (self.add_source_file(&file), 0, 0),
         }
     }
 
     pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
-        let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
-        let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
-
-        match &source_file.name {
-            FileName::Real(path) => {
-                let (dir_path, file_name) =
-                    split_path_dir_and_file(if self.should_remap_filepaths {
-                        path.remapped_path_if_available()
-                    } else {
-                        path.local_path_if_available()
-                    });
-                let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
-                let file_name = osstr_as_utf8_bytes(file_name);
-
-                let dir_id = if !dir_name.is_empty() {
-                    let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
-                    line_program.add_directory(dir_name)
-                } else {
-                    line_program.default_directory()
-                };
-                let file_name = LineString::new(file_name, line_program.encoding(), line_strings);
-
-                let info = make_file_info(source_file.src_hash);
-
-                line_program.file_has_md5 &= info.is_some();
-                line_program.add_file(file_name, dir_id, info)
-            }
-            // FIXME give more appropriate file names
-            filename => {
-                let dir_id = line_program.default_directory();
-                let dummy_file_name = LineString::new(
-                    filename
-                        .display(if self.should_remap_filepaths {
-                            FileNameDisplayPreference::Remapped
+        let cache_key = (source_file.stable_id, source_file.src_hash);
+        *self.created_files.entry(cache_key).or_insert_with(|| {
+            let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
+            let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
+
+            match &source_file.name {
+                FileName::Real(path) => {
+                    let (dir_path, file_name) =
+                        split_path_dir_and_file(if self.should_remap_filepaths {
+                            path.remapped_path_if_available()
                         } else {
-                            FileNameDisplayPreference::Local
-                        })
-                        .to_string()
-                        .into_bytes(),
-                    line_program.encoding(),
-                    line_strings,
-                );
-                line_program.add_file(dummy_file_name, dir_id, None)
+                            path.local_path_if_available()
+                        });
+                    let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
+                    let file_name = osstr_as_utf8_bytes(file_name);
+
+                    let dir_id = if !dir_name.is_empty() {
+                        let dir_name =
+                            LineString::new(dir_name, line_program.encoding(), line_strings);
+                        line_program.add_directory(dir_name)
+                    } else {
+                        line_program.default_directory()
+                    };
+                    let file_name =
+                        LineString::new(file_name, line_program.encoding(), line_strings);
+
+                    let info = make_file_info(source_file.src_hash);
+
+                    line_program.file_has_md5 &= info.is_some();
+                    line_program.add_file(file_name, dir_id, info)
+                }
+                filename => {
+                    let dir_id = line_program.default_directory();
+                    let dummy_file_name = LineString::new(
+                        filename
+                            .display(if self.should_remap_filepaths {
+                                FileNameDisplayPreference::Remapped
+                            } else {
+                                FileNameDisplayPreference::Local
+                            })
+                            .to_string()
+                            .into_bytes(),
+                        line_program.encoding(),
+                        line_strings,
+                    );
+                    line_program.add_file(dummy_file_name, dir_id, None)
+                }
             }
-        }
+        })
     }
 }
 
diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs
index b541cf0512e..172e72c0e26 100644
--- a/src/debuginfo/mod.rs
+++ b/src/debuginfo/mod.rs
@@ -16,6 +16,7 @@ use indexmap::IndexSet;
 use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_hir::def_id::DefIdMap;
 use rustc_session::Session;
+use rustc_span::{SourceFileHash, StableSourceFileId};
 
 pub(crate) use self::emit::{DebugReloc, DebugRelocName};
 pub(crate) use self::unwind::UnwindContext;
@@ -30,6 +31,7 @@ pub(crate) struct DebugContext {
 
     dwarf: DwarfUnit,
     unit_range_list: RangeList,
+    created_files: FxHashMap<(StableSourceFileId, SourceFileHash), FileId>,
     stack_pointer_register: Register,
     namespace_map: DefIdMap<UnitEntryId>,
 
@@ -130,6 +132,7 @@ impl DebugContext {
             endian,
             dwarf,
             unit_range_list: RangeList(Vec::new()),
+            created_files: FxHashMap::default(),
             stack_pointer_register,
             namespace_map: DefIdMap::default(),
             should_remap_filepaths,
@@ -169,9 +172,7 @@ impl DebugContext {
         linkage_name: &str,
         function_span: Span,
     ) -> FunctionDebugContext {
-        let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
-
-        let file_id = self.add_source_file(&file);
+        let (file_id, line, column) = self.get_span_loc(tcx, function_span, function_span);
 
         // FIXME: add to appropriate scope instead of root
         let scope = self.item_namespace(tcx, tcx.parent(instance.def_id()));