Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
perf(ivy): move local references into consts array (#33129)
Follow-up from #32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```

PR Close #33129
  • Loading branch information
crisbeto authored and atscott committed Nov 4, 2019
1 parent 5437e2d commit 66725b7
Show file tree
Hide file tree
Showing 22 changed files with 245 additions and 207 deletions.
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

0 comments on commit 66725b7

Please sign in to comment.