perf(ivy): replace select instruction with advance (#32516)

Replaces the `select` instruction with a new one called `advance`. Instead of the jumping to a specific index, the new instruction goes forward X amount of elements. The advantage of doing this is that it should generate code the compresses better.

PR Close #32516
This commit is contained in:
crisbeto
2019-09-06 23:43:16 +02:00
committed by Matias Niemelä
parent 2230dfaea7
commit 664e0015d4
34 changed files with 280 additions and 304 deletions

View File

@ -92,7 +92,7 @@ GreetComponent.ngComponentDef = i0.ɵɵdefineComponent({
i0.ɵɵelementEnd();
}
if (rf & RenderFlags.Update) {
i0.ɵɵselect(1);
i0.ɵɵadvance(1);
i0.ɵɵtextInterpolate1('Hello ', ctx.name, '!');
}
}

View File

@ -30,6 +30,7 @@ export class Identifiers {
static elementEnd: o.ExternalReference = {name: 'ɵɵelementEnd', moduleName: CORE};
static select: o.ExternalReference = {name: 'ɵɵselect', moduleName: CORE};
static advance: o.ExternalReference = {name: 'ɵɵadvance', moduleName: CORE};
static updateSyntheticHostBinding:
o.ExternalReference = {name: 'ɵɵupdateSyntheticHostBinding', moduleName: CORE};

View File

@ -114,12 +114,10 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
* all local refs and context variables are available for matching.
*/
private _updateCodeFns: (() => o.Statement)[] = [];
/**
* Memorizes the last node index for which a select instruction has been generated.
* We're initializing this to -1 to ensure the `select(0)` instruction is generated before any
* relevant update instructions.
*/
private _lastNodeIndexWithFlush: number = -1;
/** Index of the currently-selected node. */
private _currentIndex: number = 0;
/** Temporary variable declarations generated from visiting pipes, literals, etc. */
private _tempVariables: o.Statement[] = [];
/**
@ -457,8 +455,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
bindings.forEach(binding => {
chainBindings.push({sourceSpan: span, value: () => this.convertPropertyBinding(binding)});
});
this.updateInstructionChain(index, R3.i18nExp, chainBindings);
this.updateInstruction(index, span, R3.i18nApply, [o.literal(index)]);
this.updateInstructionChain(R3.i18nExp, chainBindings);
this.updateInstruction(span, R3.i18nApply, [o.literal(index)]);
}
if (!selfClosing) {
this.creationInstruction(span, R3.i18nEnd);
@ -489,7 +487,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
private interpolatedUpdateInstruction(
instruction: o.ExternalReference, elementIndex: number, attrName: string,
input: t.BoundAttribute, value: any, params: any[]) {
this.updateInstruction(
this.updateInstructionWithAdvance(
elementIndex, input.sourceSpan, instruction,
() => [o.literal(attrName), ...this.getUpdateInstructionArguments(value), ...params]);
}
@ -671,14 +669,14 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
}
});
if (bindings.length) {
this.updateInstructionChain(elementIndex, R3.i18nExp, bindings);
this.updateInstructionChain(R3.i18nExp, bindings);
}
if (i18nAttrArgs.length) {
const index: o.Expression = o.literal(this.allocateDataSlot());
const args = this.constantPool.getConstLiteral(o.literalArr(i18nAttrArgs), true);
this.creationInstruction(element.sourceSpan, R3.i18nAttributes, [index, args]);
if (hasBindings) {
this.updateInstruction(elementIndex, element.sourceSpan, R3.i18nApply, [index]);
this.updateInstruction(element.sourceSpan, R3.i18nApply, [index]);
}
}
}
@ -806,7 +804,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
}
} else {
// class prop
this.updateInstruction(elementIndex, input.sourceSpan, R3.classProp, () => {
this.updateInstructionWithAdvance(elementIndex, input.sourceSpan, R3.classProp, () => {
return [
o.literal(elementIndex), o.literal(attrName), this.convertPropertyBinding(value),
...params
@ -818,11 +816,11 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
});
if (propertyBindings.length > 0) {
this.updateInstructionChain(elementIndex, R3.property, propertyBindings);
this.updateInstructionChainWithAdvance(elementIndex, R3.property, propertyBindings);
}
if (attributeBindings.length > 0) {
this.updateInstructionChain(elementIndex, R3.attribute, attributeBindings);
this.updateInstructionChainWithAdvance(elementIndex, R3.attribute, attributeBindings);
}
// Traverse element child nodes
@ -954,7 +952,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this.allocateBindingSlots(value);
if (value instanceof Interpolation) {
this.updateInstruction(
this.updateInstructionWithAdvance(
nodeIndex, text.sourceSpan, getTextInterpolationExpression(value),
() => this.getUpdateInstructionArguments(value));
} else {
@ -1054,7 +1052,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
});
if (propertyBindings.length > 0) {
this.updateInstructionChain(templateIndex, R3.property, propertyBindings);
this.updateInstructionChainWithAdvance(templateIndex, R3.property, propertyBindings);
}
}
@ -1079,14 +1077,15 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
return instruction.params(value => this.convertPropertyBinding(value)) as o.Expression[];
});
} else {
this.updateInstruction(elementIndex, instruction.sourceSpan, instruction.reference, () => {
return instruction
.params(value => {
return (instruction.supportsInterpolation && value instanceof Interpolation) ?
this.getUpdateInstructionArguments(value) :
this.convertPropertyBinding(value);
}) as o.Expression[];
});
this.updateInstructionWithAdvance(
elementIndex, instruction.sourceSpan, instruction.reference, () => {
return instruction
.params(value => {
return (instruction.supportsInterpolation && value instanceof Interpolation) ?
this.getUpdateInstructionArguments(value) :
this.convertPropertyBinding(value);
}) as o.Expression[];
});
}
}
}
@ -1097,18 +1096,23 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this.instructionFn(this._creationCodeFns, span, reference, paramsOrFn || [], prepend);
}
private updateInstruction(
private updateInstructionWithAdvance(
nodeIndex: number, span: ParseSourceSpan|null, reference: o.ExternalReference,
paramsOrFn?: o.Expression[]|(() => o.Expression[])) {
this.addSelectInstructionIfNecessary(nodeIndex, span);
this.addAdvanceInstructionIfNecessary(nodeIndex, span);
this.updateInstruction(span, reference, paramsOrFn);
}
private updateInstruction(
span: ParseSourceSpan|null, reference: o.ExternalReference,
paramsOrFn?: o.Expression[]|(() => o.Expression[])) {
this.instructionFn(this._updateCodeFns, span, reference, paramsOrFn || []);
}
private updateInstructionChain(
nodeIndex: number, reference: o.ExternalReference, bindings: ChainableBindingInstruction[]) {
reference: o.ExternalReference, bindings: ChainableBindingInstruction[]) {
const span = bindings.length ? bindings[0].sourceSpan : null;
this.addSelectInstructionIfNecessary(nodeIndex, span);
this._updateCodeFns.push(() => {
const calls = bindings.map(property => {
const fnParams = [property.value(), ...(property.params || [])];
@ -1122,12 +1126,23 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
});
}
private addSelectInstructionIfNecessary(nodeIndex: number, span: ParseSourceSpan|null) {
if (this._lastNodeIndexWithFlush < nodeIndex) {
if (nodeIndex > 0) {
this.instructionFn(this._updateCodeFns, span, R3.select, [o.literal(nodeIndex)]);
private updateInstructionChainWithAdvance(
nodeIndex: number, reference: o.ExternalReference, bindings: ChainableBindingInstruction[]) {
this.addAdvanceInstructionIfNecessary(
nodeIndex, bindings.length ? bindings[0].sourceSpan : null);
this.updateInstructionChain(reference, bindings);
}
private addAdvanceInstructionIfNecessary(nodeIndex: number, span: ParseSourceSpan|null) {
if (nodeIndex !== this._currentIndex) {
const delta = nodeIndex - this._currentIndex;
if (delta < 1) {
throw new Error('advance instruction can only go forwards');
}
this._lastNodeIndexWithFlush = nodeIndex;
this.instructionFn(this._updateCodeFns, span, R3.advance, [o.literal(delta)]);
this._currentIndex = nodeIndex;
}
}
@ -2037,4 +2052,4 @@ export function getTranslationDeclStmts(
}
return statements;
}
}