1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // This file defines func typeOf(ast.Node) uint64.
9 // The initial map-based implementation was too slow;
10 // see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196
72 // typeOf returns a distinct single-bit value that represents the type of n.
74 // Various implementations were benchmarked with BenchmarkNewInspector:
76 // - type switch 4.9-5.5ms 2.1ms
77 // - binary search over a sorted list of types 5.5-5.9ms 2.5ms
78 // - linear scan, frequency-ordered list 5.9-6.1ms 2.7ms
79 // - linear scan, unordered list 6.4ms 2.7ms
80 // - hash table 6.5ms 3.1ms
81 // A perfect hash seemed like overkill.
83 // The compiler's switch statement is the clear winner
84 // as it produces a binary tree in code,
85 // with constant conditions and good branch prediction.
86 // (Sadly it is the most verbose in source code.)
87 // Binary search suffered from poor branch prediction.
89 func typeOf(n ast.Node) uint64 {
90 // Fast path: nearly half of all nodes are identifiers.
91 if _, ok := n.(*ast.Ident); ok {
95 // These cases include all nodes encountered by ast.Inspect.
98 return 1 << nArrayType
100 return 1 << nAssignStmt
108 return 1 << nBasicLit
109 case *ast.BinaryExpr:
110 return 1 << nBinaryExpr
112 return 1 << nBlockStmt
113 case *ast.BranchStmt:
114 return 1 << nBranchStmt
116 return 1 << nCallExpr
117 case *ast.CaseClause:
118 return 1 << nCaseClause
120 return 1 << nChanType
121 case *ast.CommClause:
122 return 1 << nCommClause
125 case *ast.CommentGroup:
126 return 1 << nCommentGroup
127 case *ast.CompositeLit:
128 return 1 << nCompositeLit
130 return 1 << nDeclStmt
132 return 1 << nDeferStmt
134 return 1 << nEllipsis
136 return 1 << nEmptyStmt
138 return 1 << nExprStmt
142 return 1 << nFieldList
148 return 1 << nFuncDecl
152 return 1 << nFuncType
161 case *ast.ImportSpec:
162 return 1 << nImportSpec
163 case *ast.IncDecStmt:
164 return 1 << nIncDecStmt
166 return 1 << nIndexExpr
167 case *ast.InterfaceType:
168 return 1 << nInterfaceType
169 case *ast.KeyValueExpr:
170 return 1 << nKeyValueExpr
171 case *ast.LabeledStmt:
172 return 1 << nLabeledStmt
178 return 1 << nParenExpr
180 return 1 << nRangeStmt
181 case *ast.ReturnStmt:
182 return 1 << nReturnStmt
183 case *ast.SelectStmt:
184 return 1 << nSelectStmt
185 case *ast.SelectorExpr:
186 return 1 << nSelectorExpr
188 return 1 << nSendStmt
190 return 1 << nSliceExpr
192 return 1 << nStarExpr
193 case *ast.StructType:
194 return 1 << nStructType
195 case *ast.SwitchStmt:
196 return 1 << nSwitchStmt
197 case *ast.TypeAssertExpr:
198 return 1 << nTypeAssertExpr
200 return 1 << nTypeSpec
201 case *ast.TypeSwitchStmt:
202 return 1 << nTypeSwitchStmt
204 return 1 << nUnaryExpr
206 return 1 << nValueSpec
211 func maskOf(nodes []ast.Node) uint64 {
213 return 1<<64 - 1 // match all node types
216 for _, n := range nodes {