perf(compiler): reduce amount of generated code for safe accesses and nullish coalescing (#41563)
This is follow-up from #41437 and it reduces the amount of code we generate for safe property accesses (`a?.b`) and nullish coalescing (`a ?? b`) by: 1. Reusing variables in nested nullish coalescing expressions. 2. Not initializing temporary variables to `null`. The way our code is generated means that the value will always be overwritten before we compare against it so the initializer didn't really matter. Fixes #41491. PR Close #41563
This commit is contained in:
parent
a1b2718b92
commit
dde81ba0cd
|
@ -1,13 +1,12 @@
|
||||||
hostBindings: function MyApp_HostBindings(rf, ctx) {
|
hostBindings: function MyApp_HostBindings(rf, ctx) {
|
||||||
if (rf & 1) {
|
if (rf & 1) {
|
||||||
i0.ɵɵlistener("click", function MyApp_click_HostBindingHandler() {
|
i0.ɵɵlistener("click", function MyApp_click_HostBindingHandler() {
|
||||||
let tmp_b_0 = null;
|
let $tmp$;
|
||||||
let tmp_b_1 = null;
|
return ctx.logLastName(($tmp$ = ($tmp$ = ctx.lastName) !== null && $tmp$ !== undefined ? $tmp$ : ctx.lastNameFallback) !== null && $tmp$ !== undefined ? $tmp$ : "unknown");
|
||||||
return ctx.logLastName((tmp_b_0 = (tmp_b_1 = ctx.lastName) !== null && tmp_b_1 !== undefined ? tmp_b_1 : ctx.lastNameFallback) !== null && tmp_b_0 !== undefined ? tmp_b_0 : "unknown");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let tmp_b_0 = null;
|
let $tmp$;
|
||||||
i0.ɵɵattribute("first-name", "Hello, " + ((tmp_b_0 = ctx.firstName) !== null && tmp_b_0 !== undefined ? tmp_b_0 : "Frodo") + "!");
|
i0.ɵɵattribute("first-name", "Hello, " + (($tmp$ = ctx.firstName) !== null && $tmp$ !== undefined ? $tmp$ : "Frodo") + "!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,11 @@ template: function MyApp_Template(rf, ctx) {
|
||||||
i0.ɵɵelementEnd();
|
i0.ɵɵelementEnd();
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let tmp_0_0 = null;
|
let $tmp_0_0$;
|
||||||
let tmp_1_0 = null;
|
let $tmp_1_0$;
|
||||||
let tmp_1_1 = null;
|
|
||||||
i0.ɵɵadvance(1);
|
i0.ɵɵadvance(1);
|
||||||
i0.ɵɵtextInterpolate1("Hello, ", (tmp_0_0 = ctx.firstName) !== null && tmp_0_0 !== undefined ? tmp_0_0 : "Frodo", "!");
|
i0.ɵɵtextInterpolate1("Hello, ", ($tmp_0_0$ = ctx.firstName) !== null && $tmp_0_0$ !== undefined ? $tmp_0_0$ : "Frodo", "!");
|
||||||
i0.ɵɵadvance(2);
|
i0.ɵɵadvance(2);
|
||||||
i0.ɵɵtextInterpolate1("Your last name is ", (tmp_1_0 = (tmp_1_1 = ctx.lastName) !== null && tmp_1_1 !== undefined ? tmp_1_1 : ctx.lastNameFallback) !== null && tmp_1_0 !== undefined ? tmp_1_0 : "unknown", "");
|
i0.ɵɵtextInterpolate1("Your last name is ", ($tmp_1_0$ = ($tmp_1_0$ = ctx.lastName) !== null && $tmp_1_0$ !== undefined ? $tmp_1_0$ : ctx.lastNameFallback) !== null && $tmp_1_0$ !== undefined ? $tmp_1_0$ : "unknown", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,10 @@ template: function MyApp_Template(rf, ctx) {
|
||||||
i0.ɵɵelement(1, "span", 0);
|
i0.ɵɵelement(1, "span", 0);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let tmp_0_0 = null;
|
let $tmp_0_0$;
|
||||||
let tmp_1_0 = null;
|
let $tmp_1_0$;
|
||||||
let tmp_1_1 = null;
|
i0.ɵɵproperty("title", "Hello, " + (($tmp_0_0$ = ctx.firstName) !== null && $tmp_0_0$ !== undefined ? $tmp_0_0$ : "Frodo") + "!");
|
||||||
i0.ɵɵproperty("title", "Hello, " + ((tmp_0_0 = ctx.firstName) !== null && tmp_0_0 !== undefined ? tmp_0_0 : "Frodo") + "!");
|
|
||||||
i0.ɵɵadvance(1);
|
i0.ɵɵadvance(1);
|
||||||
i0.ɵɵproperty("title", (tmp_1_0 = (tmp_1_1 = "Your last name is " + ctx.lastName) !== null && tmp_1_1 !== undefined ? tmp_1_1 : ctx.lastNameFallback) !== null && tmp_1_0 !== undefined ? tmp_1_0 : "unknown");
|
i0.ɵɵproperty("title", ($tmp_1_0$ = ($tmp_1_0$ = "Your last name is " + ctx.lastName) !== null && $tmp_1_0$ !== undefined ? $tmp_1_0$ : ctx.lastNameFallback) !== null && $tmp_1_0$ !== undefined ? $tmp_1_0$ : "unknown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ HostBindingDir.ɵdir = /*@__PURE__*/ $r3$.ɵɵdefineDirective({
|
||||||
hostVars: 1,
|
hostVars: 1,
|
||||||
hostBindings: function HostBindingDir_HostBindings(rf, ctx) {
|
hostBindings: function HostBindingDir_HostBindings(rf, ctx) {
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let $tmp0$ = null;
|
let $tmp0$;
|
||||||
$r3$.ɵɵhostProperty("id", ($tmp0$ = ctx.getData()) == null ? null : $tmp0$.id);
|
$r3$.ɵɵhostProperty("id", ($tmp0$ = ctx.getData()) == null ? null : $tmp0$.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
template: function MyComponent_Template(rf, ctx) {
|
template: function MyComponent_Template(rf, ctx) {
|
||||||
…
|
…
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let $tmp0$ = null;
|
let $tmp0$;
|
||||||
$r3$.ɵɵproperty("title", ctx.myTitle)("id", (tmp_1_0 = i0.ɵɵpipeBind1(1, 3, ctx.auth().identity())) == null ? null : tmp_1_0.id)("tabindex", 1);
|
$r3$.ɵɵproperty("title", ctx.myTitle)("id", ($tmp0$ = i0.ɵɵpipeBind1(1, 3, ctx.auth().identity())) == null ? null : $tmp0$.id)("tabindex", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ template: function MyComponent_Template(rf, ctx) {
|
||||||
$r3$.ɵɵelementEnd();
|
$r3$.ɵɵelementEnd();
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let $tmp_0_0$ = null;
|
let $tmp_0_0$;
|
||||||
$r3$.ɵɵi18nExp(($tmp_0_0$ = ctx.valueA.getRawValue()) == null ? null : $tmp_0_0$.getTitle());
|
$r3$.ɵɵi18nExp(($tmp_0_0$ = ctx.valueA.getRawValue()) == null ? null : $tmp_0_0$.getTitle());
|
||||||
$r3$.ɵɵi18nApply(1);
|
$r3$.ɵɵi18nApply(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,11 @@ template: function MyComponent_Template(rf, ctx) {
|
||||||
$r3$.ɵɵelementEnd();
|
$r3$.ɵɵelementEnd();
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
let $tmp_2_0$ = null;
|
let $tmp_2_0$;
|
||||||
$r3$.ɵɵadvance(2);
|
$r3$.ɵɵadvance(2);
|
||||||
$r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(2, 3, ctx.valueA))
|
$r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(2, 3, ctx.valueA))
|
||||||
(ctx.valueA == null ? null : ctx.valueA.a == null ? null : ctx.valueA.a.b)
|
(ctx.valueA == null ? null : ctx.valueA.a == null ? null : ctx.valueA.a.b)
|
||||||
(($tmp_2_0$ = ctx.valueA.getRawValue()) == null ? null : $tmp_2_0$.getTitle());
|
(($tmp_2_0$ = ctx.valueA.getRawValue()) == null ? null : $tmp_2_0$.getTitle());
|
||||||
$r3$.ɵɵi18nApply(1);
|
$r3$.ɵɵi18nApply(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,8 +259,8 @@ function temporaryName(bindingId: string, temporaryNumber: number): string {
|
||||||
return `tmp_${bindingId}_${temporaryNumber}`;
|
return `tmp_${bindingId}_${temporaryNumber}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function temporaryDeclaration(bindingId: string, temporaryNumber: number): o.Statement {
|
function temporaryDeclaration(bindingId: string, temporaryNumber: number): o.Statement {
|
||||||
return new o.DeclareVarStmt(temporaryName(bindingId, temporaryNumber), o.NULL_EXPR);
|
return new o.DeclareVarStmt(temporaryName(bindingId, temporaryNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
function prependTemporaryDecls(
|
function prependTemporaryDecls(
|
||||||
|
@ -728,15 +728,13 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produce the conditional
|
// Produce the conditional
|
||||||
return convertToStatementIfNeeded(mode, condition.conditional(o.literal(null), access));
|
return convertToStatementIfNeeded(mode, condition.conditional(o.NULL_EXPR, access));
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertNullishCoalesce(ast: cdAst.Binary, mode: _Mode): any {
|
private convertNullishCoalesce(ast: cdAst.Binary, mode: _Mode): any {
|
||||||
// Allocate the temporary variable before visiting the LHS and RHS, because they
|
|
||||||
// may allocate temporary variables too and we don't want them to be reused.
|
|
||||||
const temporary = this.allocateTemporary();
|
|
||||||
const left: o.Expression = this._visit(ast.left, _Mode.Expression);
|
const left: o.Expression = this._visit(ast.left, _Mode.Expression);
|
||||||
const right: o.Expression = this._visit(ast.right, _Mode.Expression);
|
const right: o.Expression = this._visit(ast.right, _Mode.Expression);
|
||||||
|
const temporary = this.allocateTemporary();
|
||||||
this.releaseTemporary(temporary);
|
this.releaseTemporary(temporary);
|
||||||
|
|
||||||
// Generate the following expression. It is identical to how TS
|
// Generate the following expression. It is identical to how TS
|
||||||
|
|
Loading…
Reference in New Issue