Skip to content

Commit 5dc93c4

Browse files
committed
Move less-used fields off of Node to reduce polymorphism
1 parent 8efa88f commit 5dc93c4

28 files changed

+586
-329
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,4 @@ tests/cases/user/puppeteer/puppeteer
8484
tests/cases/user/axios-src/axios-src
8585
tests/cases/user/prettier/prettier
8686
.eslintcache
87+
isolate-*-v8.log

src/compiler/binder.ts

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ namespace ts {
250250
Debug.attachFlowNodeDebugInfo(unreachableFlow);
251251
Debug.attachFlowNodeDebugInfo(reportedUnreachableFlow);
252252

253-
if (!file.locals) {
253+
if (!getBindExtraFields(file)?.locals) {
254254
tracing?.push(tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true);
255255
bind(file);
256256
tracing?.pop();
@@ -553,7 +553,7 @@ namespace ts {
553553
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
554554
}
555555
else {
556-
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
556+
return declareSymbol(getBindExtraFields(container)!.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
557557
}
558558
}
559559
else {
@@ -574,17 +574,18 @@ namespace ts {
574574
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
575575
if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
576576
if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) {
577-
if (!container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) {
577+
const containerBindNode = getBindExtraFields(container);
578+
if (!containerBindNode?.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) {
578579
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
579580
}
580581
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0;
581-
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
582+
const local = declareSymbol(containerBindNode.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
582583
local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
583-
node.localSymbol = local;
584+
getOrCreateBindExtraFields(node).localSymbol = local;
584585
return local;
585586
}
586587
else {
587-
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
588+
return declareSymbol(getBindExtraFields(container)!.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
588589
}
589590
}
590591
}
@@ -641,13 +642,13 @@ namespace ts {
641642
}
642643
container = blockScopeContainer = node;
643644
if (containerFlags & ContainerFlags.HasLocals) {
644-
container.locals = createSymbolTable();
645+
getOrCreateBindExtraFields(container).locals = createSymbolTable();
645646
}
646647
addToContainerChain(container);
647648
}
648649
else if (containerFlags & ContainerFlags.IsBlockScopedContainer) {
649650
blockScopeContainer = node;
650-
blockScopeContainer.locals = undefined;
651+
getOrCreateBindExtraFields(blockScopeContainer).locals = undefined;
651652
}
652653
if (containerFlags & ContainerFlags.IsControlFlowContainer) {
653654
const saveCurrentFlow = currentFlow;
@@ -685,7 +686,7 @@ namespace ts {
685686
if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).body)) {
686687
node.flags |= NodeFlags.HasImplicitReturn;
687688
if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn;
688-
(node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).endFlowNode = currentFlow;
689+
setEndFlowNode(node as FunctionLikeDeclarationBase | ClassStaticBlockDeclaration, currentFlow);
689690
}
690691
if (node.kind === SyntaxKind.SourceFile) {
691692
node.flags |= emitFlags;
@@ -696,7 +697,7 @@ namespace ts {
696697
addAntecedent(currentReturnTarget, currentFlow);
697698
currentFlow = finishFlowLabel(currentReturnTarget);
698699
if (node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
699-
(node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).returnFlowNode = currentFlow;
700+
setReturnFlowNode(node as FunctionLikeDeclaration | ClassStaticBlockDeclaration, currentFlow);
700701
}
701702
}
702703
if (!isImmediatelyInvoked) {
@@ -752,7 +753,7 @@ namespace ts {
752753
return;
753754
}
754755
if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && !options.allowUnreachableCode) {
755-
node.flowNode = currentFlow;
756+
setFlowNode(node, currentFlow);
756757
}
757758
switch (node.kind) {
758759
case SyntaxKind.WhileStatement:
@@ -1352,7 +1353,7 @@ namespace ts {
13521353
bind(clause);
13531354
fallthroughFlow = currentFlow;
13541355
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
1355-
clause.fallthroughFlowNode = currentFlow;
1356+
setFallthroughFlowNode(clause, currentFlow);
13561357
}
13571358
}
13581359
}
@@ -1905,7 +1906,7 @@ namespace ts {
19051906

19061907
function addToContainerChain(next: Node) {
19071908
if (lastContainer) {
1908-
lastContainer.nextContainer = next;
1909+
getOrCreateBindExtraFields(lastContainer).nextContainer = next;
19091910
}
19101911

19111912
lastContainer = next;
@@ -1968,7 +1969,7 @@ namespace ts {
19681969
// their container in the tree). To accomplish this, we simply add their declared
19691970
// symbol to the 'locals' of the container. These symbols can then be found as
19701971
// the type checker walks up the containers, checking them for matching names.
1971-
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
1972+
return declareSymbol(getBindExtraFields(container)!.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
19721973
}
19731974
}
19741975

@@ -1981,7 +1982,7 @@ namespace ts {
19811982
function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
19821983
return isExternalModule(file)
19831984
? declareModuleMember(node, symbolFlags, symbolExcludes)
1984-
: declareSymbol(file.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
1985+
: declareSymbol(getBindExtraFields(container)!.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
19851986
}
19861987

19871988
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
@@ -2095,11 +2096,12 @@ namespace ts {
20952096
}
20962097
// falls through
20972098
default:
2098-
if (!blockScopeContainer.locals) {
2099-
blockScopeContainer.locals = createSymbolTable();
2099+
const bindNode = getOrCreateBindExtraFields(blockScopeContainer);
2100+
if (!bindNode.locals) {
2101+
bindNode.locals = createSymbolTable();
21002102
addToContainerChain(blockScopeContainer);
21012103
}
2102-
declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
2104+
declareSymbol(bindNode.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
21032105
}
21042106
}
21052107

@@ -2450,12 +2452,12 @@ namespace ts {
24502452
function bindJSDoc(node: Node) {
24512453
if (hasJSDocNodes(node)) {
24522454
if (isInJSFile(node)) {
2453-
for (const j of node.jsDoc!) {
2455+
for (const j of getJSDocExtraFields(node)!.jsDoc!) {
24542456
bind(j);
24552457
}
24562458
}
24572459
else {
2458-
for (const j of node.jsDoc!) {
2460+
for (const j of getJSDocExtraFields(node)!.jsDoc!) {
24592461
setParent(j, node);
24602462
setParentRecursive(j, /*incremental*/ false);
24612463
}
@@ -2505,25 +2507,25 @@ namespace ts {
25052507
// falls through
25062508
case SyntaxKind.ThisKeyword:
25072509
if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) {
2508-
node.flowNode = currentFlow;
2510+
setFlowNode(node, currentFlow);
25092511
}
25102512
return checkContextualIdentifier(node as Identifier);
25112513
case SyntaxKind.QualifiedName:
25122514
if (currentFlow && isPartOfTypeQuery(node)) {
2513-
node.flowNode = currentFlow;
2515+
setFlowNode(node, currentFlow);
25142516
}
25152517
break;
25162518
case SyntaxKind.MetaProperty:
25172519
case SyntaxKind.SuperKeyword:
2518-
node.flowNode = currentFlow;
2520+
setFlowNode(node, currentFlow);
25192521
break;
25202522
case SyntaxKind.PrivateIdentifier:
25212523
return checkPrivateIdentifier(node as PrivateIdentifier);
25222524
case SyntaxKind.PropertyAccessExpression:
25232525
case SyntaxKind.ElementAccessExpression:
25242526
const expr = node as PropertyAccessExpression | ElementAccessExpression;
25252527
if (currentFlow && isNarrowableReference(expr)) {
2526-
expr.flowNode = currentFlow;
2528+
setFlowNode(expr, currentFlow);
25272529
}
25282530
if (isSpecialPropertyDeclaration(expr)) {
25292531
bindSpecialPropertyDeclaration(expr);
@@ -2532,7 +2534,7 @@ namespace ts {
25322534
file.commonJsModuleIndicator &&
25332535
isModuleExportsAccessExpression(expr) &&
25342536
!lookupSymbolForName(blockScopeContainer, "module" as __String)) {
2535-
declareSymbol(file.locals!, /*parent*/ undefined, expr.expression,
2537+
declareSymbol(getBindExtraFields(file)!.locals!, /*parent*/ undefined, expr.expression,
25362538
SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes);
25372539
}
25382540
break;
@@ -2598,7 +2600,7 @@ namespace ts {
25982600
case SyntaxKind.VariableDeclaration:
25992601
return bindVariableDeclarationOrBindingElement(node as VariableDeclaration);
26002602
case SyntaxKind.BindingElement:
2601-
node.flowNode = currentFlow;
2603+
setFlowNode(node, currentFlow);
26022604
return bindVariableDeclarationOrBindingElement(node as BindingElement);
26032605
case SyntaxKind.PropertyDeclaration:
26042606
case SyntaxKind.PropertySignature:
@@ -3360,7 +3362,7 @@ namespace ts {
33603362
}
33613363
}
33623364
if (currentFlow) {
3363-
node.flowNode = currentFlow;
3365+
setFlowNode(node, currentFlow);
33643366
}
33653367
checkStrictModeFunctionName(node);
33663368
const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Function;
@@ -3373,7 +3375,7 @@ namespace ts {
33733375
}
33743376

33753377
if (currentFlow && isObjectLiteralOrClassExpressionMethodOrAccessor(node)) {
3376-
node.flowNode = currentFlow;
3378+
setFlowNode(node, currentFlow);
33773379
}
33783380

33793381
return hasDynamicName(node)
@@ -3390,10 +3392,8 @@ namespace ts {
33903392
if (isJSDocTemplateTag(node.parent)) {
33913393
const container = getEffectiveContainerForJSDocTemplateTag(node.parent);
33923394
if (container) {
3393-
if (!container.locals) {
3394-
container.locals = createSymbolTable();
3395-
}
3396-
declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
3395+
const locals = getOrCreateBindExtraFields(container).locals ??= createSymbolTable();
3396+
declareSymbol(locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
33973397
}
33983398
else {
33993399
declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
@@ -3402,10 +3402,8 @@ namespace ts {
34023402
else if (node.parent.kind === SyntaxKind.InferType) {
34033403
const container = getInferTypeContainer(node.parent);
34043404
if (container) {
3405-
if (!container.locals) {
3406-
container.locals = createSymbolTable();
3407-
}
3408-
declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
3405+
const locals = getOrCreateBindExtraFields(container).locals ??= createSymbolTable();
3406+
declareSymbol(locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
34093407
}
34103408
else {
34113409
bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217
@@ -3524,7 +3522,7 @@ namespace ts {
35243522
}
35253523

35263524
function lookupSymbolForName(container: Node, name: __String): Symbol | undefined {
3527-
const local = container.locals && container.locals.get(name);
3525+
const local = getBindExtraFields(container)?.locals?.get(name);
35283526
if (local) {
35293527
return local.exportSymbol || local;
35303528
}

0 commit comments

Comments
 (0)