avoid creating unnecessary errors

previously, when attempting to locate a mixin/fn/variable, we would
check if it existing simply by calling `get_{mixin,fn,var}`. this caused
*large* performance regressions in bootstrap, where almost 15% of the
execution time was spent in these functions. the cause for this was that
`get_*` both allocates a new String and boxes the error.
This commit is contained in:
Connor Skees 2020-07-08 20:26:54 -04:00
parent 11170ac5b3
commit 05b6b539ad

View File

@ -10,7 +10,7 @@ use crate::{
value::Value, value::Value,
}; };
#[derive(Debug, Clone, Default)] #[derive(Debug, Default)]
pub(crate) struct Scope { pub(crate) struct Scope {
vars: HashMap<Identifier, Spanned<Value>>, vars: HashMap<Identifier, Spanned<Value>>,
mixins: HashMap<Identifier, Mixin>, mixins: HashMap<Identifier, Mixin>,
@ -79,7 +79,7 @@ impl Scope {
} }
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Default)]
pub(crate) struct Scopes(Vec<Scope>); pub(crate) struct Scopes(Vec<Scope>);
impl Scopes { impl Scopes {
@ -148,8 +148,8 @@ impl Scopes {
global_scope: &'a Scope, global_scope: &'a Scope,
) -> SassResult<&Value> { ) -> SassResult<&Value> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if let Ok(v) = scope.get_var(name) { if scope.var_exists(&name.node) {
return Ok(v); return scope.get_var(name);
} }
} }
global_scope.get_var(name) global_scope.get_var(name)
@ -184,8 +184,8 @@ impl Scopes {
global_scope: &'a Scope, global_scope: &'a Scope,
) -> SassResult<Mixin> { ) -> SassResult<Mixin> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if let Ok(v) = scope.get_mixin(name) { if scope.mixin_exists(&name.node) {
return Ok(v); return scope.get_mixin(name);
} }
} }
global_scope.get_mixin(name) global_scope.get_mixin(name)
@ -220,8 +220,8 @@ impl Scopes {
global_scope: &'a Scope, global_scope: &'a Scope,
) -> SassResult<Function> { ) -> SassResult<Function> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if let Ok(v) = scope.get_fn(name) { if scope.fn_exists(&name.node) {
return Ok(v); return scope.get_fn(name);
} }
} }
global_scope.get_fn(name) global_scope.get_fn(name)