From 6ba6da62d72edf69d699e2c031aa38c630e00e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 4 Sep 2022 16:33:26 +0900 Subject: [PATCH] perf(es/minifier): Make dead branch remover parallel (#5734) --- .../fixture/issues/typescript/1/output.js | 24 +++++----- .../tests/projects/output/angular-1.2.5.js | 18 ++++---- .../src/simplify/branch/mod.rs | 45 ++++++++++++++++--- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/typescript/1/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/typescript/1/output.js index 3c5ba4f0a97..63312431bcf 100644 --- a/crates/swc_ecma_minifier/tests/fixture/issues/typescript/1/output.js +++ b/crates/swc_ecma_minifier/tests/fixture/issues/typescript/1/output.js @@ -165,12 +165,14 @@ var ts; function addExportEqualsIfNeeded(statements, emitAsReturn) { if (currentModuleInfo.exportEquals) { var expressionResult = ts.visitNode(currentModuleInfo.exportEquals.expression, visitor); - if (expressionResult) if (emitAsReturn) { - var statement = factory.createReturnStatement(expressionResult); - ts.setTextRange(statement, currentModuleInfo.exportEquals), ts.setEmitFlags(statement, 1920), statements.push(statement); - } else { - var statement = factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier("module"), "exports"), expressionResult)); - ts.setTextRange(statement, currentModuleInfo.exportEquals), ts.setEmitFlags(statement, 1536), statements.push(statement); + if (expressionResult) { + if (emitAsReturn) { + var statement = factory.createReturnStatement(expressionResult); + ts.setTextRange(statement, currentModuleInfo.exportEquals), ts.setEmitFlags(statement, 1920), statements.push(statement); + } else { + var statement = factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier("module"), "exports"), expressionResult)); + ts.setTextRange(statement, currentModuleInfo.exportEquals), ts.setEmitFlags(statement, 1536), statements.push(statement); + } } } } @@ -243,10 +245,12 @@ var ts; for(var statements, variables, expressions, modifiers = void 0, removeCommentsOnExpressions = !1, _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++){ var variable = _a[_i]; if (ts.isIdentifier(variable.name) && ts.isLocalName(variable.name)) modifiers || (modifiers = ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier)), variables = ts.append(variables, variable); - else if (variable.initializer) if (!ts.isBindingPattern(variable.name) && (ts.isArrowFunction(variable.initializer) || ts.isFunctionExpression(variable.initializer) || ts.isClassExpression(variable.initializer))) { - var expression = factory.createAssignment(ts.setTextRange(factory.createPropertyAccessExpression(factory.createIdentifier("exports"), variable.name), variable.name), factory.createIdentifier(ts.getTextOfIdentifierOrLiteral(variable.name))), updatedVariable = factory.createVariableDeclaration(variable.name, variable.exclamationToken, variable.type, ts.visitNode(variable.initializer, visitor)); - variables = ts.append(variables, updatedVariable), expressions = ts.append(expressions, expression), removeCommentsOnExpressions = !0; - } else expressions = ts.append(expressions, transformInitializedVariable(variable)); + else if (variable.initializer) { + if (!ts.isBindingPattern(variable.name) && (ts.isArrowFunction(variable.initializer) || ts.isFunctionExpression(variable.initializer) || ts.isClassExpression(variable.initializer))) { + var expression = factory.createAssignment(ts.setTextRange(factory.createPropertyAccessExpression(factory.createIdentifier("exports"), variable.name), variable.name), factory.createIdentifier(ts.getTextOfIdentifierOrLiteral(variable.name))), updatedVariable = factory.createVariableDeclaration(variable.name, variable.exclamationToken, variable.type, ts.visitNode(variable.initializer, visitor)); + variables = ts.append(variables, updatedVariable), expressions = ts.append(expressions, expression), removeCommentsOnExpressions = !0; + } else expressions = ts.append(expressions, transformInitializedVariable(variable)); + } } if (variables && (statements = ts.append(statements, factory.updateVariableStatement(node, modifiers, factory.updateVariableDeclarationList(node.declarationList, variables)))), expressions) { var statement = ts.setOriginalNode(ts.setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node), node); diff --git a/crates/swc_ecma_minifier/tests/projects/output/angular-1.2.5.js b/crates/swc_ecma_minifier/tests/projects/output/angular-1.2.5.js index d20d70fbf7e..e48bed0709b 100644 --- a/crates/swc_ecma_minifier/tests/projects/output/angular-1.2.5.js +++ b/crates/swc_ecma_minifier/tests/projects/output/angular-1.2.5.js @@ -1189,14 +1189,16 @@ if (attrStart && ($compileNode = groupScan(compileNode, attrStart, attrEnd)), $template = undefined, terminalPriority > directive.priority) break; if ((directiveValue = directive.scope) && (newScopeDirective = newScopeDirective || directive, !directive.templateUrl && (assertNoDuplicate("new/isolated scope", newIsolateScopeDirective, directive, $compileNode), isObject(directiveValue) && (newIsolateScopeDirective = directive))), directiveName = directive.name, !directive.templateUrl && directive.controller && (directiveValue = directive.controller, assertNoDuplicate("'" + directiveName + "' controller", (controllerDirectives = controllerDirectives || {})[directiveName], directive, $compileNode), controllerDirectives[directiveName] = directive), (directiveValue = directive.transclude) && (hasTranscludeDirective = !0, directive.$$tlb || (assertNoDuplicate("transclusion", nonTlbTranscludeDirective, directive, $compileNode), nonTlbTranscludeDirective = directive), "element" == directiveValue ? (hasElementTranscludeDirective = !0, terminalPriority = directive.priority, $template = groupScan(compileNode, attrStart, attrEnd), compileNode = ($compileNode = templateAttrs.$$element = jqLite(document1.createComment(" " + directiveName + ": " + templateAttrs[directiveName] + " ")))[0], replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode), childTranscludeFn = compile($template, transcludeFn, terminalPriority, replaceDirective && replaceDirective.name, { nonTlbTranscludeDirective: nonTlbTranscludeDirective - })) : ($template = jqLite(jqLiteClone(compileNode)).contents(), $compileNode.empty(), childTranscludeFn = compile($template, transcludeFn))), directive.template) if (assertNoDuplicate("template", templateDirective, directive, $compileNode), templateDirective = directive, directiveValue = isFunction(directive.template) ? directive.template($compileNode, templateAttrs) : directive.template, directiveValue = denormalizeTemplate(directiveValue), directive.replace) { - if (replaceDirective = directive, compileNode = ($template = jqLite("
" + trim(directiveValue) + "
").contents())[0], 1 != $template.length || 1 !== compileNode.nodeType) throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ""); - replaceWith(jqCollection, $compileNode, compileNode); - var newTemplateAttrs = { - $attr: {} - }, templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs), unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); - newIsolateScopeDirective && markDirectivesAsIsolate(templateDirectives), directives = directives.concat(templateDirectives).concat(unprocessedDirectives), mergeTemplateAttributes(templateAttrs, newTemplateAttrs), ii = directives.length; - } else $compileNode.html(directiveValue); + })) : ($template = jqLite(jqLiteClone(compileNode)).contents(), $compileNode.empty(), childTranscludeFn = compile($template, transcludeFn))), directive.template) { + if (assertNoDuplicate("template", templateDirective, directive, $compileNode), templateDirective = directive, directiveValue = isFunction(directive.template) ? directive.template($compileNode, templateAttrs) : directive.template, directiveValue = denormalizeTemplate(directiveValue), directive.replace) { + if (replaceDirective = directive, compileNode = ($template = jqLite("
" + trim(directiveValue) + "
").contents())[0], 1 != $template.length || 1 !== compileNode.nodeType) throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ""); + replaceWith(jqCollection, $compileNode, compileNode); + var newTemplateAttrs = { + $attr: {} + }, templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs), unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + newIsolateScopeDirective && markDirectivesAsIsolate(templateDirectives), directives = directives.concat(templateDirectives).concat(unprocessedDirectives), mergeTemplateAttributes(templateAttrs, newTemplateAttrs), ii = directives.length; + } else $compileNode.html(directiveValue); + } if (directive.templateUrl) assertNoDuplicate("template", templateDirective, directive, $compileNode), templateDirective = directive, directive.replace && (replaceDirective = directive), nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, { controllerDirectives: controllerDirectives, newIsolateScopeDirective: newIsolateScopeDirective, diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs index be0d5663224..f5aaa78a432 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs @@ -7,7 +7,10 @@ use swc_common::{ Mark, Spanned, SyntaxContext, DUMMY_SP, }; use swc_ecma_ast::*; -use swc_ecma_transforms_base::pass::RepeatedJsPass; +use swc_ecma_transforms_base::{ + pass::RepeatedJsPass, + perf::{cpu_count, Parallel, ParallelExt}, +}; use swc_ecma_utils::{ extract_var_ids, is_literal, prepend_stmt, undefined, ExprCtx, ExprExt, ExprFactory, Hoister, IsEmpty, StmtExt, StmtLike, Value::Known, @@ -58,6 +61,17 @@ struct Remover { expr_ctx: ExprCtx, } +impl Parallel for Remover { + fn create(&self) -> Self { + Self { + expr_ctx: self.expr_ctx.clone(), + ..*self + } + } + + fn merge(&mut self, _: Self) {} +} + impl VisitMut for Remover { noop_visit_mut_type!(); @@ -1217,6 +1231,24 @@ impl VisitMut for Remover { s.cases.clear(); } } + + fn visit_mut_prop_or_spreads(&mut self, n: &mut Vec) { + self.maybe_par(cpu_count() * 8, n, |v, n| { + n.visit_mut_with(v); + }) + } + + fn visit_mut_expr_or_spreads(&mut self, n: &mut Vec) { + self.maybe_par(cpu_count() * 8, n, |v, n| { + n.visit_mut_with(v); + }) + } + + fn visit_mut_opt_vec_expr_or_spreads(&mut self, n: &mut Vec>) { + self.maybe_par(cpu_count() * 8, n, |v, n| { + n.visit_mut_with(v); + }) + } } impl Remover { @@ -1231,12 +1263,13 @@ impl Remover { let mut new_stmts = Vec::with_capacity(stmts.len()); - let mut iter = stmts.take().into_iter(); - while let Some(mut stmt_like) = iter.next() { - self.normal_block = true; - stmt_like.visit_mut_with(self); - self.normal_block = false; + self.maybe_par(cpu_count() * 8, &mut *stmts, |visitor, stmt| { + visitor.normal_block = true; + stmt.visit_mut_with(visitor); + }); + let mut iter = stmts.take().into_iter(); + while let Some(stmt_like) = iter.next() { let stmt_like = match stmt_like.try_into_stmt() { Ok(stmt) => { let stmt = match stmt {