Skip to content

Commit 46690f6

Browse files
added precompilation for lowering
1 parent 78cdd8a commit 46690f6

File tree

19 files changed

+3010
-32
lines changed

19 files changed

+3010
-32
lines changed

Cargo.lock

Lines changed: 16 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ schemars = { version = "0.8.21", features = ["preserve_order"] }
126126
semver = { version = "1.0.25", features = ["serde"] }
127127
serde = { version = "1.0.217", default-features = false, features = ["derive"] }
128128
serde_json = "1.0.138"
129+
bincode = "1.3.3"
129130
sha2 = "0.10.8"
130131
sha3 = "0.10.8"
131132
smol_str = { version = "0.3.2", features = ["serde"] }

crates/bin/get-lowering/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ cairo-lang-lowering = { path = "../../cairo-lang-lowering", version = "~2.9.2" }
1919
cairo-lang-starknet = { path = "../../cairo-lang-starknet", version = "~2.9.2" }
2020
cairo-lang-semantic = { path = "../../cairo-lang-semantic", version = "~2.9.2" }
2121
cairo-lang-utils = { path = "../../cairo-lang-utils", version = "~2.9.2" }
22+
bincode.workspace = true

crates/cairo-lang-compiler/src/project.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fn update_crate_root(
8585
let (crate_id, crate_settings) = get_crate_id_and_settings(db, crate_identifier, config);
8686
db.set_crate_config(
8787
crate_id,
88-
Some(CrateConfiguration { root, settings: crate_settings.clone() }),
88+
Some(CrateConfiguration { root, settings: crate_settings.clone(), precompute_file: None }),
8989
);
9090
}
9191

crates/cairo-lang-defs/src/diagnostic_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::db::DefsGroup;
1111

1212
/// A stable location of a real, concrete syntax.
1313
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
14-
pub struct StableLocation(SyntaxStablePtrId);
14+
pub struct StableLocation(pub SyntaxStablePtrId);
1515
impl StableLocation {
1616
pub fn new(stable_ptr: SyntaxStablePtrId) -> Self {
1717
Self(stable_ptr)

crates/cairo-lang-filesystem/src/db.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use smol_str::{SmolStr, ToSmolStr};
1313
use crate::cfg::CfgSet;
1414
use crate::flag::Flag;
1515
use crate::ids::{
16-
CodeMapping, CodeOrigin, CrateId, CrateLongId, Directory, FileId, FileLongId, FlagId,
17-
FlagLongId, VirtualFile,
16+
BlobId, BlobLongId, CodeMapping, CodeOrigin, CrateId, CrateLongId, Directory, FileId,
17+
FileLongId, FlagId, FlagLongId, VirtualFile,
1818
};
1919
use crate::span::{FileSummary, TextOffset, TextSpan, TextWidth};
2020

@@ -50,11 +50,12 @@ pub struct CrateConfiguration {
5050
/// The root directory of the crate.
5151
pub root: Directory,
5252
pub settings: CrateSettings,
53+
pub precompute_file: Option<BlobId>,
5354
}
5455
impl CrateConfiguration {
5556
/// Returns a new configuration.
5657
pub fn default_for_root(root: Directory) -> Self {
57-
Self { root, settings: CrateSettings::default() }
58+
Self { root, settings: CrateSettings::default(), precompute_file: None }
5859
}
5960
}
6061

@@ -182,6 +183,8 @@ pub trait FilesGroup: ExternalFiles {
182183
#[salsa::interned]
183184
fn intern_file(&self, file: FileLongId) -> FileId;
184185
#[salsa::interned]
186+
fn intern_blob(&self, blob: BlobLongId) -> BlobId;
187+
#[salsa::interned]
185188
fn intern_flag(&self, flag: FlagLongId) -> FlagId;
186189

187190
/// Main input of the project. Lists all the crates configurations.
@@ -215,6 +218,8 @@ pub trait FilesGroup: ExternalFiles {
215218
fn file_content(&self, file_id: FileId) -> Option<Arc<str>>;
216219
fn file_summary(&self, file_id: FileId) -> Option<Arc<FileSummary>>;
217220

221+
/// Query for the blob content.
222+
fn blob_content(&self, blob_id: BlobId) -> Option<Arc<[u8]>>;
218223
/// Query to get a compilation flag by its ID.
219224
fn get_flag(&self, id: FlagId) -> Option<Arc<Flag>>;
220225
}
@@ -244,6 +249,7 @@ pub fn init_dev_corelib(db: &mut (dyn FilesGroup + 'static), core_lib_dir: PathB
244249
coupons: true,
245250
},
246251
},
252+
precompute_file: None,
247253
}),
248254
);
249255
}
@@ -302,13 +308,17 @@ fn crates(db: &dyn FilesGroup) -> Vec<CrateId> {
302308
fn crate_config(db: &dyn FilesGroup, crt: CrateId) -> Option<CrateConfiguration> {
303309
match crt.lookup_intern(db) {
304310
CrateLongId::Real { .. } => db.crate_configs().get(&crt).cloned(),
305-
CrateLongId::Virtual { name: _, file_id, settings } => Some(CrateConfiguration {
306-
root: Directory::Virtual {
307-
files: BTreeMap::from([("lib.cairo".into(), file_id)]),
308-
dirs: Default::default(),
309-
},
310-
settings: toml::from_str(&settings).expect("Failed to parse virtual crate settings."),
311-
}),
311+
CrateLongId::Virtual { name: _, file_id, settings, precompute_file } => {
312+
Some(CrateConfiguration {
313+
root: Directory::Virtual {
314+
files: BTreeMap::from([("lib.cairo".into(), file_id)]),
315+
dirs: Default::default(),
316+
},
317+
settings: toml::from_str(&settings)
318+
.expect("Failed to parse virtual crate settings."),
319+
precompute_file,
320+
})
321+
}
312322
}
313323
}
314324

@@ -348,6 +358,22 @@ fn get_flag(db: &dyn FilesGroup, id: FlagId) -> Option<Arc<Flag>> {
348358
db.flags().get(&id).cloned()
349359
}
350360

361+
fn blob_content(db: &dyn FilesGroup, blob: BlobId) -> Option<Arc<[u8]>> {
362+
match blob.lookup_intern(db) {
363+
BlobLongId::OnDisk(path) => {
364+
// This does not result in performance cost due to OS caching and the fact that salsa
365+
// will re-execute only this single query if the file content did not change.
366+
db.salsa_runtime().report_synthetic_read(Durability::LOW);
367+
368+
match fs::read(path) {
369+
Ok(content) => Some(content.into()),
370+
Err(_) => None,
371+
}
372+
}
373+
BlobLongId::Virtual(content) => Some(content),
374+
}
375+
}
376+
351377
/// Returns the location of the originating user code.
352378
pub fn get_originating_location(
353379
db: &dyn FilesGroup,

crates/cairo-lang-filesystem/src/ids.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::sync::Arc;
44

55
use cairo_lang_utils::{Intern, LookupIntern, define_short_id};
66
use path_clean::PathClean;
7+
use serde::{Deserialize, Serialize};
78
use smol_str::SmolStr;
89

910
use crate::db::{CORELIB_CRATE_NAME, FilesGroup};
@@ -17,7 +18,7 @@ pub enum CrateLongId {
1718
/// A crate that appears in crate_roots(), and on the filesystem.
1819
Real { name: SmolStr, discriminator: Option<SmolStr> },
1920
/// A virtual crate, not a part of the crate_roots(). Used mainly for tests.
20-
Virtual { name: SmolStr, file_id: FileId, settings: String },
21+
Virtual { name: SmolStr, file_id: FileId, settings: String, precompute_file: Option<BlobId> },
2122
}
2223
impl CrateLongId {
2324
pub fn name(&self) -> SmolStr {
@@ -78,14 +79,14 @@ pub enum FileLongId {
7879
External(salsa::InternId),
7980
}
8081
/// Whether the file holds syntax for a module or for an expression.
81-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
82+
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
8283
pub enum FileKind {
8384
Module,
8485
Expr,
8586
}
8687

8788
/// A mapping for a code rewrite.
88-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
89+
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
8990
pub struct CodeMapping {
9091
pub span: TextSpan,
9192
pub origin: CodeOrigin,
@@ -108,7 +109,7 @@ impl CodeMapping {
108109
}
109110

110111
/// The origin of a code mapping.
111-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
112+
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
112113
pub enum CodeOrigin {
113114
/// The origin is a copied node staring at the given offset.
114115
Start(TextOffset),
@@ -214,3 +215,17 @@ impl Directory {
214215
}
215216
}
216217
}
218+
219+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
220+
pub enum BlobLongId {
221+
OnDisk(PathBuf),
222+
Virtual(Arc<[u8]>),
223+
}
224+
225+
define_short_id!(BlobId, BlobLongId, FilesGroup, lookup_intern_blob, intern_blob);
226+
227+
impl BlobId {
228+
pub fn new(db: &dyn FilesGroup, path: PathBuf) -> BlobId {
229+
BlobLongId::OnDisk(path.clean()).intern(db)
230+
}
231+
}

crates/cairo-lang-lowering/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ num-bigint = { workspace = true, default-features = true }
2323
num-integer = { workspace = true, default-features = true }
2424
num-traits = { workspace = true, default-features = true }
2525
salsa.workspace = true
26+
bincode.workspace = true
27+
serde = { workspace = true, default-features = true }
28+
smol_str.workspace = true
2629

2730
[dev-dependencies]
2831
cairo-lang-plugins = { path = "../cairo-lang-plugins" }

crates/cairo-lang-lowering/src/db.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::sync::Arc;
22

3+
use cairo_lang_debug::DebugWithDb;
34
use cairo_lang_defs as defs;
45
use cairo_lang_defs::ids::{LanguageElementId, ModuleId, ModuleItemId, NamedLanguageElementLongId};
56
use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe};
67
use cairo_lang_filesystem::ids::FileId;
78
use cairo_lang_semantic::db::SemanticGroup;
89
use cairo_lang_semantic::items::enm::SemanticEnumEx;
910
use cairo_lang_semantic::{self as semantic, ConcreteTypeId, TypeId, TypeLongId, corelib};
11+
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
1012
use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
1113
use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
1214
use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
@@ -28,6 +30,10 @@ use crate::optimizations::config::OptimizationConfig;
2830
use crate::optimizations::scrub_units::scrub_units;
2931
use crate::optimizations::strategy::{OptimizationStrategy, OptimizationStrategyId};
3032
use crate::panic::lower_panics;
33+
use crate::precompute::{
34+
DeSerializationContext, DefsFunctionWithBodyIdSerializable, MultiLoweringSerializable,
35+
SemanticSerializationLookups, SerializationLookups,
36+
};
3137
use crate::utils::InliningStrategy;
3238
use crate::{
3339
BlockId, DependencyType, FlatBlockEnd, FlatLowered, Location, MatchInfo, Statement, ids,
@@ -62,6 +68,11 @@ pub trait LoweringGroup: SemanticGroup + Upcast<dyn SemanticGroup> {
6268
function_id: defs::ids::FunctionWithBodyId,
6369
) -> Maybe<Arc<MultiLowering>>;
6470

71+
fn load_serielized_multi_lowerings(
72+
&self,
73+
file_id: cairo_lang_filesystem::ids::CrateId,
74+
) -> Option<Arc<OrderedHashMap<defs::ids::FunctionWithBodyId, MultiLowering>>>;
75+
6576
/// Computes the lowered representation of a function with a body before borrow checking.
6677
fn priv_function_with_body_lowering(
6778
&self,
@@ -382,9 +393,46 @@ fn priv_function_with_body_multi_lowering(
382393
db: &dyn LoweringGroup,
383394
function_id: defs::ids::FunctionWithBodyId,
384395
) -> Maybe<Arc<MultiLowering>> {
396+
let crate_id = function_id.module_file_id(db.upcast()).0.owning_crate(db.upcast());
397+
if let Some(map) = db.load_serielized_multi_lowerings(crate_id) {
398+
if let Some(multi_lowering) = map.get(&function_id) {
399+
return Ok(Arc::new(multi_lowering.clone()));
400+
} else {
401+
panic!("function not found in precomputed lowering {:?}", function_id.debug(db));
402+
}
403+
};
404+
385405
let multi_lowering = lower_semantic_function(db.upcast(), function_id)?;
386406
Ok(Arc::new(multi_lowering))
387407
}
408+
fn load_serielized_multi_lowerings(
409+
db: &dyn LoweringGroup,
410+
self_crate_id: cairo_lang_filesystem::ids::CrateId,
411+
) -> Option<Arc<OrderedHashMap<defs::ids::FunctionWithBodyId, MultiLowering>>> {
412+
let blob_id = db.crate_config(self_crate_id)?.precompute_file?;
413+
let Some(content) = db.blob_content(blob_id) else {
414+
return Default::default();
415+
};
416+
let (lookups, semantic_lookups, lowerings): (
417+
SerializationLookups,
418+
SemanticSerializationLookups,
419+
Vec<(DefsFunctionWithBodyIdSerializable, MultiLoweringSerializable)>,
420+
) = bincode::deserialize(&content).unwrap_or_default();
421+
let mut ctx = DeSerializationContext::new(db, lookups, semantic_lookups, self_crate_id);
422+
423+
Some(
424+
lowerings
425+
.into_iter()
426+
.map(|(function_id, lowering)| {
427+
let function_id = function_id.embed(&mut ctx.semantic_ctx);
428+
429+
let lowering = lowering.embed(&mut ctx);
430+
(function_id, lowering)
431+
})
432+
.collect::<OrderedHashMap<_, _>>()
433+
.into(),
434+
)
435+
}
388436

389437
// * Borrow checking.
390438
fn priv_function_with_body_lowering(

crates/cairo-lang-lowering/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub mod lower;
1616
pub mod objects;
1717
pub mod optimizations;
1818
pub mod panic;
19+
pub mod precompute;
1920
pub mod reorganize_blocks;
2021
pub mod scc;
2122
pub mod utils;

crates/cairo-lang-lowering/src/objects.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ pub struct StatementStructDestructure {
381381
#[derive(Clone, Debug, PartialEq, Eq)]
382382
pub struct StatementSnapshot {
383383
pub input: VarUsage,
384-
outputs: [VariableId; 2],
384+
pub outputs: [VariableId; 2],
385385
}
386386
impl StatementSnapshot {
387387
pub fn new(input: VarUsage, output_original: VariableId, output_snapshot: VariableId) -> Self {

0 commit comments

Comments
 (0)