perf(compiler): Avoid unnecessary List concats
Update `BindingRecordsCreator#getBindingRecords` and `ProtoRecordBuilder#addAst` to avoid unnecessary calls to `ListWrapper.concat`. Closes #1905
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import {isPresent, isBlank, BaseException, Type, isString} from 'angular2/src/facade/lang';
|
import {BaseException, Type, isBlank, isPresent, isString} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -109,37 +109,30 @@ class ProtoRecordBuilder {
|
|||||||
constructor() { this.records = []; }
|
constructor() { this.records = []; }
|
||||||
|
|
||||||
addAst(b: BindingRecord, variableNames: List < string >= null) {
|
addAst(b: BindingRecord, variableNames: List < string >= null) {
|
||||||
var last = ListWrapper.last(this.records);
|
var oldLast = ListWrapper.last(this.records);
|
||||||
if (isPresent(last) && last.bindingRecord.directiveRecord == b.directiveRecord) {
|
if (isPresent(oldLast) && oldLast.bindingRecord.directiveRecord == b.directiveRecord) {
|
||||||
last.lastInDirective = false;
|
oldLast.lastInDirective = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pr = _ConvertAstIntoProtoRecords.convert(b, this.records.length, variableNames);
|
_ConvertAstIntoProtoRecords.append(this.records, b, variableNames);
|
||||||
if (!ListWrapper.isEmpty(pr)) {
|
var newLast = ListWrapper.last(this.records);
|
||||||
var last = ListWrapper.last(pr);
|
if (isPresent(newLast) && newLast !== oldLast) {
|
||||||
last.lastInBinding = true;
|
newLast.lastInBinding = true;
|
||||||
last.lastInDirective = true;
|
newLast.lastInDirective = true;
|
||||||
|
|
||||||
this.records = ListWrapper.concat(this.records, pr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ConvertAstIntoProtoRecords {
|
class _ConvertAstIntoProtoRecords {
|
||||||
protoRecords: List<any>;
|
constructor(private _records: List<ProtoRecord>, private _bindingRecord: BindingRecord,
|
||||||
|
private _expressionAsString: string, private _variableNames: List<any>) {}
|
||||||
|
|
||||||
constructor(private bindingRecord: BindingRecord, private contextIndex: number,
|
static append(records: List<ProtoRecord>, b: BindingRecord, variableNames: List<any>) {
|
||||||
private expressionAsString: string, private variableNames: List<any>) {
|
var c = new _ConvertAstIntoProtoRecords(records, b, b.ast.toString(), variableNames);
|
||||||
this.protoRecords = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static convert(b: BindingRecord, contextIndex: number, variableNames: List<any>) {
|
|
||||||
var c = new _ConvertAstIntoProtoRecords(b, contextIndex, b.ast.toString(), variableNames);
|
|
||||||
b.ast.visit(c);
|
b.ast.visit(c);
|
||||||
return c.protoRecords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visitImplicitReceiver(ast: ImplicitReceiver) { return this.bindingRecord.implicitReceiver; }
|
visitImplicitReceiver(ast: ImplicitReceiver) { return this._bindingRecord.implicitReceiver; }
|
||||||
|
|
||||||
visitInterpolation(ast: Interpolation) {
|
visitInterpolation(ast: Interpolation) {
|
||||||
var args = this._visitAll(ast.expressions);
|
var args = this._visitAll(ast.expressions);
|
||||||
@ -153,7 +146,7 @@ class _ConvertAstIntoProtoRecords {
|
|||||||
|
|
||||||
visitAccessMember(ast: AccessMember) {
|
visitAccessMember(ast: AccessMember) {
|
||||||
var receiver = ast.receiver.visit(this);
|
var receiver = ast.receiver.visit(this);
|
||||||
if (isPresent(this.variableNames) && ListWrapper.contains(this.variableNames, ast.name) &&
|
if (isPresent(this._variableNames) && ListWrapper.contains(this._variableNames, ast.name) &&
|
||||||
ast.receiver instanceof
|
ast.receiver instanceof
|
||||||
ImplicitReceiver) {
|
ImplicitReceiver) {
|
||||||
return this._addRecord(RECORD_TYPE_LOCAL, ast.name, ast.name, [], null, receiver);
|
return this._addRecord(RECORD_TYPE_LOCAL, ast.name, ast.name, [], null, receiver);
|
||||||
@ -163,10 +156,9 @@ class _ConvertAstIntoProtoRecords {
|
|||||||
}
|
}
|
||||||
|
|
||||||
visitMethodCall(ast: MethodCall) {
|
visitMethodCall(ast: MethodCall) {
|
||||||
;
|
|
||||||
var receiver = ast.receiver.visit(this);
|
var receiver = ast.receiver.visit(this);
|
||||||
var args = this._visitAll(ast.args);
|
var args = this._visitAll(ast.args);
|
||||||
if (isPresent(this.variableNames) && ListWrapper.contains(this.variableNames, ast.name)) {
|
if (isPresent(this._variableNames) && ListWrapper.contains(this._variableNames, ast.name)) {
|
||||||
var target = this._addRecord(RECORD_TYPE_LOCAL, ast.name, ast.name, [], null, receiver);
|
var target = this._addRecord(RECORD_TYPE_LOCAL, ast.name, ast.name, [], null, receiver);
|
||||||
return this._addRecord(RECORD_TYPE_INVOKE_CLOSURE, "closure", null, args, null, target);
|
return this._addRecord(RECORD_TYPE_INVOKE_CLOSURE, "closure", null, args, null, target);
|
||||||
} else {
|
} else {
|
||||||
@ -236,17 +228,15 @@ class _ConvertAstIntoProtoRecords {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_addRecord(type, name, funcOrValue, args, fixedArgs, context) {
|
_addRecord(type, name, funcOrValue, args, fixedArgs, context) {
|
||||||
var selfIndex = ++this.contextIndex;
|
var selfIndex = this._records.length + 1;
|
||||||
if (context instanceof DirectiveIndex) {
|
if (context instanceof DirectiveIndex) {
|
||||||
ListWrapper.push(
|
ListWrapper.push(this._records, new ProtoRecord(type, name, funcOrValue, args, fixedArgs, -1,
|
||||||
this.protoRecords,
|
context, selfIndex, this._bindingRecord,
|
||||||
new ProtoRecord(type, name, funcOrValue, args, fixedArgs, -1, context, selfIndex,
|
this._expressionAsString, false, false));
|
||||||
this.bindingRecord, this.expressionAsString, false, false));
|
|
||||||
} else {
|
} else {
|
||||||
ListWrapper.push(
|
ListWrapper.push(this._records, new ProtoRecord(type, name, funcOrValue, args, fixedArgs,
|
||||||
this.protoRecords,
|
context, null, selfIndex, this._bindingRecord,
|
||||||
new ProtoRecord(type, name, funcOrValue, args, fixedArgs, context, null, selfIndex,
|
this._expressionAsString, false, false));
|
||||||
this.bindingRecord, this.expressionAsString, false, false));
|
|
||||||
}
|
}
|
||||||
return selfIndex;
|
return selfIndex;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,10 @@ class BindingRecordsCreator {
|
|||||||
|
|
||||||
for (var boundElementIndex = 0; boundElementIndex < elementBinders.length; boundElementIndex++) {
|
for (var boundElementIndex = 0; boundElementIndex < elementBinders.length; boundElementIndex++) {
|
||||||
var renderElementBinder = elementBinders[boundElementIndex];
|
var renderElementBinder = elementBinders[boundElementIndex];
|
||||||
bindings = ListWrapper.concat(bindings, this._createTextNodeRecords(renderElementBinder));
|
this._createTextNodeRecords(bindings, renderElementBinder);
|
||||||
bindings = ListWrapper.concat(bindings, this._createElementPropertyRecords(boundElementIndex, renderElementBinder));
|
this._createElementPropertyRecords(bindings, boundElementIndex, renderElementBinder);
|
||||||
bindings = ListWrapper.concat(bindings, this._createDirectiveRecords(boundElementIndex,
|
this._createDirectiveRecords(bindings, boundElementIndex,
|
||||||
renderElementBinder.directives, allDirectiveMetadatas));
|
renderElementBinder.directives, allDirectiveMetadatas);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings;
|
return bindings;
|
||||||
@ -46,29 +46,35 @@ class BindingRecordsCreator {
|
|||||||
for (var elementIndex = 0; elementIndex < elementBinders.length; ++elementIndex) {
|
for (var elementIndex = 0; elementIndex < elementBinders.length; ++elementIndex) {
|
||||||
var dirs = elementBinders[elementIndex].directives;
|
var dirs = elementBinders[elementIndex].directives;
|
||||||
for (var dirIndex = 0; dirIndex < dirs.length; ++dirIndex) {
|
for (var dirIndex = 0; dirIndex < dirs.length; ++dirIndex) {
|
||||||
ListWrapper.push(directiveRecords, this._getDirectiveRecord(elementIndex, dirIndex, allDirectiveMetadatas[dirs[dirIndex].directiveIndex]));
|
ListWrapper.push(directiveRecords,
|
||||||
|
this._getDirectiveRecord(
|
||||||
|
elementIndex, dirIndex, allDirectiveMetadatas[dirs[dirIndex].directiveIndex]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return directiveRecords;
|
return directiveRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTextNodeRecords(renderElementBinder:renderApi.ElementBinder) {
|
_createTextNodeRecords(bindings: List<BindingRecord>,
|
||||||
if (isBlank(renderElementBinder.textBindings)) return [];
|
renderElementBinder: renderApi.ElementBinder) {
|
||||||
return ListWrapper.map(renderElementBinder.textBindings, b => BindingRecord.createForTextNode(b, this._textNodeIndex++));
|
if (isBlank(renderElementBinder.textBindings)) return;
|
||||||
}
|
|
||||||
|
|
||||||
_createElementPropertyRecords(boundElementIndex:number, renderElementBinder:renderApi.ElementBinder) {
|
ListWrapper.forEach(renderElementBinder.textBindings, (b) => {
|
||||||
var res = [];
|
ListWrapper.push(bindings, BindingRecord.createForTextNode(b, this._textNodeIndex++));
|
||||||
MapWrapper.forEach(renderElementBinder.propertyBindings, (astWithSource, propertyName) => {
|
|
||||||
ListWrapper.push(res, BindingRecord.createForElement(astWithSource, boundElementIndex, propertyName));
|
|
||||||
});
|
});
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createDirectiveRecords(boundElementIndex:number, directiveBinders:List<renderApi.DirectiveBinder>,
|
_createElementPropertyRecords(bindings: List<BindingRecord>,
|
||||||
|
boundElementIndex:number, renderElementBinder:renderApi.ElementBinder) {
|
||||||
|
MapWrapper.forEach(renderElementBinder.propertyBindings, (astWithSource, propertyName) => {
|
||||||
|
ListWrapper.push(bindings,
|
||||||
|
BindingRecord.createForElement(astWithSource, boundElementIndex, propertyName));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_createDirectiveRecords(bindings: List<BindingRecord>,
|
||||||
|
boundElementIndex:number, directiveBinders:List<renderApi.DirectiveBinder>,
|
||||||
allDirectiveMetadatas:List<renderApi.DirectiveMetadata>) {
|
allDirectiveMetadatas:List<renderApi.DirectiveMetadata>) {
|
||||||
var res = [];
|
|
||||||
for (var i = 0; i < directiveBinders.length; i++) {
|
for (var i = 0; i < directiveBinders.length; i++) {
|
||||||
var directiveBinder = directiveBinders[i];
|
var directiveBinder = directiveBinders[i];
|
||||||
var directiveMetadata = allDirectiveMetadatas[directiveBinder.directiveIndex];
|
var directiveMetadata = allDirectiveMetadatas[directiveBinder.directiveIndex];
|
||||||
@ -79,18 +85,17 @@ class BindingRecordsCreator {
|
|||||||
// it monomorphic!
|
// it monomorphic!
|
||||||
var setter = reflector.setter(propertyName);
|
var setter = reflector.setter(propertyName);
|
||||||
var directiveRecord = this._getDirectiveRecord(boundElementIndex, i, directiveMetadata);
|
var directiveRecord = this._getDirectiveRecord(boundElementIndex, i, directiveMetadata);
|
||||||
var b = BindingRecord.createForDirective(astWithSource, propertyName, setter, directiveRecord);
|
ListWrapper.push(bindings,
|
||||||
ListWrapper.push(res, b);
|
BindingRecord.createForDirective(astWithSource, propertyName, setter, directiveRecord));
|
||||||
});
|
});
|
||||||
|
|
||||||
// host properties
|
// host properties
|
||||||
MapWrapper.forEach(directiveBinder.hostPropertyBindings, (astWithSource, propertyName) => {
|
MapWrapper.forEach(directiveBinder.hostPropertyBindings, (astWithSource, propertyName) => {
|
||||||
var dirIndex = new DirectiveIndex(boundElementIndex, i);
|
var dirIndex = new DirectiveIndex(boundElementIndex, i);
|
||||||
var b = BindingRecord.createForHostProperty(dirIndex, astWithSource, propertyName);
|
ListWrapper.push(bindings,
|
||||||
ListWrapper.push(res, b);
|
BindingRecord.createForHostProperty(dirIndex, astWithSource, propertyName));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_getDirectiveRecord(boundElementIndex:number, directiveIndex:number, directiveMetadata:renderApi.DirectiveMetadata): DirectiveRecord {
|
_getDirectiveRecord(boundElementIndex:number, directiveIndex:number, directiveMetadata:renderApi.DirectiveMetadata): DirectiveRecord {
|
||||||
|
Reference in New Issue
Block a user