@@ -5,46 +5,62 @@ import (
55 "github.com/microsoft/TypeScript/tsc/internal/core"
66)
77
8- // nodeLinkStore is a links store keyed by node references. Values are stored directly
9- // in the pages of the store which is suitable for values where sizeof(V) is small.
8+ // When possible, nodeLinkStore and symbolLinkStore store Node and Symbol links in an efficient and densely
9+ // packed paged array store. When a Node or Symbol has not yet been assigned an ID, the store provides one
10+ // from a generator that produces sequences of IDs in a reserved range of the ID space. The generator grabs
11+ // chunks of 256 IDs from a central atomic counter, ensuring that each block of 256 IDs is consecutive and
12+ // causing Node or Symbol links to be densely packed within a single page.
13+
14+ const maxPageLinkCount = 0x100_0000 // 16M
15+
1016type nodeLinkStore [V any ] struct {
11- store core.PagedLinkStore [V ]
17+ gen ast.NodeIdGenerator
18+ links core.LinkStore [uint64 , V ]
19+ pages core.PagedLinkStore [V ]
1220}
1321
1422func (s * nodeLinkStore [V ]) Get (node * ast.Node ) * V {
15- return s .store .Get (uint64 (ast .GetNodeId (node )))
23+ id := uint64 (s .gen .GetNodeId (node ))
24+ if id >= ast .BlockIdOffset && id < ast .BlockIdOffset + maxPageLinkCount {
25+ return s .pages .Get (id - ast .BlockIdOffset )
26+ }
27+ return s .links .Get (id )
1628}
1729
1830func (s * nodeLinkStore [V ]) Has (node * ast.Node ) bool {
19- return s .store . Has ( uint64 ( ast . GetNodeId ( node )))
31+ return s .TryGet ( node ) != nil
2032}
2133
2234func (s * nodeLinkStore [V ]) TryGet (node * ast.Node ) * V {
23- return s .store .TryGet (uint64 (ast .GetNodeId (node )))
35+ id := uint64 (s .gen .GetNodeId (node ))
36+ if id >= ast .BlockIdOffset && id < ast .BlockIdOffset + maxPageLinkCount {
37+ return s .pages .TryGet (id - ast .BlockIdOffset )
38+ }
39+ return s .links .TryGet (id )
2440}
2541
26- // symbolArenaLinkStore is a links store keyed by symbol references. Values are stored
27- // indirectly in an arena which is suitable for values where sizeof(V) is larger.
28- type symbolArenaLinkStore [V any ] struct {
29- store core.PagedLinkStore [* V ]
30- arena core.Arena [V ]
42+ type symbolLinkStore [V any ] struct {
43+ gen ast.SymbolIdGenerator
44+ links core.LinkStore [uint64 , V ]
45+ pages core.PagedLinkStore [V ]
3146}
3247
33- func (s * symbolArenaLinkStore [V ]) Get (symbol * ast.Symbol ) * V {
34- link := s . store . Get ( uint64 (ast . GetSymbolId (symbol ) ))
35- if * link == nil {
36- * link = s . arena . New ( )
48+ func (s * symbolLinkStore [V ]) Get (symbol * ast.Symbol ) * V {
49+ id := uint64 (s . gen . GetSymbolId (symbol ))
50+ if id >= ast . BlockIdOffset && id < ast . BlockIdOffset + maxPageLinkCount {
51+ return s . pages . Get ( id - ast . BlockIdOffset )
3752 }
38- return * link
53+ return s . links . Get ( id )
3954}
4055
41- func (s * symbolArenaLinkStore [V ]) Has (symbol * ast.Symbol ) bool {
56+ func (s * symbolLinkStore [V ]) Has (symbol * ast.Symbol ) bool {
4257 return s .TryGet (symbol ) != nil
4358}
4459
45- func (s * symbolArenaLinkStore [V ]) TryGet (symbol * ast.Symbol ) * V {
46- if link := s .store .TryGet (uint64 (ast .GetSymbolId (symbol ))); link != nil {
47- return * link
60+ func (s * symbolLinkStore [V ]) TryGet (symbol * ast.Symbol ) * V {
61+ id := uint64 (s .gen .GetSymbolId (symbol ))
62+ if id >= ast .BlockIdOffset && id < ast .BlockIdOffset + maxPageLinkCount {
63+ return s .pages .TryGet (id - ast .BlockIdOffset )
4864 }
49- return nil
65+ return s . links . TryGet ( id )
5066}
0 commit comments