Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(ivy): move local references into consts array #33129

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -796,7 +796,6 @@ describe('compiler compliance', () => {
`IfDirective.ɵfac = function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵɵdirectiveInject($i$.TemplateRef)); };`;

const MyComponentDefinition = `
const $c1$ = ["foo", ""];
function MyComponent_li_2_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "li");
Expand All @@ -816,16 +815,16 @@ describe('compiler compliance', () => {
selectors: [["my-component"]],
decls: 3,
vars: 0,
consts: [[${AttributeMarker.Template}, "if"]],
consts: [["foo", ""], [${AttributeMarker.Template}, "if"]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "ul", null, $c1$);
$r3$.ɵɵtemplate(2, MyComponent_li_2_Template, 2, 2, "li", 0);
$r3$.ɵɵelementStart(0, "ul", null, 0);
$r3$.ɵɵtemplate(2, MyComponent_li_2_Template, 2, 2, "li", 1);
$r3$.ɵɵelementEnd();
}
},
directives:[IfDirective],
encapsulation: 2
directives: [IfDirective],
encapsulation: 2
});`;

const MyComponentFactory =
Expand Down Expand Up @@ -2231,16 +2230,16 @@ describe('compiler compliance', () => {
};

const MyComponentDefinition = `
const $c1$ = ["user", ""];
MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
type: MyComponent,
selectors: [["my-component"]],
decls: 3,
vars: 1,
consts: [["user", ""]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelement(0, "input", null, $c1$);
$r3$.ɵɵelement(0, "input", null, 0);
$r3$.ɵɵtext(2);
}
if (rf & 2) {
Expand Down Expand Up @@ -2292,9 +2291,6 @@ describe('compiler compliance', () => {
};

const MyComponentDefinition = `
const $c1$ = ["foo", ""];
const $c3$ = ["baz", ""];
const $c4$ = ["bar", ""];
function MyComponent_div_3_span_2_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "span");
Expand All @@ -2315,8 +2311,8 @@ describe('compiler compliance', () => {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "div");
$r3$.ɵɵtext(1);
$r3$.ɵɵtemplate(2, MyComponent_div_3_span_2_Template, 2, 3, "span", 0);
$r3$.ɵɵelement(3, "span", null, $c4$);
$r3$.ɵɵtemplate(2, MyComponent_div_3_span_2_Template, 2, 3, "span", 1);
$r3$.ɵɵelement(3, "span", null, 3);
$r3$.ɵɵelementEnd();
}
if (rf & 2) {
Expand All @@ -2333,13 +2329,13 @@ describe('compiler compliance', () => {
selectors: [["my-component"]],
decls: 6,
vars: 1,
consts: [[${AttributeMarker.Template}, "if"]],
consts: [["foo", ""], [${AttributeMarker.Template}, "if"], ["baz", ""], ["bar", ""]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelement(0, "div", null, $c1$);
$r3$.ɵɵelement(0, "div", null, 0);
$r3$.ɵɵtext(2);
$r3$.ɵɵtemplate(3, MyComponent_div_3_Template, 5, 2, "div", 0);
$r3$.ɵɵelement(4, "div", null, $c3$);
$r3$.ɵɵtemplate(3, MyComponent_div_3_Template, 5, 2, "div", 1);
$r3$.ɵɵelement(4, "div", null, 2);
}
if (rf & 2) {
const $foo$ = $r3$.ɵɵreference(1);
Expand Down Expand Up @@ -2381,8 +2377,6 @@ describe('compiler compliance', () => {
};

const template = `
const $c1$ = ["foo", ""];

function MyComponent_div_0_span_3_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵɵelementStart(0, "span");
Expand All @@ -2400,8 +2394,8 @@ describe('compiler compliance', () => {
function MyComponent_div_0_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵɵelementStart(0, "div");
$i0$.ɵɵelement(1, "div", null, $c1$);
$i0$.ɵɵtemplate(3, MyComponent_div_0_span_3_Template, 2, 2, "span", 1);
$i0$.ɵɵelement(1, "div", null, 1);
$i0$.ɵɵtemplate(3, MyComponent_div_0_span_3_Template, 2, 2, "span", 2);
$i0$.ɵɵelementEnd();
}
if (rf & 2) {
Expand All @@ -2412,7 +2406,7 @@ describe('compiler compliance', () => {
}

// ...
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Template}, "ngIf"]],
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], ["foo", ""], [${AttributeMarker.Template}, "ngIf"]],
template:function MyComponent_Template(rf, ctx){
if (rf & 1) {
$i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 4, 1, "div", 0);
Expand Down
Expand Up @@ -1251,12 +1251,11 @@ describe('compiler compliance: bindings', () => {
`);

const template = `
const $_c1$ = ["myRef", ""];
consts: [["id", "my-id"]],
consts: [["id", "my-id"], ["myRef", ""]],
template:function MyComponent_Template(rf, $ctx$){
if (rf & 1) {
$i0$.ɵɵelementStart(0, "b", 0, $_c1$);
$i0$.ɵɵelementStart(0, "b", 0, 1);
$i0$.ɵɵdisableBindings();
$i0$.ɵɵelementStart(2, "i");
$i0$.ɵɵtext(3, "Hello {{ name }}!");
Expand Down
Expand Up @@ -193,14 +193,13 @@ describe('compiler compliance: listen()', () => {
};

const MyComponentDefinition = `
const $e2_refs$ = ["user", ""];
MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
type: MyComponent,
selectors: [["my-component"]],
decls: 4,
vars: 0,
consts: [[${AttributeMarker.Bindings}, "click"]],
consts: [[${AttributeMarker.Bindings}, "click"], ["user", ""]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
const $s$ = $r3$.ɵɵgetCurrentView();
Expand All @@ -212,7 +211,7 @@ describe('compiler compliance: listen()', () => {
});
$r3$.ɵɵtext(1, "Save");
$r3$.ɵɵelementEnd();
$r3$.ɵɵelement(2, "input", null, $e2_refs$);
$r3$.ɵɵelement(2, "input", null, 1);
}
},
encapsulation: 2
Expand Down
Expand Up @@ -491,19 +491,17 @@ describe('compiler compliance: template', () => {
};

const template = `
const $t0_refs$ = ["foo", ""];
function MyComponent_ng_template_0_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵɵtext(0, "some-content");
}
}
// ...
consts: [["foo", ""]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", null, $t0_refs$, $i0$.ɵɵtemplateRefExtractor);
$i0$.ɵɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", null, 0, $i0$.ɵɵtemplateRefExtractor);
}
}`;

Expand Down
38 changes: 21 additions & 17 deletions packages/compiler/src/render3/view/template.ts
Expand Up @@ -606,10 +606,11 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// add attributes for directive and projection matching purposes
attributes.push(...this.prepareNonRenderAttrs(
allOtherInputs, element.outputs, stylingBuilder, [], i18nAttrs, ngProjectAsAttr));
parameters.push(this.addConstants(attributes));
parameters.push(this.addAttrsToConsts(attributes));

// local refs (ex.: <div #foo #bar="baz">)
parameters.push(this.prepareRefsParameter(element.references));
const refs = this.prepareRefsArray(element.references);
parameters.push(this.addToConsts(refs));

const wasInNamespace = this._namespace;
const currentNamespace = this.getNamespaceInstruction(namespaceKey);
Expand Down Expand Up @@ -869,11 +870,12 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
(a: t.TextAttribute) => { attrsExprs.push(asLiteral(a.name), asLiteral(a.value)); });
attrsExprs.push(...this.prepareNonRenderAttrs(
template.inputs, template.outputs, undefined, template.templateAttrs));
parameters.push(this.addConstants(attrsExprs));
parameters.push(this.addAttrsToConsts(attrsExprs));

// local refs (ex.: <ng-template #foo>)
if (template.references && template.references.length) {
parameters.push(this.prepareRefsParameter(template.references));
const refs = this.prepareRefsArray(template.references);
parameters.push(this.addToConsts(refs));
parameters.push(o.importExpr(R3.templateRefExtractor));
}

Expand Down Expand Up @@ -1294,24 +1296,26 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
return attrExprs;
}

private addConstants(constExprs: o.Expression[]): o.LiteralExpr {
if (constExprs.length > 0) {
const literal = o.literalArr(constExprs);
private addToConsts(expression: o.Expression): o.LiteralExpr {
if (o.isNull(expression)) {
return o.TYPED_NULL_EXPR;
}

// Try to reuse a literal that's already in the array, if possible.
for (let i = 0; i < this._constants.length; i++) {
if (this._constants[i].isEquivalent(literal)) {
return o.literal(i);
}
// Try to reuse a literal that's already in the array, if possible.
for (let i = 0; i < this._constants.length; i++) {
if (this._constants[i].isEquivalent(expression)) {
return o.literal(i);
}

return o.literal(this._constants.push(literal) - 1);
}

return o.TYPED_NULL_EXPR;
return o.literal(this._constants.push(expression) - 1);
}

private addAttrsToConsts(attrs: o.Expression[]): o.LiteralExpr {
return attrs.length > 0 ? this.addToConsts(o.literalArr(attrs)) : o.TYPED_NULL_EXPR;
}

private prepareRefsParameter(references: t.Reference[]): o.Expression {
private prepareRefsArray(references: t.Reference[]): o.Expression {
if (!references || references.length === 0) {
return o.TYPED_NULL_EXPR;
}
Expand All @@ -1336,7 +1340,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
return [reference.name, reference.value];
}));

return this.constantPool.getConstLiteral(asLiteral(refsParam), true);
return asLiteral(refsParam);
}

private prepareListenerParameter(tagName: string, outputAst: t.BoundEvent, index: number):
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/render3/definition.ts
Expand Up @@ -18,7 +18,7 @@ import {stringify} from '../util/stringify';
import {EMPTY_ARRAY, EMPTY_OBJ} from './empty';
import {NG_COMP_DEF, NG_DIR_DEF, NG_FACTORY_DEF, NG_LOC_ID_DEF, NG_MOD_DEF, NG_PIPE_DEF} from './fields';
import {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, ContentQueriesFunction, DirectiveDef, DirectiveDefFeature, DirectiveTypesOrFactory, FactoryFn, HostBindingsFunction, PipeDef, PipeType, PipeTypesOrFactory, ViewQueriesFunction} from './interfaces/definition';
import {TAttributes} from './interfaces/node';
import {TConstants} from './interfaces/node';
// while SelectorFlags is unused here, it's required so that types don't get resolved lazily
// see: https://github.com/Microsoft/web-build-tools/issues/1050
import {CssSelectorList, SelectorFlags} from './interfaces/projection';
Expand Down Expand Up @@ -172,8 +172,11 @@ export function ɵɵdefineComponent<T>(componentDefinition: {
*/
template: ComponentTemplate<T>;

/** Constants for the nodes in the component's view. */
consts?: TAttributes[];
/**
* Constants for the nodes in the component's view.
* Includes attribute arrays, local definition arrays etc.
*/
consts?: TConstants;

/**
* An array of `ngContent[selector]` values that were found in the template.
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/render3/instructions/container.ts
Expand Up @@ -17,7 +17,7 @@ import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW
import {assertNodeType} from '../node_assert';
import {appendChild, removeView} from '../node_manipulation';
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {load} from '../util/view_utils';
import {getConstant, load} from '../util/view_utils';

import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';

Expand Down Expand Up @@ -56,28 +56,28 @@ export function ɵɵcontainer(index: number): void {
* @param decls The number of nodes, local refs, and pipes for this template
* @param vars The number of bindings for this template
* @param tagName The name of the container element, if applicable
* @param constsIndex Index of template in the `consts` array.
* @param localRefs A set of local reference bindings on the element.
* @param attrsIndex Index of template attributes in the `consts` array.
* @param localRefs Index of the local references in the `consts` array.
* @param localRefExtractor A function which extracts local-refs values from the template.
* Defaults to the current element associated with the local-ref.
*
* @codeGenApi
*/
export function ɵɵtemplate(
index: number, templateFn: ComponentTemplate<any>| null, decls: number, vars: number,
tagName?: string | null, constsIndex?: number | null, localRefs?: string[] | null,
tagName?: string | null, attrsIndex?: number | null, localRefsIndex?: number | null,
localRefExtractor?: LocalRefExtractor) {
const lView = getLView();
const tView = lView[TVIEW];
const tViewConsts = tView.consts;

// TODO: consider a separate node type for templates
const tContainerNode = containerInternal(
lView, index, tagName || null,
tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex]);
lView, index, tagName || null, getConstant(tViewConsts, attrsIndex) as TAttributes);
const localRefs = getConstant(tViewConsts, localRefsIndex) as string[];
if (tView.firstTemplatePass) {
ngDevMode && ngDevMode.firstTemplatePass++;
resolveDirectives(tView, lView, tContainerNode, localRefs || null);
resolveDirectives(tView, lView, tContainerNode, localRefs);
registerPostOrderHooks(tView, tContainerNode);

const embeddedTView = tContainerNode.tViews = createTView(
Expand Down