refactor(compiler): purify literal arrays and maps in template pipeline (#50118)

This commit transforms literal arrays and maps within expressions in the
template pipeline into `ir.PureFunctionExpr` expressions, in order to
memoize the allocation of objects and arrays inside the update pass of
change detection.

PR Close #50118
This commit is contained in:
Alex Rickabaugh 2023-05-02 11:04:51 -07:00 committed by Dylan Hunn
parent a56726c069
commit 35227049a1
2 changed files with 67 additions and 0 deletions

View file

@ -29,12 +29,14 @@ import {phaseMergeNextContext} from './phases/next_context_merging';
import {phaseNgContainer} from './phases/ng_container';
import {phaseSaveRestoreView} from './phases/save_restore_view';
import {phasePureFunctionExtraction} from './phases/pure_function_extraction';
import {phasePureLiteralStructures} from './phases/pure_literal_structures';
/**
* Run all transformation phases in the correct order against a `ComponentCompilation`. After this
* processing, the compilation should be in a state where it can be emitted via `emitTemplateFn`.s
*/
export function transformTemplate(cpl: ComponentCompilation): void {
phasePureLiteralStructures(cpl);
phaseGenerateVariables(cpl);
phaseSaveRestoreView(cpl);
phaseResolveNames(cpl);

View file

@ -0,0 +1,65 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as o from '../../../../output/output_ast';
import * as ir from '../../ir';
import type {ComponentCompilation} from '../compilation';
export function phasePureLiteralStructures(cpl: ComponentCompilation): void {
for (const view of cpl.views.values()) {
for (const op of view.update) {
ir.transformExpressionsInOp(op, (expr, flags) => {
if (flags & ir.VisitorContextFlag.InChildOperation) {
return expr;
}
if (expr instanceof o.LiteralArrayExpr) {
return transformLiteralArray(expr);
} else if (expr instanceof o.LiteralMapExpr) {
return transformLiteralMap(expr);
}
return expr;
}, ir.VisitorContextFlag.None);
}
}
}
function transformLiteralArray(expr: o.LiteralArrayExpr): o.Expression {
const derivedEntries: o.Expression[] = [];
const nonConstantArgs: o.Expression[] = [];
for (const entry of expr.entries) {
if (entry.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry);
derivedEntries.push(new ir.PureFunctionParameterExpr(idx));
}
}
return new ir.PureFunctionExpr(o.literalArr(derivedEntries), nonConstantArgs);
}
function transformLiteralMap(expr: o.LiteralMapExpr): o.Expression {
let derivedEntries: o.LiteralMapEntry[] = [];
const nonConstantArgs: o.Expression[] = [];
for (const entry of expr.entries) {
if (entry.value.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry.value);
derivedEntries.push(new o.LiteralMapEntry(
entry.key,
new ir.PureFunctionParameterExpr(idx),
entry.quoted,
));
}
}
return new ir.PureFunctionExpr(o.literalMap(derivedEntries), nonConstantArgs);
}