Skip to content

Sway compiler optimizations #7080

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

Merged
merged 6 commits into from
Apr 15, 2025
Merged
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
6 changes: 3 additions & 3 deletions forc-plugins/forc-doc/src/render/item/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ impl Renderable for TyFunctionDecl {
let attributes = self.attributes.to_html_string();

let mut fn_sig = format!("fn {}(", self.name.as_str());
for param in &self.parameters {
for param in self.parameters.iter() {
let mut param_str = String::new();
if param.is_reference {
write!(param_str, "ref ")?;
Expand Down Expand Up @@ -651,7 +651,7 @@ impl Renderable for TyFunctionDecl {
}
: "(";
@ if multiline {
@ for param in &self.parameters {
@ for param in self.parameters.iter() {
br;
: " ";
@ if param.is_reference {
Expand All @@ -672,7 +672,7 @@ impl Renderable for TyFunctionDecl {
br;
: ")";
} else {
@ for param in &self.parameters {
@ for param in self.parameters.iter() {
@ if param.is_reference {
: "ref";
}
Expand Down
9 changes: 9 additions & 0 deletions sway-core/src/concurrent_slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ where
.clone()
}

/// Improve performance by avoiding `Arc::clone`.
/// The slab is kept locked while running `f`.
pub fn map<R>(&self, index: usize, f: impl FnOnce(&T) -> R) -> R {
let inner = self.inner.read();
f(inner.items[index]
.as_ref()
.expect("invalid slab index for ConcurrentSlab::get"))
}

pub fn retain(&self, predicate: impl Fn(&usize, &mut Arc<T>) -> bool) {
let mut inner = self.inner.write();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ fn connect_fn_params_struct_enums<'eng: 'cfg, 'cfg>(
fn_decl_entry_node: NodeIndex,
) -> Result<(), CompileError> {
let type_engine = engines.te();
for fn_param in &fn_decl.parameters {
for fn_param in fn_decl.parameters.iter() {
let ty = type_engine.to_typeinfo(
fn_param.type_argument.type_id(),
&fn_param.type_argument.span(),
Expand Down
9 changes: 9 additions & 0 deletions sway-core/src/decl_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ impl Clone for DeclEngine {

pub trait DeclEngineGet<I, U> {
fn get(&self, index: &I) -> Arc<U>;
fn map<R>(&self, index: &I, f: impl FnOnce(&U) -> R) -> R;
}

pub trait DeclEngineGetParsedDeclId<T>
Expand Down Expand Up @@ -175,12 +176,20 @@ macro_rules! decl_engine_get {
fn get(&self, index: &DeclId<$decl>) -> Arc<$decl> {
self.$slab.get(index.inner())
}

fn map<R>(&self, index: &DeclId<$decl>, f: impl FnOnce(&$decl) -> R) -> R {
self.$slab.map(index.inner(), f)
}
}

impl DeclEngineGet<DeclRef<DeclId<$decl>>, $decl> for DeclEngine {
fn get(&self, index: &DeclRef<DeclId<$decl>>) -> Arc<$decl> {
self.$slab.get(index.id().inner())
}

fn map<R>(&self, index: &DeclRef<DeclId<$decl>>, f: impl FnOnce(&$decl) -> R) -> R {
self.$slab.map(index.id().inner(), f)
}
}
};
}
Expand Down
5 changes: 5 additions & 0 deletions sway-core/src/decl_engine/parsed_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct ParsedDeclEngine {

pub trait ParsedDeclEngineGet<I, U> {
fn get(&self, index: &I) -> Arc<U>;
fn map<R>(&self, index: &I, f: impl FnOnce(&U) -> R) -> R;
}

pub trait ParsedDeclEngineInsert<T> {
Expand All @@ -58,6 +59,10 @@ macro_rules! decl_engine_get {
fn get(&self, index: &ParsedDeclId<$decl>) -> Arc<$decl> {
self.$slab.get(index.inner())
}

fn map<R>(&self, index: &ParsedDeclId<$decl>, f: impl FnOnce(&$decl) -> R) -> R {
self.$slab.map(index.inner(), f)
}
}
};
}
Expand Down
49 changes: 49 additions & 0 deletions sway-core/src/decl_engine/replace_decls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ pub trait ReplaceDecls {
}
}

impl<T: ReplaceDecls + Clone> ReplaceDecls for std::sync::Arc<T> {
fn replace_decls_inner(
&mut self,
decl_mapping: &DeclMapping,
handler: &Handler,
ctx: &mut TypeCheckContext,
) -> Result<bool, ErrorEmitted> {
if let Some(item) = std::sync::Arc::get_mut(self) {
item.replace_decls_inner(decl_mapping, handler, ctx)
} else {
let mut item = self.as_ref().clone();
let r = item.replace_decls_inner(decl_mapping, handler, ctx)?;
*self = std::sync::Arc::new(item);
Ok(r)
}
}
}

pub(crate) trait ReplaceFunctionImplementingType {
fn replace_implementing_type(&mut self, engines: &Engines, implementing_type: ty::TyDecl);
}
Expand All @@ -38,6 +56,18 @@ pub(crate) trait UpdateConstantExpression {
fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl);
}

impl<T: UpdateConstantExpression + Clone> UpdateConstantExpression for std::sync::Arc<T> {
fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) {
if let Some(item) = std::sync::Arc::get_mut(self) {
item.update_constant_expression(engines, implementing_type);
} else {
let mut item = self.as_ref().clone();
item.update_constant_expression(engines, implementing_type);
*self = std::sync::Arc::new(item);
}
}
}

// Iterate the tree searching for references to a const generic,
// and initialize its value with the passed value
pub(crate) trait MaterializeConstGenerics {
Expand All @@ -49,3 +79,22 @@ pub(crate) trait MaterializeConstGenerics {
value: &TyExpression,
) -> Result<(), ErrorEmitted>;
}

impl<T: MaterializeConstGenerics + Clone> MaterializeConstGenerics for std::sync::Arc<T> {
fn materialize_const_generics(
&mut self,
engines: &Engines,
handler: &Handler,
name: &str,
value: &TyExpression,
) -> Result<(), ErrorEmitted> {
if let Some(item) = std::sync::Arc::get_mut(self) {
item.materialize_const_generics(engines, handler, name, value)
} else {
let mut item = self.as_ref().clone();
let r = item.materialize_const_generics(engines, handler, name, value);
*self = std::sync::Arc::new(item);
r
}
}
}
2 changes: 1 addition & 1 deletion sway-core/src/language/ty/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ impl TyFunctionDecl {
TyFunctionDecl {
purity: *purity,
name: name.clone(),
body: TyCodeBlock::default(),
body: <_>::default(),
implementing_type: None,
implementing_for_typeid: None,
span: span.clone(),
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/language/ty/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn get_type_not_allowed_error(

fn check_no_ref_main(engines: &Engines, handler: &Handler, main_function: &DeclId<TyFunctionDecl>) {
let main_function = engines.de().get_function(main_function);
for param in &main_function.parameters {
for param in main_function.parameters.iter() {
if param.is_reference && param.is_mutable {
handler.emit_err(CompileError::RefMutableNotAllowedInMain {
param_name: param.name.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl ty::TyAbiDecl {
)
.unwrap_or_else(|_| ty::TyFunctionDecl::error(&method));
error_on_shadowing_superabi_method(&method.name, ctx);
for param in &method.parameters {
for param in method.parameters.iter() {
if param.is_reference || param.is_mutable {
handler.emit_err(CompileError::RefMutableNotAllowedInContractAbi {
param_name: param.name.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl ty::TyFunctionDecl {

let function_decl = ty::TyFunctionDecl {
name: name.clone(),
body: TyCodeBlock::default(),
body: <_>::default(),
parameters: new_parameters,
implementing_type: None,
implementing_for_typeid,
Expand Down Expand Up @@ -220,7 +220,7 @@ impl ty::TyFunctionDecl {
}

// Insert the previously type checked function parameters into the current namespace.
for p in parameters {
for p in parameters.iter() {
p.insert_into_namespace(handler, ctx.by_ref());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ fn type_check_impl_method(
for (impl_method_signature_param, impl_method_param) in impl_method_signature
.parameters
.iter_mut()
.zip(&mut impl_method.parameters)
.zip(impl_method.parameters.iter_mut())
{
// TODO use trait constraints as part of the type here to
// implement trait constraint solver */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl ty::TyTraitFn {
ty::TyFunctionDecl {
purity: self.purity,
name: self.name.clone(),
body: ty::TyCodeBlock::default(),
body: <_>::default(),
parameters: self.parameters.clone(),
implementing_type: match abi_mode.clone() {
AbiMode::ImplAbiFn(_abi_name, abi_decl_id) => {
Expand Down
56 changes: 28 additions & 28 deletions sway-core/src/semantic_analysis/namespace/trait_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,9 @@ impl TraitMap {
*type_id,
*map_type_id,
engines,
),
)
.map(|(name, item)| (name.to_string(), item))
.collect(),
engines,
);
}
Expand All @@ -711,49 +713,51 @@ impl TraitMap {
trait_map
}

fn filter_dummy_methods(
map_trait_items: &TraitItems,
fn filter_dummy_methods<'a>(
map_trait_items: &'a TraitItems,
type_id: TypeId,
map_type_id: TypeId,
engines: &Engines,
) -> TraitItems {
let mut insertable = true;
if let TypeInfo::UnknownGeneric {
is_from_type_parameter,
..
} = *engines.te().get(map_type_id)
{
insertable = !is_from_type_parameter
|| matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. });
}
engines: &'a Engines,
) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
TypeInfo::UnknownGeneric {
is_from_type_parameter,
..
} => Some(*is_from_type_parameter),
_ => None,
});
let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
!is_from_type_parameter
|| matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
} else {
true
};

map_trait_items
.iter()
.filter_map(|(name, item)| match item {
.filter_map(move |(name, item)| match item {
ResolvedTraitImplItem::Parsed(_item) => todo!(),
ResolvedTraitImplItem::Typed(item) => match item {
ty::TyTraitItem::Fn(decl_ref) => {
let decl = (*engines.de().get(decl_ref.id())).clone();
ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
if decl.is_trait_method_dummy && !insertable {
None
} else {
Some((
name.clone(),
name.as_str(),
ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
))
}
}
}),
ty::TyTraitItem::Constant(decl_ref) => Some((
name.clone(),
name.as_str(),
ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
)),
ty::TyTraitItem::Type(decl_ref) => Some((
name.clone(),
name.as_str(),
ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
)),
},
})
.collect()
}

fn make_item_for_type_mapping(
Expand Down Expand Up @@ -859,9 +863,7 @@ impl TraitMap {
entry.key.type_id,
engines,
)
.values()
.cloned()
.map(|i| (i, entry.key.clone()))
.map(|(_, i)| (i, entry.key.clone()))
.collect::<Vec<_>>();

items.extend(trait_items);
Expand Down Expand Up @@ -1019,9 +1021,7 @@ impl TraitMap {
e.key.type_id,
engines,
)
.values()
.cloned()
.map(|i| {
.map(|(_, i)| {
Self::make_item_for_type_mapping(
engines,
i,
Expand Down
Loading
Loading