@@ -2,15 +2,27 @@ package metadata
22
33// Builder accumulates per-package metadata facts and builds a PackageMeta.
44type Builder struct {
5- pm * PackageMeta
6- strToID map [string ]uint32
5+ pm * PackageMeta
6+ strToID map [string ]uint32
7+ seenEdge map [[2 ]Symbol ]struct {}
8+ seenTypeChild map [[2 ]Symbol ]struct {}
9+ seenInterfaceInfo map [interfaceInfoKey ]struct {}
10+ seenUseIface map [[2 ]Symbol ]struct {}
11+ seenUseIfaceMethod map [useIfaceMethodKey ]struct {}
12+ seenUseNamedMethod map [useNamedMethodKey ]struct {}
713}
814
915// NewBuilder creates an empty metadata builder.
1016func NewBuilder () * Builder {
1117 return & Builder {
12- pm : NewPackageMeta (nil ),
13- strToID : make (map [string ]uint32 ),
18+ pm : NewPackageMeta (nil ),
19+ strToID : make (map [string ]uint32 ),
20+ seenEdge : make (map [[2 ]Symbol ]struct {}),
21+ seenTypeChild : make (map [[2 ]Symbol ]struct {}),
22+ seenInterfaceInfo : make (map [interfaceInfoKey ]struct {}),
23+ seenUseIface : make (map [[2 ]Symbol ]struct {}),
24+ seenUseIfaceMethod : make (map [useIfaceMethodKey ]struct {}),
25+ seenUseNamedMethod : make (map [useNamedMethodKey ]struct {}),
1426 }
1527}
1628
@@ -35,32 +47,57 @@ func (b *Builder) intern(s string) uint32 {
3547
3648// AddEdge records an ordinary reachability edge src -> dst.
3749func (b * Builder ) AddEdge (src , dst Symbol ) {
38- addUniqueSymbol (& b .pm .ordinaryEdges , src , dst )
50+ key := [2 ]Symbol {src , dst }
51+ if _ , ok := b .seenEdge [key ]; ok {
52+ return
53+ }
54+ b .seenEdge [key ] = struct {}{}
55+ b .pm .ordinaryEdges [src ] = append (b .pm .ordinaryEdges [src ], dst )
3956}
4057
4158// AddTypeChild records that parent type references child type.
4259func (b * Builder ) AddTypeChild (parent , child Symbol ) {
43- addUniqueSymbol (& b .pm .typeChildren , parent , child )
60+ key := [2 ]Symbol {parent , child }
61+ if _ , ok := b .seenTypeChild [key ]; ok {
62+ return
63+ }
64+ b .seenTypeChild [key ] = struct {}{}
65+ b .pm .typeChildren [parent ] = append (b .pm .typeChildren [parent ], child )
4466}
4567
4668// AddIfaceEntry records the method set of an interface type.
4769func (b * Builder ) AddIfaceEntry (iface Symbol , methods []MethodSig ) {
4870 for _ , method := range methods {
49- addUniqueMethodSig (& b .pm .interfaceInfo , iface , method )
71+ key := interfaceInfoKey {Iface : iface , Sig : method }
72+ if _ , ok := b .seenInterfaceInfo [key ]; ok {
73+ continue
74+ }
75+ b .seenInterfaceInfo [key ] = struct {}{}
76+ b .pm .interfaceInfo [iface ] = append (b .pm .interfaceInfo [iface ], method )
5077 }
5178}
5279
5380// AddUseIface records types converted to interface when owner is reachable.
5481func (b * Builder ) AddUseIface (owner Symbol , types []Symbol ) {
5582 for _ , typ := range types {
56- addUniqueSymbol (& b .pm .useIface , owner , typ )
83+ key := [2 ]Symbol {owner , typ }
84+ if _ , ok := b .seenUseIface [key ]; ok {
85+ continue
86+ }
87+ b .seenUseIface [key ] = struct {}{}
88+ b .pm .useIface [owner ] = append (b .pm .useIface [owner ], typ )
5789 }
5890}
5991
6092// AddUseIfaceMethod records interface method calls when owner is reachable.
6193func (b * Builder ) AddUseIfaceMethod (owner Symbol , demands []IfaceMethodDemand ) {
6294 for _ , demand := range demands {
63- addUniqueIfaceMethodDemand (& b .pm .useIfaceMethod , owner , demand )
95+ key := useIfaceMethodKey {Owner : owner , Demand : demand }
96+ if _ , ok := b .seenUseIfaceMethod [key ]; ok {
97+ continue
98+ }
99+ b .seenUseIfaceMethod [key ] = struct {}{}
100+ b .pm .useIfaceMethod [owner ] = append (b .pm .useIfaceMethod [owner ], demand )
64101 }
65102}
66103
@@ -75,7 +112,12 @@ func (b *Builder) AddMethodInfo(typeID Symbol, slots []MethodSlot) {
75112// AddUseNamedMethod records constant MethodByName method names.
76113func (b * Builder ) AddUseNamedMethod (owner Symbol , names []Name ) {
77114 for _ , name := range names {
78- addUniqueName (& b .pm .useNamedMethod , owner , name )
115+ key := useNamedMethodKey {Owner : owner , Name : name }
116+ if _ , ok := b .seenUseNamedMethod [key ]; ok {
117+ continue
118+ }
119+ b .seenUseNamedMethod [key ] = struct {}{}
120+ b .pm .useNamedMethod [owner ] = append (b .pm .useNamedMethod [owner ], name )
79121 }
80122}
81123
@@ -94,42 +136,17 @@ func (b *Builder) Build() *PackageMeta {
94136 return b .pm
95137}
96138
97- func addUniqueSymbol (m * map [Symbol ][]Symbol , key , value Symbol ) {
98- values := (* m )[key ]
99- for _ , existing := range values {
100- if existing == value {
101- return
102- }
103- }
104- (* m )[key ] = append (values , value )
105- }
106-
107- func addUniqueName (m * map [Symbol ][]Name , key Symbol , value Name ) {
108- values := (* m )[key ]
109- for _ , existing := range values {
110- if existing == value {
111- return
112- }
113- }
114- (* m )[key ] = append (values , value )
139+ type interfaceInfoKey struct {
140+ Iface Symbol
141+ Sig MethodSig
115142}
116143
117- func addUniqueMethodSig (m * map [Symbol ][]MethodSig , key Symbol , value MethodSig ) {
118- values := (* m )[key ]
119- for _ , existing := range values {
120- if existing == value {
121- return
122- }
123- }
124- (* m )[key ] = append (values , value )
144+ type useIfaceMethodKey struct {
145+ Owner Symbol
146+ Demand IfaceMethodDemand
125147}
126148
127- func addUniqueIfaceMethodDemand (m * map [Symbol ][]IfaceMethodDemand , key Symbol , value IfaceMethodDemand ) {
128- values := (* m )[key ]
129- for _ , existing := range values {
130- if existing == value {
131- return
132- }
133- }
134- (* m )[key ] = append (values , value )
149+ type useNamedMethodKey struct {
150+ Owner Symbol
151+ Name Name
135152}
0 commit comments