From 2a591312e55201f0eb33f887d0d8fdc62f90361c Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Thu, 1 Sep 2022 12:28:59 +0100 Subject: [PATCH] Add a monomorphization cache to the declaration engine. This introduces a cache to the declaration engine that keeps track of functions/structs that have been instantiated from a specific set of type parameters. This was originally prototyped in https://github.com/tritao/declaration-engine-and-collection-context-demo/commit/c3aa5e718211ee1a88d7ebc51798280e8321e387, where these APIs where wired to the function application and struct expressions instantiation code. However given the declaration engine is not hooked up yet here, this PR is just adding the APIs, and more proper testing will be added as we wire things up. Closes https://github.com/FuelLabs/sway/issues/2636. --- .../declaration_engine/declaration_engine.rs | 238 +++++++++++++----- sway-core/src/type_system/mod.rs | 2 +- sway-core/src/type_system/type_argument.rs | 6 + sway-core/src/type_system/type_parameter.rs | 6 + 4 files changed, 189 insertions(+), 63 deletions(-) diff --git a/sway-core/src/declaration_engine/declaration_engine.rs b/sway-core/src/declaration_engine/declaration_engine.rs index 08c44d36587..d2769c2847b 100644 --- a/sway-core/src/declaration_engine/declaration_engine.rs +++ b/sway-core/src/declaration_engine/declaration_engine.rs @@ -4,11 +4,15 @@ use sway_types::{Span, Spanned}; use crate::{ concurrent_slab::ConcurrentSlab, + error::{err, ok}, + namespace::{Path, Root}, semantic_analysis::{ TypedImplTrait, TypedStorageDeclaration, TypedStructDeclaration, TypedTraitDeclaration, TypedTraitFn, }, - CompileError, TypedFunctionDeclaration, + type_system::TypeArgument, + type_system::{type_engine::monomorphize, EnforceTypeArguments}, + CompileError, CompileResult, TypedFunctionDeclaration, }; use super::{declaration_id::DeclarationId, declaration_wrapper::DeclarationWrapper}; @@ -24,6 +28,7 @@ pub(crate) struct DeclarationEngine { // *declaration_id -> vec of monomorphized copies // where the declaration_id is the original declaration monomorphized_copies: RwLock>>, + is_monomorph_cache_enabled: bool, } impl DeclarationEngine { @@ -39,14 +44,10 @@ impl DeclarationEngine { fn de_add_monomorphized_copy(&self, original_id: DeclarationId, new_id: DeclarationId) { let mut monomorphized_copies = self.monomorphized_copies.write().unwrap(); - match monomorphized_copies.get_mut(&*original_id) { - Some(prev) => { - prev.push(new_id); - } - None => { - monomorphized_copies.insert(*original_id, vec![new_id]); - } - } + monomorphized_copies + .entry(*original_id) + .and_modify(|f| f.push(new_id.clone())) + .or_insert_with(|| vec![new_id.clone()]); } fn de_get_monomorphized_copies(&self, original_id: DeclarationId) -> Vec { @@ -76,17 +77,83 @@ impl DeclarationEngine { self.slab.get(*index).expect_function(span) } - fn de_add_monomorphized_function_copy( + pub(crate) fn de_get_monomorphized_function( &self, original_id: DeclarationId, - new_copy: TypedFunctionDeclaration, - ) { - let span = new_copy.span(); - let new_id = DeclarationId::new( - self.slab.insert(DeclarationWrapper::Function(new_copy)), - span, + type_arguments: &Vec, + access_span: &Span, + ) -> Result { + for copy in self + .de_get_monomorphized_copies(original_id) + .iter() + .cloned() + { + let monomorphized_fn_decl = copy.expect_function(access_span)?; + if &monomorphized_fn_decl.type_parameters == type_arguments { + return Ok(monomorphized_fn_decl); + } + } + Err(CompileError::Internal( + "could not find monomorphized function", + access_span.clone(), + )) + } + + pub(crate) fn de_get_or_create_monomorphized_function( + &mut self, + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, + ) -> CompileResult { + let mut warnings = Vec::new(); + let mut errors = Vec::new(); + + if self.is_monomorph_cache_enabled { + let cached_fn_decl = check!( + CompileResult::from(self.de_get_monomorphized_function( + decl_id, + type_arguments, + call_site_span + )), + return err(warnings, errors), + warnings, + errors + ); + return ok(cached_fn_decl, warnings, errors); + } + + // monomorphize the function declaration into a new copy + let mut typed_function_declaration = check!( + CompileResult::from(self.de_get_function(decl_id.clone(), call_site_span)), + return err(warnings, errors), + warnings, + errors + ); + + check!( + monomorphize( + &mut typed_function_declaration, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ), + return err(warnings, errors), + warnings, + errors ); - self.de_add_monomorphized_copy(original_id, new_id) + + // add the new copy to the declaration engine + let new_id = self.slab.insert(DeclarationWrapper::Function( + typed_function_declaration.clone(), + )); + self.de_add_monomorphized_copy(decl_id, DeclarationId::new(new_id, call_site_span.clone())); + + ok(typed_function_declaration, warnings, errors) } fn de_get_monomorphized_function_copies( @@ -129,7 +196,7 @@ impl DeclarationEngine { self.slab.get(*index).expect_trait_fn(span) } - fn insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { + fn de_insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { let span = trait_impl.span.clone(); DeclarationId::new( self.slab.insert(DeclarationWrapper::TraitImpl(trait_impl)), @@ -158,26 +225,83 @@ impl DeclarationEngine { self.slab.get(*index).expect_struct(span) } - fn de_add_monomorphized_struct_copy( + pub(crate) fn de_get_monomorphized_struct( &self, original_id: DeclarationId, - new_copy: TypedStructDeclaration, - ) { - let span = new_copy.span(); - let new_id = - DeclarationId::new(self.slab.insert(DeclarationWrapper::Struct(new_copy)), span); - self.de_add_monomorphized_copy(original_id, new_id) + type_arguments: &Vec, + span: &Span, + ) -> Result { + for copy in self + .de_get_monomorphized_copies(original_id) + .iter() + .cloned() + { + let monomorphized_struct_decl = copy.expect_struct(span)?; + if &monomorphized_struct_decl.type_parameters == type_arguments { + return Ok(monomorphized_struct_decl); + } + } + Err(CompileError::Internal( + "could not find monomorphized struct", + span.clone(), + )) } - fn de_get_monomorphized_struct_copies( + pub(crate) fn de_get_or_create_monomorphized_struct( &self, - original_id: DeclarationId, - span: &Span, - ) -> Result, CompileError> { - self.de_get_monomorphized_copies(original_id) - .into_iter() - .map(|x| x.expect_struct(span)) - .collect::>() + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, + ) -> CompileResult { + let mut warnings = Vec::new(); + let mut errors = Vec::new(); + + if self.is_monomorph_cache_enabled { + let cached_struct_decl = check!( + CompileResult::from(self.de_get_monomorphized_struct( + decl_id, + type_arguments, + call_site_span + )), + return err(warnings, errors), + warnings, + errors + ); + return ok(cached_struct_decl, warnings, errors); + } + + // monomorphize the struct declaration into a new copy + let mut typed_struct_declaration = check!( + CompileResult::from(self.de_get_struct(decl_id.clone(), call_site_span)), + return err(warnings, errors), + warnings, + errors + ); + + check!( + monomorphize( + &mut typed_struct_declaration, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ), + return err(warnings, errors), + warnings, + errors + ); + + // add the new copy to the declaration engine + let new_id = self + .slab + .insert(DeclarationWrapper::Struct(typed_struct_declaration.clone())); + self.de_add_monomorphized_copy(decl_id, DeclarationId::new(new_id, call_site_span.clone())); + + ok(typed_struct_declaration, warnings, errors) } fn de_insert_storage(&self, storage: TypedStorageDeclaration) -> DeclarationId { @@ -213,20 +337,6 @@ pub(crate) fn de_get_function( DECLARATION_ENGINE.de_get_function(index, span) } -pub(crate) fn de_add_monomorphized_function_copy( - original_id: DeclarationId, - new_copy: TypedFunctionDeclaration, -) { - DECLARATION_ENGINE.de_add_monomorphized_function_copy(original_id, new_copy); -} - -pub(crate) fn de_get_monomorphized_function_copies( - original_id: DeclarationId, - span: &Span, -) -> Result, CompileError> { - DECLARATION_ENGINE.de_get_monomorphized_function_copies(original_id, span) -} - pub(crate) fn de_insert_trait(r#trait: TypedTraitDeclaration) -> DeclarationId { DECLARATION_ENGINE.de_insert_trait(r#trait) } @@ -249,8 +359,8 @@ pub(crate) fn de_get_trait_fn( DECLARATION_ENGINE.de_get_trait_fn(index, span) } -pub(crate) fn insert_trait_impl(trait_impl: TypedImplTrait) -> DeclarationId { - DECLARATION_ENGINE.insert_trait_impl(trait_impl) +pub(crate) fn de_insert_trait_impl(trait_impl: TypedImplTrait) -> DeclarationId { + DECLARATION_ENGINE.de_insert_trait_impl(trait_impl) } pub(crate) fn de_get_trait_impl( @@ -264,25 +374,29 @@ pub(crate) fn de_insert_struct(r#struct: TypedStructDeclaration) -> DeclarationI DECLARATION_ENGINE.de_insert_struct(r#struct) } -pub(crate) fn de_get_struct( +pub fn de_get_struct( index: DeclarationId, span: &Span, ) -> Result { DECLARATION_ENGINE.de_get_struct(index, span) } -pub(crate) fn de_add_monomorphized_struct_copy( - original_id: DeclarationId, - new_copy: TypedStructDeclaration, -) { - DECLARATION_ENGINE.de_add_monomorphized_struct_copy(original_id, new_copy); -} - -pub(crate) fn de_get_monomorphized_struct_copies( - original_id: DeclarationId, - span: &Span, -) -> Result, CompileError> { - DECLARATION_ENGINE.de_get_monomorphized_struct_copies(original_id, span) +pub(crate) fn de_get_or_create_monomorphized_struct( + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, +) -> CompileResult { + DECLARATION_ENGINE.de_get_or_create_monomorphized_struct( + decl_id, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ) } pub(crate) fn de_insert_storage(storage: TypedStorageDeclaration) -> DeclarationId { diff --git a/sway-core/src/type_system/mod.rs b/sway-core/src/type_system/mod.rs index bd80f613081..cccf02e9d7c 100644 --- a/sway-core/src/type_system/mod.rs +++ b/sway-core/src/type_system/mod.rs @@ -7,7 +7,7 @@ mod resolved_type; mod trait_constraint; mod type_argument; mod type_binding; -mod type_engine; +pub(crate) mod type_engine; mod type_id; mod type_info; mod type_mapping; diff --git a/sway-core/src/type_system/type_argument.rs b/sway-core/src/type_system/type_argument.rs index 03657319e6e..ad7aedbfc9a 100644 --- a/sway-core/src/type_system/type_argument.rs +++ b/sway-core/src/type_system/type_argument.rs @@ -30,6 +30,12 @@ impl PartialEq for TypeArgument { } } +impl PartialEq for TypeArgument { + fn eq(&self, other: &TypeParameter) -> bool { + self.type_id == other.type_id + } +} + impl Default for TypeArgument { fn default() -> Self { let initial_type_id = insert_type(TypeInfo::Unknown); diff --git a/sway-core/src/type_system/type_parameter.rs b/sway-core/src/type_system/type_parameter.rs index cbbcc93ac82..7bec38a4a50 100644 --- a/sway-core/src/type_system/type_parameter.rs +++ b/sway-core/src/type_system/type_parameter.rs @@ -37,6 +37,12 @@ impl PartialEq for TypeParameter { } } +impl PartialEq for TypeParameter { + fn eq(&self, other: &TypeArgument) -> bool { + self.type_id == other.type_id + } +} + impl CopyTypes for TypeParameter { fn copy_types(&mut self, type_mapping: &TypeMapping) { self.type_id = match look_up_type_id(self.type_id).matches_type_parameter(type_mapping) {