Skip to content

Commit 51dcd90

Browse files
authored
Cache mapper instantiations (#61505)
1 parent ffd98c1 commit 51dcd90

File tree

90 files changed

+5474
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+5474
-81
lines changed

src/compiler/checker.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2322,6 +2322,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
23222322
var inferenceContexts: (InferenceContext | undefined)[] = [];
23232323
var inferenceContextCount = 0;
23242324

2325+
var activeTypeMappers: TypeMapper[] = [];
2326+
var activeTypeMappersCaches: Map<string, Type>[] = [];
2327+
var activeTypeMappersCount = 0;
2328+
23252329
var emptyStringType = getStringLiteralType("");
23262330
var zeroType = getNumberLiteralType(0);
23272331
var zeroBigIntType = getBigIntLiteralType({ negative: false, base10Value: "0" });
@@ -20858,10 +20862,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2085820862
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
2085920863
return errorType;
2086020864
}
20865+
const index = findActiveMapper(mapper);
20866+
if (index === -1) {
20867+
pushActiveMapper(mapper);
20868+
}
20869+
const key = type.id + getAliasId(aliasSymbol, aliasTypeArguments);
20870+
const mapperCache = activeTypeMappersCaches[index !== -1 ? index : activeTypeMappersCount - 1];
20871+
const cached = mapperCache.get(key);
20872+
if (cached) {
20873+
return cached;
20874+
}
2086120875
totalInstantiationCount++;
2086220876
instantiationCount++;
2086320877
instantiationDepth++;
2086420878
const result = instantiateTypeWorker(type, mapper, aliasSymbol, aliasTypeArguments);
20879+
if (index === -1) {
20880+
popActiveMapper();
20881+
}
20882+
else {
20883+
mapperCache.set(key, result);
20884+
}
2086520885
instantiationDepth--;
2086620886
return result;
2086720887
}
@@ -27452,6 +27472,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2745227472
inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
2745327473
}
2745427474
}
27475+
clearActiveMapperCaches();
2745527476
}
2745627477

2745727478
return inference.inferredType;
@@ -32668,6 +32689,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3266832689
}
3266932690
}
3267032691

32692+
function pushActiveMapper(mapper: TypeMapper) {
32693+
activeTypeMappers[activeTypeMappersCount] = mapper;
32694+
activeTypeMappersCaches[activeTypeMappersCount] = new Map();
32695+
activeTypeMappersCount++;
32696+
}
32697+
32698+
function popActiveMapper() {
32699+
activeTypeMappersCount--;
32700+
}
32701+
32702+
function findActiveMapper(mapper: TypeMapper) {
32703+
for (let i = activeTypeMappersCount - 1; i >= 0; i--) {
32704+
if (mapper === activeTypeMappers[i]) {
32705+
return i;
32706+
}
32707+
}
32708+
return -1;
32709+
}
32710+
32711+
function clearActiveMapperCaches() {
32712+
for (let i = activeTypeMappersCount - 1; i >= 0; i--) {
32713+
activeTypeMappersCaches[i].clear();
32714+
}
32715+
}
32716+
3267132717
function getContextualImportAttributeType(node: ImportAttribute) {
3267232718
return getTypeOfPropertyOfContextualType(getGlobalImportAttributesType(/*reportErrors*/ false), getNameFromImportAttribute(node));
3267332719
}

tests/baselines/reference/callsOnComplexSignatures.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== callsOnComplexSignatures.tsx ===

tests/baselines/reference/checkJsxChildrenCanBeTupleType.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== checkJsxChildrenCanBeTupleType.tsx ===

tests/baselines/reference/checkJsxChildrenProperty16.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== checkJsxChildrenProperty16.tsx ===

tests/baselines/reference/checkJsxUnionSFXContextualTypeInferredCorrectly.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== checkJsxUnionSFXContextualTypeInferredCorrectly.tsx ===

tests/baselines/reference/circularBaseConstraint.types

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//// [tests/cases/compiler/circularBaseConstraint.ts] ////
22

3-
=== Performance Stats ===
4-
Instantiation count: 2,500
5-
63
=== circularBaseConstraint.ts ===
74
// Repro from #54610
85

tests/baselines/reference/circularlySimplifyingConditionalTypesNoCrash.types

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//// [tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts] ////
22

3-
=== Performance Stats ===
4-
Instantiation count: 2,500
5-
63
=== circularlySimplifyingConditionalTypesNoCrash.ts ===
74
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
85
>Omit : Omit<T, K>

tests/baselines/reference/conditionalTypeDiscriminatingLargeUnionRegularTypeFetchingSpeedReasonable.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Strict subtype cache: 2,500
55
Assignability cache: 10,000
66
Type Count: 10,000
7-
Instantiation count: 100,000
7+
Instantiation count: 50,000
88

99
=== conditionalTypeDiscriminatingLargeUnionRegularTypeFetchingSpeedReasonable.ts ===
1010
type BigUnion =

tests/baselines/reference/conditionalTypeDoesntSpinForever.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
=== Performance Stats ===
44
Type Count: 1,000
5-
Instantiation count: 2,500 -> 5,000
5+
Instantiation count: 2,500
66

77
=== conditionalTypeDoesntSpinForever.ts ===
88
// A *self-contained* demonstration of the problem follows...

tests/baselines/reference/conditionalTypeVarianceBigArrayConstraintsPerformance.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 1,000
55
Type Count: 5,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== conditionalTypeVarianceBigArrayConstraintsPerformance.ts ===

tests/baselines/reference/conditionalTypes1.types

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//// [tests/cases/conformance/types/conditional/conditionalTypes1.ts] ////
22

3-
=== Performance Stats ===
4-
Instantiation count: 1,000
5-
63
=== conditionalTypes1.ts ===
74
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
85
>T00 : T00
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//// [tests/cases/compiler/contextualParameterAndSelfReferentialConstraint1.ts] ////
2+
3+
=== contextualParameterAndSelfReferentialConstraint1.ts ===
4+
type NoExcessProperties<T, U> = T & {
5+
>NoExcessProperties : Symbol(NoExcessProperties, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 0))
6+
>T : Symbol(T, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 24))
7+
>U : Symbol(U, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 26))
8+
>T : Symbol(T, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 24))
9+
10+
readonly [K in Exclude<keyof U, keyof T>]: never;
11+
>K : Symbol(K, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 1, 12))
12+
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
13+
>U : Symbol(U, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 26))
14+
>T : Symbol(T, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 24))
15+
16+
};
17+
18+
interface Effect<out A> {
19+
>Effect : Symbol(Effect, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 2, 2))
20+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 4, 17))
21+
22+
readonly EffectTypeId: {
23+
>EffectTypeId : Symbol(Effect.EffectTypeId, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 4, 25))
24+
25+
readonly _A: (_: never) => A;
26+
>_A : Symbol(_A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 5, 26))
27+
>_ : Symbol(_, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 6, 18))
28+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 4, 17))
29+
30+
};
31+
}
32+
33+
declare function pipe<A, B>(a: A, ab: (a: A) => B): B;
34+
>pipe : Symbol(pipe, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 8, 1))
35+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 22))
36+
>B : Symbol(B, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 24))
37+
>a : Symbol(a, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 28))
38+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 22))
39+
>ab : Symbol(ab, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 33))
40+
>a : Symbol(a, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 39))
41+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 22))
42+
>B : Symbol(B, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 24))
43+
>B : Symbol(B, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 24))
44+
45+
interface RepeatOptions<A> {
46+
>RepeatOptions : Symbol(RepeatOptions, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 54))
47+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 12, 24))
48+
49+
until?: (_: A) => boolean;
50+
>until : Symbol(RepeatOptions.until, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 12, 28))
51+
>_ : Symbol(_, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 13, 11))
52+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 12, 24))
53+
}
54+
55+
declare const repeat: {
56+
>repeat : Symbol(repeat, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 16, 13))
57+
58+
<O extends NoExcessProperties<RepeatOptions<A>, O>, A>(
59+
>O : Symbol(O, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 3))
60+
>NoExcessProperties : Symbol(NoExcessProperties, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 0, 0))
61+
>RepeatOptions : Symbol(RepeatOptions, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 10, 54))
62+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 53))
63+
>O : Symbol(O, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 3))
64+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 53))
65+
66+
options: O,
67+
>options : Symbol(options, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 57))
68+
>O : Symbol(O, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 3))
69+
70+
): (self: Effect<A>) => Effect<A>;
71+
>self : Symbol(self, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 19, 6))
72+
>Effect : Symbol(Effect, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 2, 2))
73+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 53))
74+
>Effect : Symbol(Effect, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 2, 2))
75+
>A : Symbol(A, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 17, 53))
76+
77+
};
78+
79+
pipe(
80+
>pipe : Symbol(pipe, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 8, 1))
81+
82+
{} as Effect<boolean>,
83+
>Effect : Symbol(Effect, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 2, 2))
84+
85+
repeat({
86+
>repeat : Symbol(repeat, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 16, 13))
87+
88+
until: (x) => {
89+
>until : Symbol(until, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 24, 10))
90+
>x : Symbol(x, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 25, 12))
91+
92+
return x; // boolean
93+
>x : Symbol(x, Decl(contextualParameterAndSelfReferentialConstraint1.ts, 25, 12))
94+
95+
},
96+
}),
97+
);
98+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//// [tests/cases/compiler/contextualParameterAndSelfReferentialConstraint1.ts] ////
2+
3+
=== contextualParameterAndSelfReferentialConstraint1.ts ===
4+
type NoExcessProperties<T, U> = T & {
5+
>NoExcessProperties : NoExcessProperties<T, U>
6+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
7+
8+
readonly [K in Exclude<keyof U, keyof T>]: never;
9+
};
10+
11+
interface Effect<out A> {
12+
readonly EffectTypeId: {
13+
>EffectTypeId : { readonly _A: (_: never) => A; }
14+
> : ^^^^^^^^^^^^^^^ ^^^
15+
16+
readonly _A: (_: never) => A;
17+
>_A : (_: never) => A
18+
> : ^ ^^ ^^^^^
19+
>_ : never
20+
> : ^^^^^
21+
22+
};
23+
}
24+
25+
declare function pipe<A, B>(a: A, ab: (a: A) => B): B;
26+
>pipe : <A, B>(a: A, ab: (a: A) => B) => B
27+
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
28+
>a : A
29+
> : ^
30+
>ab : (a: A) => B
31+
> : ^ ^^ ^^^^^
32+
>a : A
33+
> : ^
34+
35+
interface RepeatOptions<A> {
36+
until?: (_: A) => boolean;
37+
>until : ((_: A) => boolean) | undefined
38+
> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^
39+
>_ : A
40+
> : ^
41+
}
42+
43+
declare const repeat: {
44+
>repeat : <O extends NoExcessProperties<RepeatOptions<A>, O>, A>(options: O) => (self: Effect<A>) => Effect<A>
45+
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^
46+
47+
<O extends NoExcessProperties<RepeatOptions<A>, O>, A>(
48+
options: O,
49+
>options : O
50+
> : ^
51+
52+
): (self: Effect<A>) => Effect<A>;
53+
>self : Effect<A>
54+
> : ^^^^^^^^^
55+
56+
};
57+
58+
pipe(
59+
>pipe( {} as Effect<boolean>, repeat({ until: (x) => { return x; // boolean }, }),) : Effect<boolean>
60+
> : ^^^^^^^^^^^^^^^
61+
>pipe : <A, B>(a: A, ab: (a: A) => B) => B
62+
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
63+
64+
{} as Effect<boolean>,
65+
>{} as Effect<boolean> : Effect<boolean>
66+
> : ^^^^^^^^^^^^^^^
67+
>{} : {}
68+
> : ^^
69+
70+
repeat({
71+
>repeat({ until: (x) => { return x; // boolean }, }) : (self: Effect<boolean>) => Effect<boolean>
72+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
>repeat : <O extends NoExcessProperties<RepeatOptions<A>, O>, A>(options: O) => (self: Effect<A>) => Effect<A>
74+
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^
75+
>{ until: (x) => { return x; // boolean }, } : { until: (x: boolean) => boolean; }
76+
> : ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
77+
78+
until: (x) => {
79+
>until : (x: boolean) => boolean
80+
> : ^ ^^^^^^^^^^^^^^^^^^^^^
81+
>(x) => { return x; // boolean } : (x: boolean) => boolean
82+
> : ^ ^^^^^^^^^^^^^^^^^^^^^
83+
>x : boolean
84+
> : ^^^^^^^
85+
86+
return x; // boolean
87+
>x : boolean
88+
> : ^^^^^^^
89+
90+
},
91+
}),
92+
);
93+

tests/baselines/reference/contextuallyTypedJsxChildren.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== contextuallyTypedJsxChildren.tsx ===

tests/baselines/reference/controlFlowOptionalChain3.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== Performance Stats ===
44
Assignability cache: 2,500
55
Type Count: 10,000
6-
Instantiation count: 100,000
6+
Instantiation count: 50,000
77
Symbol count: 50,000
88

99
=== controlFlowOptionalChain3.tsx ===

tests/baselines/reference/declarationEmitHigherOrderRetainedGenerics.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
=== Performance Stats ===
44
Type Count: 1,000
5-
Instantiation count: 2,500 -> 5,000
5+
Instantiation count: 2,500
66

77
=== declarationEmitHigherOrderRetainedGenerics.ts ===
88
export interface TypeLambda {

tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//// [tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts] ////
22

3-
=== Performance Stats ===
4-
Instantiation count: 500 -> 1,000
5-
63
=== declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts ===
74
// Note that both of the following have an `any` in their return type from where we bottom out the type printout
85
// for having too many instances of the same symbol nesting.

0 commit comments

Comments
 (0)