소스 검색

LibJS: Avoid creating empty environment for `catch` without parameter

When there is no `catch` parameter to bind the error, we don't need
to allocate an environment, since there's nothing to add to it.

This avoids one environment allocation every time we catch like this:

    try {
        ...
    } catch {
        ...
    }
Andreas Kling 1 년 전
부모
커밋
4f488f7e07
1개의 변경된 파일11개의 추가작업 그리고 2개의 파일을 삭제
  1. 11 2
      Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

+ 11 - 2
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -2369,10 +2369,14 @@ Bytecode::CodeGenerationErrorOr<void> TryStatement::generate_bytecode(Bytecode::
         if (!m_finalizer)
         if (!m_finalizer)
             generator.emit<Bytecode::Op::LeaveUnwindContext>();
             generator.emit<Bytecode::Op::LeaveUnwindContext>();
 
 
-        generator.begin_variable_scope();
+        // OPTIMIZATION: We avoid creating a lexical environment if the catch clause has no parameter.
+        bool did_create_variable_scope_for_catch_clause = false;
+
         TRY(m_handler->parameter().visit(
         TRY(m_handler->parameter().visit(
             [&](DeprecatedFlyString const& parameter) -> Bytecode::CodeGenerationErrorOr<void> {
             [&](DeprecatedFlyString const& parameter) -> Bytecode::CodeGenerationErrorOr<void> {
                 if (!parameter.is_empty()) {
                 if (!parameter.is_empty()) {
+                    generator.begin_variable_scope();
+                    did_create_variable_scope_for_catch_clause = true;
                     auto parameter_identifier = generator.intern_identifier(parameter);
                     auto parameter_identifier = generator.intern_identifier(parameter);
                     generator.emit<Bytecode::Op::CreateVariable>(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
                     generator.emit<Bytecode::Op::CreateVariable>(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
                     generator.emit<Bytecode::Op::SetVariable>(parameter_identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize);
                     generator.emit<Bytecode::Op::SetVariable>(parameter_identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize);
@@ -2380,6 +2384,9 @@ Bytecode::CodeGenerationErrorOr<void> TryStatement::generate_bytecode(Bytecode::
                 return {};
                 return {};
             },
             },
             [&](NonnullRefPtr<BindingPattern const> const& binding_pattern) -> Bytecode::CodeGenerationErrorOr<void> {
             [&](NonnullRefPtr<BindingPattern const> const& binding_pattern) -> Bytecode::CodeGenerationErrorOr<void> {
+                generator.begin_variable_scope();
+                did_create_variable_scope_for_catch_clause = true;
+
                 auto value_register = generator.allocate_register();
                 auto value_register = generator.allocate_register();
                 generator.emit<Bytecode::Op::Store>(value_register);
                 generator.emit<Bytecode::Op::Store>(value_register);
                 TRY(generate_binding_pattern_bytecode(generator, *binding_pattern, Bytecode::Op::SetVariable::InitializationMode::Initialize, value_register, true));
                 TRY(generate_binding_pattern_bytecode(generator, *binding_pattern, Bytecode::Op::SetVariable::InitializationMode::Initialize, value_register, true));
@@ -2393,7 +2400,9 @@ Bytecode::CodeGenerationErrorOr<void> TryStatement::generate_bytecode(Bytecode::
 
 
         TRY(m_handler->body().generate_bytecode(generator));
         TRY(m_handler->body().generate_bytecode(generator));
         handler_target = Bytecode::Label { handler_block };
         handler_target = Bytecode::Label { handler_block };
-        generator.end_variable_scope();
+
+        if (did_create_variable_scope_for_catch_clause)
+            generator.end_variable_scope();
 
 
         if (!generator.is_current_block_terminated()) {
         if (!generator.is_current_block_terminated()) {
             if (m_finalizer) {
             if (m_finalizer) {