3 // This file defines func typeOf(ast.Node) uint64.
5 // The initial map-based implementation was too slow;
6 // see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196
68 // typeOf returns a distinct single-bit value that represents the type of n.
70 // Various implementations were benchmarked with BenchmarkNewInspector:
72 // - type switch 4.9-5.5ms 2.1ms
73 // - binary search over a sorted list of types 5.5-5.9ms 2.5ms
74 // - linear scan, frequency-ordered list 5.9-6.1ms 2.7ms
75 // - linear scan, unordered list 6.4ms 2.7ms
76 // - hash table 6.5ms 3.1ms
77 // A perfect hash seemed like overkill.
79 // The compiler's switch statement is the clear winner
80 // as it produces a binary tree in code,
81 // with constant conditions and good branch prediction.
82 // (Sadly it is the most verbose in source code.)
83 // Binary search suffered from poor branch prediction.
85 func typeOf(n ast.Node) uint64 {
86 // Fast path: nearly half of all nodes are identifiers.
87 if _, ok := n.(*ast.Ident); ok {
91 // These cases include all nodes encountered by ast.Inspect.
94 return 1 << nArrayType
96 return 1 << nAssignStmt
104 return 1 << nBasicLit
105 case *ast.BinaryExpr:
106 return 1 << nBinaryExpr
108 return 1 << nBlockStmt
109 case *ast.BranchStmt:
110 return 1 << nBranchStmt
112 return 1 << nCallExpr
113 case *ast.CaseClause:
114 return 1 << nCaseClause
116 return 1 << nChanType
117 case *ast.CommClause:
118 return 1 << nCommClause
121 case *ast.CommentGroup:
122 return 1 << nCommentGroup
123 case *ast.CompositeLit:
124 return 1 << nCompositeLit
126 return 1 << nDeclStmt
128 return 1 << nDeferStmt
130 return 1 << nEllipsis
132 return 1 << nEmptyStmt
134 return 1 << nExprStmt
138 return 1 << nFieldList
144 return 1 << nFuncDecl
148 return 1 << nFuncType
157 case *ast.ImportSpec:
158 return 1 << nImportSpec
159 case *ast.IncDecStmt:
160 return 1 << nIncDecStmt
162 return 1 << nIndexExpr
163 case *ast.InterfaceType:
164 return 1 << nInterfaceType
165 case *ast.KeyValueExpr:
166 return 1 << nKeyValueExpr
167 case *ast.LabeledStmt:
168 return 1 << nLabeledStmt
174 return 1 << nParenExpr
176 return 1 << nRangeStmt
177 case *ast.ReturnStmt:
178 return 1 << nReturnStmt
179 case *ast.SelectStmt:
180 return 1 << nSelectStmt
181 case *ast.SelectorExpr:
182 return 1 << nSelectorExpr
184 return 1 << nSendStmt
186 return 1 << nSliceExpr
188 return 1 << nStarExpr
189 case *ast.StructType:
190 return 1 << nStructType
191 case *ast.SwitchStmt:
192 return 1 << nSwitchStmt
193 case *ast.TypeAssertExpr:
194 return 1 << nTypeAssertExpr
196 return 1 << nTypeSpec
197 case *ast.TypeSwitchStmt:
198 return 1 << nTypeSwitchStmt
200 return 1 << nUnaryExpr
202 return 1 << nValueSpec
207 func maskOf(nodes []ast.Node) uint64 {
209 return 1<<64 - 1 // match all node types
212 for _, n := range nodes {