From 59f1f2c5a8fd844a6cc55e9a773a7003bd8e5480 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Mon, 27 Dec 2021 13:02:27 +0000 Subject: [PATCH] cmd/goyacc: reduce array sizes using smaller base types These arrays can be quite large, reducing the size of them save lot of space reducing cache usage and file size. Signed-off-by: Frediano Ziglio Change-Id: I446088627bc135cb47f6bee919e147b24d1ad848 Reviewed-on: https://go-review.googlesource.com/c/tools/+/374434 Reviewed-by: Keith Randall Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor gopls-CI: kokoro TryBot-Result: Gopher Robot --- cmd/goyacc/yacc.go | 146 ++++++++++++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 54 deletions(-) diff --git a/cmd/goyacc/yacc.go b/cmd/goyacc/yacc.go index 848717e42..70d01f0d5 100644 --- a/cmd/goyacc/yacc.go +++ b/cmd/goyacc/yacc.go @@ -51,6 +51,7 @@ import ( "fmt" "go/format" "io/ioutil" + "math" "os" "strconv" "strings" @@ -2157,7 +2158,7 @@ func output() { if !lflag { fmt.Fprintf(ftable, "\n//line yacctab:1") } - fmt.Fprintf(ftable, "\nvar %sExca = [...]int{\n", prefix) + var actions []int if len(errors) > 0 { stateTable = make([]Row, nstate) @@ -2230,10 +2231,11 @@ func output() { } } } - wract(i) + actions = addActions(actions, i) } - fmt.Fprintf(ftable, "}\n") + arrayOutColumns("Exca", actions, 2, false) + fmt.Fprintf(ftable, "\n") ftable.WriteRune('\n') fmt.Fprintf(ftable, "const %sPrivate = %v\n", prefix, PRIVATE) } @@ -2278,7 +2280,7 @@ func precftn(r, t, s int) { // output state i // temp1 has the actions, lastred the default // -func wract(i int) { +func addActions(act []int, i int) []int { var p, p1 int // find the best choice for lastred @@ -2351,18 +2353,19 @@ func wract(i int) { continue } if flag == 0 { - fmt.Fprintf(ftable, "\t-1, %v,\n", i) + act = append(act, -1, i) } flag++ - fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1) + act = append(act, p, p1) zzexcp++ } } if flag != 0 { defact[i] = -2 - fmt.Fprintf(ftable, "\t-2, %v,\n", lastred) + act = append(act, -2, lastred) } optst[i] = os + return act } // @@ -2855,7 +2858,7 @@ func others() { } } arout("Chk", temp1, nstate) - arout("Def", defact, nstate) + arrayOutColumns("Def", defact[:nstate], 10, false) // put out token translation tables // table 1 has 0-256 @@ -2903,8 +2906,7 @@ func others() { // table 3 has everything else ftable.WriteRune('\n') - fmt.Fprintf(ftable, "var %sTok3 = [...]int{\n\t", prefix) - c = 0 + var v []int for i = 1; i <= ntokens; i++ { j = tokset[i].value if j >= 0 && j < 256 { @@ -2914,19 +2916,11 @@ func others() { continue } - if c%5 != 0 { - ftable.WriteRune(' ') - } - fmt.Fprintf(ftable, "%d, %d,", j, i) - c++ - if c%5 == 0 { - fmt.Fprint(ftable, "\n\t") - } + v = append(v, j, i) } - if c%5 != 0 { - ftable.WriteRune(' ') - } - fmt.Fprintf(ftable, "%d,\n}\n", 0) + v = append(v, 0) + arout("Tok3", v, len(v)) + fmt.Fprintf(ftable, "\n") // Custom error messages. fmt.Fprintf(ftable, "\n") @@ -3013,21 +3007,65 @@ Loop: } } -func arout(s string, v []int, n int) { +func minMax(v []int) (min, max int) { + if len(v) == 0 { + return + } + min = v[0] + max = v[0] + for _, i := range v { + if i < min { + min = i + } + if i > max { + max = i + } + } + return +} + +// return the smaller integral base type to store the values in v +func minType(v []int, allowUnsigned bool) (typ string) { + typ = "int" + typeLen := 8 + min, max := minMax(v) + checkType := func(name string, size, minType, maxType int) { + if min >= minType && max <= maxType && typeLen > size { + typ = name + typeLen = size + } + } + checkType("int32", 4, math.MinInt32, math.MaxInt32) + checkType("int16", 2, math.MinInt16, math.MaxInt16) + checkType("int8", 1, math.MinInt8, math.MaxInt8) + if allowUnsigned { + // Do not check for uint32, not worth and won't compile on 32 bit systems + checkType("uint16", 2, 0, math.MaxUint16) + checkType("uint8", 1, 0, math.MaxUint8) + } + return +} + +func arrayOutColumns(s string, v []int, columns int, allowUnsigned bool) { s = prefix + s ftable.WriteRune('\n') - fmt.Fprintf(ftable, "var %v = [...]int{", s) - for i := 0; i < n; i++ { - if i%10 == 0 { + minType := minType(v, allowUnsigned) + fmt.Fprintf(ftable, "var %v = [...]%s{", s, minType) + for i, val := range v { + if i%columns == 0 { fmt.Fprintf(ftable, "\n\t") } else { ftable.WriteRune(' ') } - fmt.Fprintf(ftable, "%d,", v[i]) + fmt.Fprintf(ftable, "%d,", val) } fmt.Fprintf(ftable, "\n}\n") } +func arout(s string, v []int, n int) { + arrayOutColumns(s, v[:n], 10, true) +} + // // output the summary on y.output // @@ -3332,9 +3370,9 @@ func $$ErrorMessage(state, lookAhead int) string { expected := make([]int, 0, 4) // Look for shiftable tokens. - base := $$Pact[state] + base := int($$Pact[state]) for tok := TOKSTART; tok-1 < len($$Toknames); tok++ { - if n := base + tok; n >= 0 && n < $$Last && $$Chk[$$Act[n]] == tok { + if n := base + tok; n >= 0 && n < $$Last && int($$Chk[int($$Act[n])]) == tok { if len(expected) == cap(expected) { return res } @@ -3344,13 +3382,13 @@ func $$ErrorMessage(state, lookAhead int) string { if $$Def[state] == -2 { i := 0 - for $$Exca[i] != -1 || $$Exca[i+1] != state { + for $$Exca[i] != -1 || int($$Exca[i+1]) != state { i += 2 } // Look for tokens that we accept or reduce. for i += 2; $$Exca[i] >= 0; i += 2 { - tok := $$Exca[i] + tok := int($$Exca[i]) if tok < TOKSTART || $$Exca[i+1] == 0 { continue } @@ -3381,30 +3419,30 @@ func $$lex1(lex $$Lexer, lval *$$SymType) (char, token int) { token = 0 char = lex.Lex(lval) if char <= 0 { - token = $$Tok1[0] + token = int($$Tok1[0]) goto out } if char < len($$Tok1) { - token = $$Tok1[char] + token = int($$Tok1[char]) goto out } if char >= $$Private { if char < $$Private+len($$Tok2) { - token = $$Tok2[char-$$Private] + token = int($$Tok2[char-$$Private]) goto out } } for i := 0; i < len($$Tok3); i += 2 { - token = $$Tok3[i+0] + token = int($$Tok3[i+0]) if token == char { - token = $$Tok3[i+1] + token = int($$Tok3[i+1]) goto out } } out: if token == 0 { - token = $$Tok2[1] /* unknown char */ + token = int($$Tok2[1]) /* unknown char */ } if $$Debug >= 3 { __yyfmt__.Printf("lex %s(%d)\n", $$Tokname(token), uint(char)) @@ -3459,7 +3497,7 @@ $$stack: $$S[$$p].yys = $$state $$newstate: - $$n = $$Pact[$$state] + $$n = int($$Pact[$$state]) if $$n <= $$Flag { goto $$default /* simple state */ } @@ -3470,8 +3508,8 @@ $$newstate: if $$n < 0 || $$n >= $$Last { goto $$default } - $$n = $$Act[$$n] - if $$Chk[$$n] == $$token { /* valid shift */ + $$n = int($$Act[$$n]) + if int($$Chk[$$n]) == $$token { /* valid shift */ $$rcvr.char = -1 $$token = -1 $$VAL = $$rcvr.lval @@ -3484,7 +3522,7 @@ $$newstate: $$default: /* default state action */ - $$n = $$Def[$$state] + $$n = int($$Def[$$state]) if $$n == -2 { if $$rcvr.char < 0 { $$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval) @@ -3493,18 +3531,18 @@ $$default: /* look through exception table */ xi := 0 for { - if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state { + if $$Exca[xi+0] == -1 && int($$Exca[xi+1]) == $$state { break } xi += 2 } for xi += 2; ; xi += 2 { - $$n = $$Exca[xi+0] + $$n = int($$Exca[xi+0]) if $$n < 0 || $$n == $$token { break } } - $$n = $$Exca[xi+1] + $$n = int($$Exca[xi+1]) if $$n < 0 { goto ret0 } @@ -3526,10 +3564,10 @@ $$default: /* find a state where "error" is a legal shift action */ for $$p >= 0 { - $$n = $$Pact[$$S[$$p].yys] + $$ErrCode + $$n = int($$Pact[$$S[$$p].yys]) + $$ErrCode if $$n >= 0 && $$n < $$Last { - $$state = $$Act[$$n] /* simulate a shift of "error" */ - if $$Chk[$$state] == $$ErrCode { + $$state = int($$Act[$$n]) /* simulate a shift of "error" */ + if int($$Chk[$$state]) == $$ErrCode { goto $$stack } } @@ -3565,7 +3603,7 @@ $$default: $$pt := $$p _ = $$pt // guard against "declared and not used" - $$p -= $$R2[$$n] + $$p -= int($$R2[$$n]) // $$p is now the index of $0. Perform the default action. Iff the // reduced production is ε, $1 is possibly out of range. if $$p+1 >= len($$S) { @@ -3576,16 +3614,16 @@ $$default: $$VAL = $$S[$$p+1] /* consult goto table to find next state */ - $$n = $$R1[$$n] - $$g := $$Pgo[$$n] + $$n = int($$R1[$$n]) + $$g := int($$Pgo[$$n]) $$j := $$g + $$S[$$p].yys + 1 if $$j >= $$Last { - $$state = $$Act[$$g] + $$state = int($$Act[$$g]) } else { - $$state = $$Act[$$j] - if $$Chk[$$state] != -$$n { - $$state = $$Act[$$g] + $$state = int($$Act[$$j]) + if int($$Chk[$$state]) != -$$n { + $$state = int($$Act[$$g]) } } // dummy call; replaced with literal code