Skip to content
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

chore: Add strategy for caching the parsing layer #3849

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/fm/src/file_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ impl FileMap {
pub fn get_file_id(&self, file_name: &PathString) -> Option<FileId> {
self.name_to_id.get(file_name).cloned()
}

pub fn all_file_ids(&self) -> impl Iterator<Item = &FileId> {
self.name_to_id.values()
}
}
impl Default for FileMap {
fn default() -> Self {
Expand Down
2 changes: 2 additions & 0 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId {
context.file_manager.add_file_with_source_canonical_path(Path::new(&path), source);
}

context.repopulate_cache();

let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr");
let std_file_id = context
.file_manager
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::{
},
errors::{DefCollectorErrorKind, DuplicateType},
};
use crate::hir::def_map::{parse_file, LocalModuleId, ModuleData, ModuleId};
use crate::hir::def_map::{LocalModuleId, ModuleData, ModuleId};
use crate::hir::resolution::import::ImportDirective;
use crate::hir::Context;

Expand Down Expand Up @@ -555,7 +555,7 @@ impl<'a> ModCollector<'a> {
context.visited_files.insert(child_file_id, location);

// Parse the AST for the module we just found and then recursively look for it's defs
let (ast, parsing_errors) = parse_file(&context.file_manager, child_file_id);
let (ast, parsing_errors) = context.parsed_file_results(child_file_id);
let ast = ast.into_sorted();

errors.extend(
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/hir/def_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl CrateDefMap {

// First parse the root file.
let root_file_id = context.crate_graph[crate_id].root_file_id;
let (ast, parsing_errors) = parse_file(&context.file_manager, root_file_id);
let (ast, parsing_errors) = context.parsed_file_results(root_file_id);
let mut ast = ast.into_sorted();

for macro_processor in &macro_processors {
Expand Down
54 changes: 51 additions & 3 deletions compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ pub mod type_check;
use crate::graph::{CrateGraph, CrateId};
use crate::hir_def::function::FuncMeta;
use crate::node_interner::{FuncId, NodeInterner, StructId};
use crate::parser::ParserError;
use crate::ParsedModule;
use def_map::{Contract, CrateDefMap};
use fm::FileManager;
use noirc_errors::Location;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};

use self::def_map::TestFunction;
use self::def_map::{parse_file, TestFunction};

/// Helper object which groups together several useful context objects used
/// during name resolution. Once name resolution is finished, only the
Expand All @@ -26,6 +28,8 @@ pub struct Context {
/// A map of each file that already has been visited from a prior `mod foo;` declaration.
/// This is used to issue an error if a second `mod foo;` is declared to the same file.
pub visited_files: BTreeMap<fm::FileId, Location>,

file_to_ast_cache: HashMap<fm::FileId, (ParsedModule, Vec<ParserError>)>,
}

#[derive(Debug, Copy, Clone)]
Expand All @@ -37,15 +41,59 @@ pub enum FunctionNameMatch<'a> {

impl Context {
pub fn new(file_manager: FileManager, crate_graph: CrateGraph) -> Context {
Context {
let mut context = Context {
def_interner: NodeInterner::default(),
def_maps: BTreeMap::new(),
visited_files: BTreeMap::new(),
crate_graph,
file_manager,
file_to_ast_cache: HashMap::default(),
};

context.populate_cache_with_file_manager();

context
}

// TODO: This method should live at a higher level
fn populate_cache_with_file_manager(&mut self) {
for file_id in self.file_manager.as_file_map().all_file_ids() {
let file_path = self.file_manager.path(*file_id);
let file_extension =
file_path.extension().expect("expected all file paths to have an extension");
// TODO: Another reason we may not want to have this method here
// TODO: is the fact that we want to not have the compiler worry
// TODO about the nr file extension
if file_extension != "nr" {
continue;
}
self.file_to_ast_cache.insert(*file_id, parse_file(&self.file_manager, *file_id));
}
}

// TODO: Do not merge with this method!
pub fn repopulate_cache(&mut self) {
for file_id in self.file_manager.as_file_map().all_file_ids() {
let file_path = self.file_manager.path(*file_id);
let file_extension =
file_path.extension().expect("expected all file paths to have an extension");
// TODO: Another reason we may not want to have this method here
// TODO: is the fact that we want to not have the compiler worry
// TODO about the nr file extension
if file_extension != "nr" {
continue;
}
self.file_to_ast_cache.insert(*file_id, parse_file(&self.file_manager, *file_id));
}
}
Comment on lines +74 to +88
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the hack, I added to repopulate the cache once I know we have added the stdlib to the file manager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied the above method and made this one public


pub fn parsed_file_results(&self, file_id: fm::FileId) -> (ParsedModule, Vec<ParserError>) {
// TODO: we could make it parse the file if it is not in the cache
//
// TODO: Check if we can return a reference here instead of cloning.
self.file_to_ast_cache.get(&file_id).expect("noir file not found in cache").clone()
}

/// Returns the CrateDefMap for a given CrateId.
/// It is perfectly valid for the compiler to look
/// up a CrateDefMap and it is not available.
Expand Down