Skip to content

Commit 6e80fe2

Browse files
committed
go/token: replace map with array for looking up keywords
array access has considerable less overhead than map access thus yielding benefits in performance and package initialization.
1 parent de45645 commit 6e80fe2

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

src/go/token/token.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -279,19 +279,35 @@ func (op Token) Precedence() int {
279279
return LowestPrec
280280
}
281281

282-
var keywords map[string]Token
282+
var keywords [256]Token
283283

284284
func init() {
285-
keywords = make(map[string]Token, keyword_end-(keyword_beg+1))
286285
for i := keyword_beg + 1; i < keyword_end; i++ {
287-
keywords[tokens[i]] = i
286+
keywords[keywordsIndex(i.String())] = i
288287
}
289288
}
290289

290+
// keywordsIndex maps an identifier to an index in keywords array.
291+
func keywordsIndex(maybeKeyword string) uint8 {
292+
if len(maybeKeyword) <= 3 {
293+
if len(maybeKeyword) == 0 {
294+
return 0
295+
}
296+
return maybeKeyword[0]
297+
}
298+
v0 := maybeKeyword[0]
299+
v1 := maybeKeyword[1]
300+
v2 := maybeKeyword[2]
301+
v3 := maybeKeyword[3]
302+
h := v0 + v1*8 + v2 - v3
303+
return h
304+
}
305+
291306
// Lookup maps an identifier to its keyword token or [IDENT] (if not a keyword).
292307
func Lookup(ident string) Token {
293-
if tok, is_keyword := keywords[ident]; is_keyword {
294-
return tok
308+
maybeMatch := keywords[keywordsIndex(ident)]
309+
if maybeMatch != 0 && maybeMatch.String() == ident {
310+
return maybeMatch
295311
}
296312
return IDENT
297313
}
@@ -319,10 +335,9 @@ func IsExported(name string) bool {
319335
}
320336

321337
// IsKeyword reports whether name is a Go keyword, such as "func" or "return".
322-
func IsKeyword(name string) bool {
323-
// TODO: opt: use a perfect hash function instead of a global map.
324-
_, ok := keywords[name]
325-
return ok
338+
func IsKeyword(ident string) bool {
339+
tok := keywords[keywordsIndex(ident)]
340+
return tok != 0 && tok.String() == ident
326341
}
327342

328343
// IsIdentifier reports whether name is a Go identifier, that is, a non-empty

0 commit comments

Comments
 (0)