More critical path optimization in binder

This commit is contained in:
Anders Hejlsberg 2016-05-29 16:04:34 -07:00
parent 66e9f7dc21
commit 5b4dffc2d7

View file

@ -1556,15 +1556,9 @@ namespace ts {
if (!node) { if (!node) {
return; return;
} }
node.parent = parent; node.parent = parent;
const saveInStrictMode = inStrictMode; const saveInStrictMode = inStrictMode;
if (!saveInStrictMode) { // First we bind declaration nodes to a symbol if possible. We'll both create a symbol
updateStrictMode(node);
}
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
// and then potentially add the symbol to an appropriate symbol table. Possible // and then potentially add the symbol to an appropriate symbol table. Possible
// destination symbol tables are: // destination symbol tables are:
// //
@ -1572,56 +1566,40 @@ namespace ts {
// 2) The 'members' table of the current container's symbol. // 2) The 'members' table of the current container's symbol.
// 3) The 'locals' table of the current container. // 3) The 'locals' table of the current container.
// //
// However, not all symbols will end up in any of these tables. 'Anonymous' symbols // However, not all symbols will end up in any of these tables. 'Anonymous' symbols
// (like TypeLiterals for example) will not be put in any table. // (like TypeLiterals for example) will not be put in any table.
bindWorker(node); bindWorker(node);
// Then we recurse into the children of the node to bind them as well. For certain
// Then we recurse into the children of the node to bind them as well. For certain // symbols we do specialized work when we recurse. For example, we'll keep track of
// symbols we do specialized work when we recurse. For example, we'll keep track of // the current 'container' node when it changes. This helps us know which symbol table
// the current 'container' node when it changes. This helps us know which symbol table // a local should go into for example. Since terminal nodes are known not to have
// a local should go into for example. // children, as an optimization we don't process those.
const saveParent = parent; if (node.kind > SyntaxKind.LastToken) {
parent = node; const saveParent = parent;
const containerFlags = getContainerFlags(node); parent = node;
if (containerFlags === ContainerFlags.None) { const containerFlags = getContainerFlags(node);
bindChildren(node); if (containerFlags === ContainerFlags.None) {
bindChildren(node);
}
else {
bindContainer(node, containerFlags);
}
parent = saveParent;
} }
else {
bindContainer(node, containerFlags);
}
parent = saveParent;
inStrictMode = saveInStrictMode; inStrictMode = saveInStrictMode;
} }
function updateStrictMode(node: Node) {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.ModuleBlock:
updateStrictModeStatementList((<SourceFile | ModuleBlock>node).statements);
return;
case SyntaxKind.Block:
if (isFunctionLike(node.parent)) {
updateStrictModeStatementList((<Block>node).statements);
}
return;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
// All classes are automatically in strict mode in ES6.
inStrictMode = true;
return;
}
}
function updateStrictModeStatementList(statements: NodeArray<Statement>) { function updateStrictModeStatementList(statements: NodeArray<Statement>) {
for (const statement of statements) { if (!inStrictMode) {
if (!isPrologueDirective(statement)) { for (const statement of statements) {
return; if (!isPrologueDirective(statement)) {
} return;
}
if (isUseStrictPrologueDirective(<ExpressionStatement>statement)) { if (isUseStrictPrologueDirective(<ExpressionStatement>statement)) {
inStrictMode = true; inStrictMode = true;
return; return;
}
} }
} }
} }
@ -1753,6 +1731,8 @@ namespace ts {
// Members of classes, interfaces, and modules // Members of classes, interfaces, and modules
case SyntaxKind.ClassExpression: case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassDeclaration:
// All classes are automatically in strict mode in ES6.
inStrictMode = true;
return bindClassLikeDeclaration(<ClassLikeDeclaration>node); return bindClassLikeDeclaration(<ClassLikeDeclaration>node);
case SyntaxKind.InterfaceDeclaration: case SyntaxKind.InterfaceDeclaration:
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
@ -1778,7 +1758,15 @@ namespace ts {
case SyntaxKind.ExportAssignment: case SyntaxKind.ExportAssignment:
return bindExportAssignment(<ExportAssignment>node); return bindExportAssignment(<ExportAssignment>node);
case SyntaxKind.SourceFile: case SyntaxKind.SourceFile:
updateStrictModeStatementList((<SourceFile>node).statements);
return bindSourceFileIfExternalModule(); return bindSourceFileIfExternalModule();
case SyntaxKind.Block:
if (!isFunctionLike(node.parent)) {
return;
}
// Fall through
case SyntaxKind.ModuleBlock:
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);
} }
} }