]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use bufio.Reader directly in lexer
authorDavid Crawshaw <crawshaw@golang.org>
Fri, 11 Mar 2016 18:39:20 +0000 (13:39 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Fri, 11 Mar 2016 21:27:23 +0000 (21:27 +0000)
Removes an intermediate layer of functions that was clogging up a
corner of the compiler's profile graph.

I can't measure a performance improvement running a large build
like jujud, but the profile reports less total time spent in
gc.(*lexer).getr.

Change-Id: I3000585cfcb0f9729d3a3859e9023690a6528591
Reviewed-on: https://go-review.googlesource.com/20565
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/export.go
src/cmd/compile/internal/gc/lex.go
src/cmd/compile/internal/gc/parser.go
src/cmd/internal/obj/util.go
test/syntax/ddd.go [new file with mode: 0644]

index e6f76e72515985c1ff5bb21ed3780b0d0eefe908..a68281f5a71bd3446b8bafcd4bc2760c9387067c 100644 (file)
@@ -8,8 +8,8 @@
 package gc
 
 import (
+       "bufio"
        "cmd/compile/internal/big"
-       "cmd/internal/obj"
        "encoding/binary"
        "fmt"
 )
@@ -20,7 +20,7 @@ import (
 // changes to bimport.go and bexport.go.
 
 // Import populates importpkg from the serialized package data.
-func Import(in *obj.Biobuf) {
+func Import(in *bufio.Reader) {
        p := importer{in: in}
        p.buf = p.bufarray[:]
 
@@ -137,7 +137,7 @@ func idealType(typ *Type) *Type {
 }
 
 type importer struct {
-       in       *obj.Biobuf
+       in       *bufio.Reader
        buf      []byte   // for reading strings
        bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
        pkgList  []*Pkg
@@ -855,16 +855,16 @@ func (p *importer) ReadByte() (byte, error) {
 // byte is the bottleneck interface for reading from p.in.
 // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
 func (p *importer) byte() byte {
-       c := obj.Bgetc(p.in)
+       c, err := p.in.ReadByte()
        p.read++
-       if c < 0 {
-               Fatalf("importer: read error")
+       if err != nil {
+               Fatalf("importer: read error: %v", err)
        }
        if c == '|' {
-               c = obj.Bgetc(p.in)
+               c, err = p.in.ReadByte()
                p.read++
-               if c < 0 {
-                       Fatalf("importer: read error")
+               if err != nil {
+                       Fatalf("importer: read error: %v", err)
                }
                switch c {
                case 'S':
@@ -875,5 +875,5 @@ func (p *importer) byte() byte {
                        Fatalf("importer: unexpected escape sequence in export data")
                }
        }
-       return byte(c)
+       return c
 }
index 9a1f1a6aaf3a41cea3dbe558efefdf8adaa96a88..69b969dfdfada91ef5e9131239a7f459ffa80229 100644 (file)
@@ -5,6 +5,7 @@
 package gc
 
 import (
+       "bufio"
        "bytes"
        "cmd/internal/obj"
        "fmt"
@@ -387,7 +388,7 @@ func dumpexport() {
                        pkgMap = make(map[string]*Pkg)
                        pkgs = nil
                        importpkg = mkpkg("")
-                       Import(obj.Binitr(&copy)) // must not die
+                       Import(bufio.NewReader(&copy)) // must not die
                        importpkg = nil
                        pkgs = savedPkgs
                        pkgMap = savedPkgMap
index b9bbe559737bbbf74d0bd3db96a5f54e3cf9aec5..f8ec00079f9edca18a32a13f6f0929cc7b5d5c6b 100644 (file)
@@ -7,6 +7,7 @@
 package gc
 
 import (
+       "bufio"
        "cmd/compile/internal/ssa"
        "cmd/internal/obj"
        "flag"
@@ -335,15 +336,16 @@ func Main() {
 
                linehistpush(infile)
 
-               bin, err := obj.Bopenr(infile)
+               f, err := os.Open(infile)
                if err != nil {
                        fmt.Printf("open %s: %v\n", infile, err)
                        errorexit()
                }
+               bin := bufio.NewReader(f)
 
                // Skip initial BOM if present.
-               if obj.Bgetrune(bin) != BOM {
-                       obj.Bungetrune(bin)
+               if r, _, _ := bin.ReadRune(); r != BOM {
+                       bin.UnreadRune()
                }
 
                block = 1
@@ -362,7 +364,7 @@ func Main() {
                lexlineno++
 
                linehistpop()
-               obj.Bterm(bin)
+               f.Close()
        }
 
        testdclstack()
@@ -541,7 +543,7 @@ func saveerrors() {
        nerrors = 0
 }
 
-func arsize(b *obj.Biobuf, name string) int {
+func arsize(b *bufio.Reader, name string) int {
        var buf [ArhdrSize]byte
        if _, err := io.ReadFull(b, buf[:]); err != nil {
                return -1
@@ -555,14 +557,11 @@ func arsize(b *obj.Biobuf, name string) int {
        return i
 }
 
-func skiptopkgdef(b *obj.Biobuf) bool {
+func skiptopkgdef(b *bufio.Reader) bool {
        // archive header
-       p := obj.Brdline(b, '\n')
-       if p == "" {
-               return false
-       }
-       if obj.Blinelen(b) != 8 {
-               return false
+       p, err := b.ReadString('\n')
+       if err != nil {
+               log.Fatalf("reading input: %v", err)
        }
        if p != "!<arch>\n" {
                return false
@@ -672,10 +671,10 @@ func loadsys() {
        incannedimport = 1
 
        importpkg = Runtimepkg
-       parse_import(obj.Binitr(strings.NewReader(runtimeimport)), nil)
+       parse_import(bufio.NewReader(strings.NewReader(runtimeimport)), nil)
 
        importpkg = unsafepkg
-       parse_import(obj.Binitr(strings.NewReader(unsafeimport)), nil)
+       parse_import(bufio.NewReader(strings.NewReader(unsafeimport)), nil)
 
        importpkg = nil
        incannedimport = 0
@@ -761,12 +760,13 @@ func importfile(f *Val, indent []byte) {
 
        importpkg.Imported = true
 
-       imp, err := obj.Bopenr(file)
+       impf, err := os.Open(file)
        if err != nil {
                Yyerror("can't open import: %q: %v", path_, err)
                errorexit()
        }
-       defer obj.Bterm(imp)
+       defer impf.Close()
+       imp := bufio.NewReader(impf)
 
        if strings.HasSuffix(file, ".a") {
                if !skiptopkgdef(imp) {
@@ -776,7 +776,13 @@ func importfile(f *Val, indent []byte) {
        }
 
        // check object header
-       p := obj.Brdstr(imp, '\n', 1)
+       p, err := imp.ReadString('\n')
+       if err != nil {
+               log.Fatalf("reading input: %v", err)
+       }
+       if len(p) > 0 {
+               p = p[:len(p)-1]
+       }
 
        if p != "empty archive" {
                if !strings.HasPrefix(p, "go object ") {
@@ -800,23 +806,23 @@ func importfile(f *Val, indent []byte) {
        // $$B\n (new format): import directly, then feed the lexer a dummy statement
 
        // look for $$
-       var c int
+       var c byte
        for {
-               c = obj.Bgetc(imp)
-               if c < 0 {
+               c, err = imp.ReadByte()
+               if err != nil {
                        break
                }
                if c == '$' {
-                       c = obj.Bgetc(imp)
-                       if c == '$' || c < 0 {
+                       c, err = imp.ReadByte()
+                       if c == '$' || err != nil {
                                break
                        }
                }
        }
 
        // get character after $$
-       if c >= 0 {
-               c = obj.Bgetc(imp)
+       if err == nil {
+               c, _ = imp.ReadByte()
        }
 
        switch c {
@@ -826,7 +832,7 @@ func importfile(f *Val, indent []byte) {
 
        case 'B':
                // new export format
-               obj.Bgetc(imp) // skip \n after $$B
+               imp.ReadByte() // skip \n after $$B
                Import(imp)
 
        default:
@@ -879,9 +885,7 @@ const (
 
 type lexer struct {
        // source
-       bin    *obj.Biobuf
-       peekr1 rune
-       peekr2 rune // second peekc for ...
+       bin *bufio.Reader
 
        nlsemi bool // if set, '\n' and EOF translate to ';'
 
@@ -1025,8 +1029,9 @@ l0:
                }
 
                if c1 == '.' {
-                       c1 = l.getr()
-                       if c1 == '.' {
+                       p, err := l.bin.Peek(1)
+                       if err == nil && p[0] == '.' {
+                               l.getr()
                                c = LDDD
                                goto lx
                        }
@@ -1886,49 +1891,26 @@ func pragcgo(text string) {
 }
 
 func (l *lexer) getr() rune {
-       // unread rune != 0 available
-       if r := l.peekr1; r != 0 {
-               l.peekr1 = l.peekr2
-               l.peekr2 = 0
-               if r == '\n' && importpkg == nil {
-                       lexlineno++
+redo:
+       r, w, err := l.bin.ReadRune()
+       if err != nil {
+               if err != io.EOF {
+                       Fatalf("io error: %v", err)
                }
-               return r
+               return -1
        }
-
-redo:
-       // common case: 7bit ASCII
-       c := obj.Bgetc(l.bin)
-       if c < utf8.RuneSelf {
-               if c == 0 {
-                       yyerrorl(lexlineno, "illegal NUL byte")
-                       return 0
-               }
-               if c == '\n' && importpkg == nil {
+       switch r {
+       case 0:
+               yyerrorl(lexlineno, "illegal NUL byte")
+       case '\n':
+               if importpkg == nil {
                        lexlineno++
                }
-               return rune(c)
-       }
-       // c >= utf8.RuneSelf
-
-       // uncommon case: non-ASCII
-       var buf [utf8.UTFMax]byte
-       buf[0] = byte(c)
-       buf[1] = byte(obj.Bgetc(l.bin))
-       i := 2
-       for ; i < len(buf) && !utf8.FullRune(buf[:i]); i++ {
-               buf[i] = byte(obj.Bgetc(l.bin))
-       }
-
-       r, w := utf8.DecodeRune(buf[:i])
-       if r == utf8.RuneError && w == 1 {
-               // The string conversion here makes a copy for passing
-               // to fmt.Printf, so that buf itself does not escape and
-               // can be allocated on the stack.
-               yyerrorl(lexlineno, "illegal UTF-8 sequence % x", string(buf[:i]))
-       }
-
-       if r == BOM {
+       case utf8.RuneError:
+               if w == 1 {
+                       yyerrorl(lexlineno, "illegal UTF-8 sequence")
+               }
+       case BOM:
                yyerrorl(lexlineno, "Unicode (UTF-8) BOM in middle of file")
                goto redo
        }
@@ -1937,8 +1919,7 @@ redo:
 }
 
 func (l *lexer) ungetr(r rune) {
-       l.peekr2 = l.peekr1
-       l.peekr1 = r
+       l.bin.UnreadRune()
        if r == '\n' && importpkg == nil {
                lexlineno--
        }
index fa7e70c43f64f4eb8b108921a811ebeac22dfd40..b2584c80d67e563a0ca9542f5865c44acdb07c9c 100644 (file)
@@ -13,7 +13,7 @@ package gc
 // to handle optional commas and semicolons before a closing ) or } .
 
 import (
-       "cmd/internal/obj"
+       "bufio"
        "fmt"
        "strconv"
        "strings"
@@ -22,12 +22,12 @@ import (
 const trace = false // if set, parse tracing can be enabled with -x
 
 // parse_import parses the export data of a package that is imported.
-func parse_import(bin *obj.Biobuf, indent []byte) {
+func parse_import(bin *bufio.Reader, indent []byte) {
        newparser(bin, indent).import_package()
 }
 
 // parse_file parses a single Go source file.
-func parse_file(bin *obj.Biobuf) {
+func parse_file(bin *bufio.Reader) {
        newparser(bin, nil).file()
 }
 
@@ -40,7 +40,7 @@ type parser struct {
 
 // newparser returns a new parser ready to parse from src.
 // indent is the initial indentation for tracing output.
-func newparser(src *obj.Biobuf, indent []byte) *parser {
+func newparser(src *bufio.Reader, indent []byte) *parser {
        var p parser
        p.bin = src
        p.indent = indent
index 4c37f76ca9cf63e8878503b9584bc9ac8e433834..bd533a003638eacf0ec800812cc22bdce84f22bd 100644 (file)
@@ -129,18 +129,6 @@ func Bgetc(b *Biobuf) int {
        return int(c)
 }
 
-func Bgetrune(b *Biobuf) int {
-       r, _, err := b.r.ReadRune()
-       if err != nil {
-               return -1
-       }
-       return int(r)
-}
-
-func Bungetrune(b *Biobuf) {
-       b.r.UnreadRune()
-}
-
 func (b *Biobuf) Read(p []byte) (int, error) {
        return b.r.Read(p)
 }
@@ -158,17 +146,6 @@ func Brdline(b *Biobuf, delim int) string {
        return string(s)
 }
 
-func Brdstr(b *Biobuf, delim int, cut int) string {
-       s, err := b.r.ReadString(byte(delim))
-       if err != nil {
-               log.Fatalf("reading input: %v", err)
-       }
-       if len(s) > 0 && cut > 0 {
-               s = s[:len(s)-1]
-       }
-       return s
-}
-
 func Blinelen(b *Biobuf) int {
        return b.linelen
 }
diff --git a/test/syntax/ddd.go b/test/syntax/ddd.go
new file mode 100644 (file)
index 0000000..476ae22
--- /dev/null
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f() {
+       g(f..3) // ERROR "unexpected literal \.3, expecting name or \("
+}