Skip to content

Commit 1f1dd93

Browse files
authored
Port TS PR 61505 - Cache mapper instantiations (#1358)
1 parent 9953b71 commit 1f1dd93

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

internal/checker/checker.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,8 @@ type Checker struct {
856856
skipDirectInferenceNodes collections.Set[*ast.Node]
857857
ctx context.Context
858858
packagesMap map[string]bool
859+
activeMappers []*TypeMapper
860+
activeTypeMappersCaches []map[string]*Type
859861
}
860862

861863
func NewChecker(program Program) *Checker {
@@ -21178,14 +21180,66 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl
2117821180
c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite)
2117921181
return c.errorType
2118021182
}
21183+
index := c.findActiveMapper(m)
21184+
if index == -1 {
21185+
c.pushActiveMapper(m)
21186+
}
21187+
var b KeyBuilder
21188+
b.WriteType(t)
21189+
b.WriteAlias(alias)
21190+
key := b.String()
21191+
cache := c.activeTypeMappersCaches[core.IfElse(index != -1, index, len(c.activeTypeMappersCaches)-1)]
21192+
if cachedType, ok := cache[key]; ok {
21193+
return cachedType
21194+
}
2118121195
c.TotalInstantiationCount++
2118221196
c.instantiationCount++
2118321197
c.instantiationDepth++
2118421198
result := c.instantiateTypeWorker(t, m, alias)
21199+
if index == -1 {
21200+
c.popActiveMapper()
21201+
} else {
21202+
cache[key] = result
21203+
}
2118521204
c.instantiationDepth--
2118621205
return result
2118721206
}
2118821207

21208+
func (c *Checker) pushActiveMapper(mapper *TypeMapper) {
21209+
c.activeMappers = append(c.activeMappers, mapper)
21210+
21211+
lastIndex := len(c.activeTypeMappersCaches)
21212+
if cap(c.activeTypeMappersCaches) > lastIndex {
21213+
// The cap may contain an empty map from popActiveMapper; reuse it.
21214+
c.activeTypeMappersCaches = c.activeTypeMappersCaches[:lastIndex+1]
21215+
if c.activeTypeMappersCaches[lastIndex] == nil {
21216+
c.activeTypeMappersCaches[lastIndex] = make(map[string]*Type, 1)
21217+
}
21218+
} else {
21219+
c.activeTypeMappersCaches = append(c.activeTypeMappersCaches, make(map[string]*Type, 1))
21220+
}
21221+
}
21222+
21223+
func (c *Checker) popActiveMapper() {
21224+
c.activeMappers[len(c.activeMappers)-1] = nil
21225+
c.activeMappers = c.activeMappers[:len(c.activeMappers)-1]
21226+
21227+
// Clear the map, but leave it in the list for later reuse.
21228+
lastIndex := len(c.activeTypeMappersCaches) - 1
21229+
clear(c.activeTypeMappersCaches[lastIndex])
21230+
c.activeTypeMappersCaches = c.activeTypeMappersCaches[:lastIndex]
21231+
}
21232+
21233+
func (c *Checker) findActiveMapper(mapper *TypeMapper) int {
21234+
return core.FindLastIndex(c.activeMappers, func(m *TypeMapper) bool { return m == mapper })
21235+
}
21236+
21237+
func (c *Checker) clearActiveMapperCaches() {
21238+
for _, cache := range c.activeTypeMappersCaches {
21239+
clear(cache)
21240+
}
21241+
}
21242+
2118921243
// Return true if the given type could possibly reference a type parameter for which
2119021244
// we perform type inference (i.e. a type parameter of a generic function). We cache
2119121245
// results for union and intersection types for performance reasons.

internal/checker/inference.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,7 @@ func (c *Checker) getInferredType(n *InferenceContext, index int) *Type {
13291329
}
13301330
inference.inferredType = inferredType
13311331
}
1332+
c.clearActiveMapperCaches()
13321333
}
13331334
return inference.inferredType
13341335
}

0 commit comments

Comments
 (0)