Skip to content

Commit 2779352

Browse files
committed
make binder singleton, inline bindWithReachabilityChecks
1 parent f96980d commit 2779352

File tree

2 files changed

+73
-48
lines changed

2 files changed

+73
-48
lines changed

src/compiler/binder.ts

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ namespace ts {
9292
IsContainerWithLocals = IsContainer | HasLocals
9393
}
9494

95+
const binder = createBinder();
96+
9597
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
9698
let start = new Date().getTime();
97-
bindSourceFileWorker(file, options);
99+
binder(file, options);
98100
bindTime += new Date().getTime() - start;
99101
}
100102

101-
function bindSourceFileWorker(file: SourceFile, options: CompilerOptions) {
103+
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
104+
let file: SourceFile;
105+
let options: CompilerOptions;
102106
let parent: Node;
103107
let container: Node;
104108
let blockScopeContainer: Node;
@@ -115,19 +119,37 @@ namespace ts {
115119
// If this file is an external module, then it is automatically in strict-mode according to
116120
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
117121
// not depending on if we see "use strict" in certain places (or if we hit a class/namespace).
118-
let inStrictMode = !!file.externalModuleIndicator;
122+
let inStrictMode: boolean;
119123

120124
let symbolCount = 0;
121-
let Symbol = objectAllocator.getSymbolConstructor();
122-
let classifiableNames: Map<string> = {};
125+
let Symbol: { new (flags: SymbolFlags, name: string): Symbol };
126+
let classifiableNames: Map<string>;
127+
128+
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
129+
file = f;
130+
options = opts;
131+
inStrictMode = !!file.externalModuleIndicator;
132+
classifiableNames = {};
133+
Symbol = objectAllocator.getSymbolConstructor();
134+
135+
if (!file.locals) {
136+
bind(file);
137+
file.symbolCount = symbolCount;
138+
file.classifiableNames = classifiableNames;
139+
}
123140

124-
if (!file.locals) {
125-
bind(file);
126-
file.symbolCount = symbolCount;
127-
file.classifiableNames = classifiableNames;
141+
parent = undefined;
142+
container = undefined;
143+
blockScopeContainer = undefined;
144+
lastContainer = undefined;
145+
seenThisKeyword = false;
146+
hasExplicitReturn = false;
147+
labelStack = undefined;
148+
labelIndexMap = undefined;
149+
implicitLabels = undefined;
128150
}
129151

130-
return;
152+
return bindSourceFile;
131153

132154
function createSymbol(flags: SymbolFlags, name: string): Symbol {
133155
symbolCount++;
@@ -360,31 +382,23 @@ namespace ts {
360382
blockScopeContainer.locals = undefined;
361383
}
362384

363-
if (node.kind === SyntaxKind.InterfaceDeclaration) {
364-
seenThisKeyword = false;
365-
bindWithReachabilityChecks(node);
366-
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
367-
}
368-
else {
369-
bindWithReachabilityChecks(node);
370-
}
371-
372-
container = saveContainer;
373-
parent = saveParent;
374-
blockScopeContainer = savedBlockScopeContainer;
375-
}
376-
377-
function bindWithReachabilityChecks(node: Node): void {
378385
let savedReachabilityState: Reachability;
379386
let savedLabelStack: Reachability[];
380387
let savedLabels: Map<number>;
381388
let savedImplicitLabels: number[];
382389
let savedHasExplicitReturn: boolean;
383390

391+
const kind = node.kind;
392+
let flags = node.flags;
393+
384394
// reset all reachability check related flags on node (for incremental scenarios)
385-
node.flags &= ~NodeFlags.ReachabilityCheckFlags;
395+
flags &= ~NodeFlags.ReachabilityCheckFlags;
396+
397+
if (kind === SyntaxKind.InterfaceDeclaration) {
398+
seenThisKeyword = false;
399+
}
386400

387-
let saveState = node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleBlock || isFunctionLike(node);
401+
let saveState = kind === SyntaxKind.SourceFile || kind === SyntaxKind.ModuleBlock || isFunctionLikeKind(kind);
388402
if (saveState) {
389403
savedReachabilityState = currentReachabilityState;
390404
savedLabelStack = labelStack;
@@ -399,20 +413,30 @@ namespace ts {
399413

400414
bindReachableStatement(node);
401415

402-
if (currentReachabilityState === Reachability.Reachable && isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
403-
node.flags |= NodeFlags.HasImplicitReturn;
416+
if (currentReachabilityState === Reachability.Reachable && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
417+
flags |= NodeFlags.HasImplicitReturn;
404418
if (hasExplicitReturn) {
405-
node.flags |= NodeFlags.HasExplicitReturn;
419+
flags |= NodeFlags.HasExplicitReturn;
406420
}
407421
}
408422

423+
if (kind === SyntaxKind.InterfaceDeclaration) {
424+
flags = seenThisKeyword ? flags | NodeFlags.ContainsThis : flags & ~NodeFlags.ContainsThis;
425+
}
426+
427+
node.flags = flags;
428+
409429
if (saveState) {
410430
hasExplicitReturn = savedHasExplicitReturn;
411431
currentReachabilityState = savedReachabilityState;
412432
labelStack = savedLabelStack;
413433
labelIndexMap = savedLabels;
414434
implicitLabels = savedImplicitLabels;
415435
}
436+
437+
container = saveContainer;
438+
parent = saveParent;
439+
blockScopeContainer = savedBlockScopeContainer;
416440
}
417441

418442
/**

src/compiler/utilities.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -622,25 +622,26 @@ namespace ts {
622622
}
623623

624624
export function isFunctionLike(node: Node): node is FunctionLikeDeclaration {
625-
if (node) {
626-
switch (node.kind) {
627-
case SyntaxKind.Constructor:
628-
case SyntaxKind.FunctionExpression:
629-
case SyntaxKind.FunctionDeclaration:
630-
case SyntaxKind.ArrowFunction:
631-
case SyntaxKind.MethodDeclaration:
632-
case SyntaxKind.MethodSignature:
633-
case SyntaxKind.GetAccessor:
634-
case SyntaxKind.SetAccessor:
635-
case SyntaxKind.CallSignature:
636-
case SyntaxKind.ConstructSignature:
637-
case SyntaxKind.IndexSignature:
638-
case SyntaxKind.FunctionType:
639-
case SyntaxKind.ConstructorType:
640-
return true;
641-
}
625+
return node && isFunctionLikeKind(node.kind);
626+
}
627+
628+
export function isFunctionLikeKind(kind: SyntaxKind): boolean {
629+
switch (kind) {
630+
case SyntaxKind.Constructor:
631+
case SyntaxKind.FunctionExpression:
632+
case SyntaxKind.FunctionDeclaration:
633+
case SyntaxKind.ArrowFunction:
634+
case SyntaxKind.MethodDeclaration:
635+
case SyntaxKind.MethodSignature:
636+
case SyntaxKind.GetAccessor:
637+
case SyntaxKind.SetAccessor:
638+
case SyntaxKind.CallSignature:
639+
case SyntaxKind.ConstructSignature:
640+
case SyntaxKind.IndexSignature:
641+
case SyntaxKind.FunctionType:
642+
case SyntaxKind.ConstructorType:
643+
return true;
642644
}
643-
return false;
644645
}
645646

646647
export function introducesArgumentsExoticObject(node: Node) {

0 commit comments

Comments
 (0)