From ed60d6371354e848c8ce9ef7e1c38fa5c8040ae2 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:17:04 +0200 Subject: [PATCH] Implement optimization identifier --- boa_ast/src/operations.rs | 60 +++++++++++++++++++++++++ boa_engine/src/bytecompiler/function.rs | 18 +++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/boa_ast/src/operations.rs b/boa_ast/src/operations.rs index 09d7634d06b..09dab5a6745 100644 --- a/boa_ast/src/operations.rs +++ b/boa_ast/src/operations.rs @@ -2156,3 +2156,63 @@ impl<'ast> Visitor<'ast> for ReturnsValueVisitor { ControlFlow::Continue(()) } } + +/// Returns `true` if the given statement can optimize local variables. +#[must_use] +pub fn can_optimize_local_variables<'a, N>(node: &'a N) -> bool +where + &'a N: Into>, +{ + CanOptimizeLocalVariables.visit(node.into()).is_continue() +} + +/// The [`Visitor`] used for [`returns_value`]. +#[derive(Debug)] +struct CanOptimizeLocalVariables; + +impl<'ast> Visitor<'ast> for CanOptimizeLocalVariables { + type BreakTy = (); + + fn visit_with(&mut self, _node: &'ast crate::statement::With) -> ControlFlow { + ControlFlow::Break(()) + } + + fn visit_call(&mut self, node: &'ast crate::expression::Call) -> ControlFlow { + if let Expression::Identifier(identifier) = node.function() { + if identifier.sym() == Sym::EVAL { + return ControlFlow::Break(()); + } + } + + try_break!(node.function().visit_with(self)); + + for arg in node.args() { + try_break!(arg.visit_with(self)); + } + + ControlFlow::Continue(()) + } + + fn visit_function(&mut self, _node: &'ast Function) -> ControlFlow { + ControlFlow::Break(()) + } + + fn visit_arrow_function(&mut self, _node: &'ast ArrowFunction) -> ControlFlow { + ControlFlow::Break(()) + } + + fn visit_async_function(&mut self, _node: &'ast AsyncFunction) -> ControlFlow { + ControlFlow::Break(()) + } + + fn visit_async_arrow_function( + &mut self, + _node: &'ast AsyncArrowFunction, + ) -> ControlFlow { + ControlFlow::Break(()) + } + + fn visit_class(&mut self, _node: &'ast Class) -> ControlFlow { + ControlFlow::Break(()) + } +} diff --git a/boa_engine/src/bytecompiler/function.rs b/boa_engine/src/bytecompiler/function.rs index 986fef08dcd..01045f7660a 100644 --- a/boa_engine/src/bytecompiler/function.rs +++ b/boa_engine/src/bytecompiler/function.rs @@ -7,7 +7,10 @@ use crate::{ vm::{CodeBlock, CodeBlockFlags, Opcode}, Context, }; -use boa_ast::function::{FormalParameterList, FunctionBody}; +use boa_ast::{ + function::{FormalParameterList, FunctionBody}, + operations::can_optimize_local_variables, +}; use boa_gc::Gc; use boa_interner::Sym; @@ -148,6 +151,19 @@ impl FunctionCompiler { compiler.async_handler = Some(compiler.push_handler()); } + let can_optimize_params = can_optimize_local_variables(parameters); + let can_optimize_body = can_optimize_local_variables(body); + println!("Can optimize params: {can_optimize_params}"); + println!("Can optimize body: {can_optimize_body}"); + + let can_optimize = can_optimize_params + && can_optimize_body + && !parameters.has_arguments() + && !parameters.has_duplicates() + && !parameters.has_rest_parameter() + && parameters.is_simple(); + println!("Can optimize function: {can_optimize}"); + let (env_label, additional_env) = compiler.function_declaration_instantiation( body, parameters,