diff options
author | Ian Lance Taylor <iant@golang.org> | 2018-09-24 21:46:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-09-24 21:46:21 +0000 |
commit | dd931d9b48647e898dc80927c532ae93cc09e192 (patch) | |
tree | 71be2295cd79b8a182f6130611658db8628772d5 /libgo/go/compress | |
parent | 779d8a5ad09b01428726ea5a0e6c87bd9ac3c0e4 (diff) | |
download | gcc-dd931d9b48647e898dc80927c532ae93cc09e192.zip gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.gz gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.bz2 |
libgo: update to Go 1.11
Reviewed-on: https://go-review.googlesource.com/136435
gotools/:
* Makefile.am (mostlyclean-local): Run chmod on check-go-dir to
make sure it is writable.
(check-go-tools): Likewise.
(check-vet): Copy internal/objabi to check-vet-dir.
* Makefile.in: Rebuild.
From-SVN: r264546
Diffstat (limited to 'libgo/go/compress')
-rw-r--r-- | libgo/go/compress/bzip2/bzip2.go | 2 | ||||
-rw-r--r-- | libgo/go/compress/bzip2/huffman.go | 92 | ||||
-rw-r--r-- | libgo/go/compress/flate/deflate.go | 2 | ||||
-rw-r--r-- | libgo/go/compress/flate/inflate.go | 65 | ||||
-rw-r--r-- | libgo/go/compress/gzip/gzip.go | 12 | ||||
-rw-r--r-- | libgo/go/compress/gzip/gzip_test.go | 38 | ||||
-rw-r--r-- | libgo/go/compress/gzip/issue14937_test.go | 4 | ||||
-rw-r--r-- | libgo/go/compress/lzw/reader_test.go | 2 | ||||
-rw-r--r-- | libgo/go/compress/zlib/reader_test.go | 2 | ||||
-rw-r--r-- | libgo/go/compress/zlib/writer.go | 2 |
10 files changed, 126 insertions, 95 deletions
diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go index f07c7e8..c40129b 100644 --- a/libgo/go/compress/bzip2/bzip2.go +++ b/libgo/go/compress/bzip2/bzip2.go @@ -8,7 +8,7 @@ package bzip2 import "io" // There's no RFC for bzip2. I used the Wikipedia page for reference and a lot -// of guessing: http://en.wikipedia.org/wiki/Bzip2 +// of guessing: https://en.wikipedia.org/wiki/Bzip2 // The source code to pyflate was useful for debugging: // http://www.paul.sladen.org/projects/pyflate diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go index dbba9a5..36ae954 100644 --- a/libgo/go/compress/bzip2/huffman.go +++ b/libgo/go/compress/bzip2/huffman.go @@ -43,30 +43,34 @@ func (t *huffmanTree) Decode(br *bitReader) (v uint16) { if br.bits > 0 { // Get next bit - fast path. br.bits-- - bit = 0 - (uint16(br.n>>br.bits) & 1) + bit = uint16(br.n>>(br.bits&63)) & 1 } else { // Get next bit - slow path. // Use ReadBits to retrieve a single bit // from the underling io.ByteReader. - bit = 0 - uint16(br.ReadBits(1)) + bit = uint16(br.ReadBits(1)) } - // now - // bit = 0xffff if the next bit was 1 - // bit = 0x0000 if the next bit was 0 - // 1 means left, 0 means right. - // - // if bit == 0xffff { - // nodeIndex = node.left - // } else { - // nodeIndex = node.right - // } - nodeIndex = (bit & node.left) | (^bit & node.right) + // Trick a compiler into generating conditional move instead of branch, + // by making both loads unconditional. + l, r := node.left, node.right + + if bit == 1 { + nodeIndex = l + } else { + nodeIndex = r + } if nodeIndex == invalidNodeValue { // We found a leaf. Use the value of bit to decide // whether is a left or a right value. - return (bit & node.leftValue) | (^bit & node.rightValue) + l, r := node.leftValue, node.rightValue + if bit == 1 { + v = l + } else { + v = r + } + return } } } @@ -90,13 +94,24 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { // First we sort the code length assignments by ascending code length, // using the symbol value to break ties. - pairs := huffmanSymbolLengthPairs(make([]huffmanSymbolLengthPair, len(lengths))) + pairs := make([]huffmanSymbolLengthPair, len(lengths)) for i, length := range lengths { pairs[i].value = uint16(i) pairs[i].length = length } - sort.Sort(pairs) + sort.Slice(pairs, func(i, j int) bool { + if pairs[i].length < pairs[j].length { + return true + } + if pairs[i].length > pairs[j].length { + return false + } + if pairs[i].value < pairs[j].value { + return true + } + return false + }) // Now we assign codes to the symbols, starting with the longest code. // We keep the codes packed into a uint32, at the most-significant end. @@ -105,7 +120,7 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { code := uint32(0) length := uint8(32) - codes := huffmanCodes(make([]huffmanCode, len(lengths))) + codes := make([]huffmanCode, len(lengths)) for i := len(pairs) - 1; i >= 0; i-- { if length > pairs[i].length { length = pairs[i].length @@ -120,7 +135,9 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { // Now we can sort by the code so that the left half of each branch are // grouped together, recursively. - sort.Sort(codes) + sort.Slice(codes, func(i, j int) bool { + return codes[i].code < codes[j].code + }) t.nodes = make([]huffmanNode, len(codes)) _, err := buildHuffmanNode(&t, codes, 0) @@ -133,30 +150,6 @@ type huffmanSymbolLengthPair struct { length uint8 } -// huffmanSymbolLengthPair is used to provide an interface for sorting. -type huffmanSymbolLengthPairs []huffmanSymbolLengthPair - -func (h huffmanSymbolLengthPairs) Len() int { - return len(h) -} - -func (h huffmanSymbolLengthPairs) Less(i, j int) bool { - if h[i].length < h[j].length { - return true - } - if h[i].length > h[j].length { - return false - } - if h[i].value < h[j].value { - return true - } - return false -} - -func (h huffmanSymbolLengthPairs) Swap(i, j int) { - h[i], h[j] = h[j], h[i] -} - // huffmanCode contains a symbol, its code and code length. type huffmanCode struct { code uint32 @@ -164,21 +157,6 @@ type huffmanCode struct { value uint16 } -// huffmanCodes is used to provide an interface for sorting. -type huffmanCodes []huffmanCode - -func (n huffmanCodes) Len() int { - return len(n) -} - -func (n huffmanCodes) Less(i, j int) bool { - return n[i].code < n[j].code -} - -func (n huffmanCodes) Swap(i, j int) { - n[i], n[j] = n[j], n[i] -} - // buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in // the Huffman tree at the given level. It returns the index of the newly // constructed node. diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go index 4d6a535..8b92f15 100644 --- a/libgo/go/compress/flate/deflate.go +++ b/libgo/go/compress/flate/deflate.go @@ -720,7 +720,7 @@ func (w *Writer) Write(data []byte) (n int, err error) { // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. func (w *Writer) Flush() error { // For more about flushing: - // http://www.bolet.org/~pornin/deflate-flush.html + // https://www.bolet.org/~pornin/deflate-flush.html return w.d.syncFlush() } diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go index faa33cc..25e81f3 100644 --- a/libgo/go/compress/flate/inflate.go +++ b/libgo/go/compress/flate/inflate.go @@ -10,7 +10,7 @@ package flate import ( "bufio" "io" - mathbits "math/bits" + "math/bits" "strconv" "sync" ) @@ -113,7 +113,7 @@ type huffmanDecoder struct { // tree (i.e., neither over-subscribed nor under-subscribed). The exception is a // degenerate case where the tree has only a single symbol with length 1. Empty // trees are permitted. -func (h *huffmanDecoder) init(bits []int) bool { +func (h *huffmanDecoder) init(lengths []int) bool { // Sanity enables additional runtime tests during Huffman // table construction. It's intended to be used during // development to supplement the currently ad-hoc unit tests. @@ -127,7 +127,7 @@ func (h *huffmanDecoder) init(bits []int) bool { // compute min and max length. var count [maxCodeLen]int var min, max int - for _, n := range bits { + for _, n := range lengths { if n == 0 { continue } @@ -177,7 +177,7 @@ func (h *huffmanDecoder) init(bits []int) bool { link := nextcode[huffmanChunkBits+1] >> 1 h.links = make([][]uint32, huffmanNumChunks-link) for j := uint(link); j < huffmanNumChunks; j++ { - reverse := int(mathbits.Reverse16(uint16(j))) + reverse := int(bits.Reverse16(uint16(j))) reverse >>= uint(16 - huffmanChunkBits) off := j - uint(link) if sanity && h.chunks[reverse] != 0 { @@ -188,14 +188,14 @@ func (h *huffmanDecoder) init(bits []int) bool { } } - for i, n := range bits { + for i, n := range lengths { if n == 0 { continue } code := nextcode[n] nextcode[n]++ chunk := uint32(i<<huffmanValueShift | n) - reverse := int(mathbits.Reverse16(uint16(code))) + reverse := int(bits.Reverse16(uint16(code))) reverse >>= uint(16 - n) if n <= huffmanChunkBits { for off := reverse; off < len(h.chunks); off += 1 << uint(n) { @@ -557,7 +557,7 @@ readLiteral: return } } - dist = int(mathbits.Reverse8(uint8(f.b & 0x1F << 3))) + dist = int(bits.Reverse8(uint8(f.b & 0x1F << 3))) f.b >>= 5 f.nb -= 5 } else { @@ -629,10 +629,7 @@ func (f *decompressor) dataBlock() { nr, err := io.ReadFull(f.r, f.buf[0:4]) f.roffset += int64(nr) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } n := int(f.buf[0]) | int(f.buf[1])<<8 @@ -665,10 +662,7 @@ func (f *decompressor) copyData() { f.copyLen -= cnt f.dict.writeMark(cnt) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } @@ -690,13 +684,18 @@ func (f *decompressor) finishBlock() { f.step = (*decompressor).nextBlock } +// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF. +func noEOF(e error) error { + if e == io.EOF { + return io.ErrUnexpectedEOF + } + return e +} + func (f *decompressor) moreBits() error { c, err := f.r.ReadByte() if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return err + return noEOF(err) } f.roffset++ f.b |= uint32(c) << f.nb @@ -711,25 +710,37 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { // cases, the chunks slice will be 0 for the invalid sequence, leading it // satisfy the n == 0 check below. n := uint(h.min) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b for { - for f.nb < n { - if err := f.moreBits(); err != nil { - return 0, err + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + return 0, noEOF(err) } + f.roffset++ + b |= uint32(c) << (nb & 31) + nb += 8 } - chunk := h.chunks[f.b&(huffmanNumChunks-1)] + chunk := h.chunks[b&(huffmanNumChunks-1)] n = uint(chunk & huffmanCountMask) if n > huffmanChunkBits { - chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask] + chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask] n = uint(chunk & huffmanCountMask) } - if n <= f.nb { + if n <= nb { if n == 0 { + f.b = b + f.nb = nb f.err = CorruptInputError(f.roffset) return 0, f.err } - f.b >>= n - f.nb -= n + f.b = b >> (n & 31) + f.nb = nb - n return int(chunk >> huffmanValueShift), nil } } diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go index 0cc44c5..eaeb185 100644 --- a/libgo/go/compress/gzip/gzip.go +++ b/libgo/go/compress/gzip/gzip.go @@ -41,7 +41,7 @@ type Writer struct { // NewWriter returns a new Writer. // Writes to the returned writer are compressed and written to w. // -// It is the caller's responsibility to call Close on the WriteCloser when done. +// It is the caller's responsibility to call Close on the Writer when done. // Writes may be buffered and not flushed until Close. // // Callers that wish to set the fields in Writer.Header must do so before @@ -165,26 +165,26 @@ func (z *Writer) Write(p []byte) (int, error) { z.buf[8] = 4 } z.buf[9] = z.OS - n, z.err = z.w.Write(z.buf[:10]) + _, z.err = z.w.Write(z.buf[:10]) if z.err != nil { - return n, z.err + return 0, z.err } if z.Extra != nil { z.err = z.writeBytes(z.Extra) if z.err != nil { - return n, z.err + return 0, z.err } } if z.Name != "" { z.err = z.writeString(z.Name) if z.err != nil { - return n, z.err + return 0, z.err } } if z.Comment != "" { z.err = z.writeString(z.Comment) if z.err != nil { - return n, z.err + return 0, z.err } } if z.compressor == nil { diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go index 865c529..e16aba1 100644 --- a/libgo/go/compress/gzip/gzip_test.go +++ b/libgo/go/compress/gzip/gzip_test.go @@ -7,6 +7,7 @@ package gzip import ( "bufio" "bytes" + "io" "io/ioutil" "reflect" "testing" @@ -233,3 +234,40 @@ func TestWriterReset(t *testing.T) { t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String()) } } + +type limitedWriter struct { + N int +} + +func (l *limitedWriter) Write(p []byte) (n int, err error) { + if n := l.N; n < len(p) { + l.N = 0 + return n, io.ErrShortWrite + } + l.N -= len(p) + return len(p), nil +} + +// Write should never return more bytes than the input slice. +func TestLimitedWrite(t *testing.T) { + msg := []byte("a") + + for lim := 2; lim < 20; lim++ { + z := NewWriter(&limitedWriter{lim}) + if n, _ := z.Write(msg); n > len(msg) { + t.Errorf("Write() = %d, want %d or less", n, len(msg)) + } + + z.Reset(&limitedWriter{lim}) + z.Header = Header{ + Comment: "comment", + Extra: []byte("extra"), + ModTime: time.Now(), + Name: "name", + OS: 1, + } + if n, _ := z.Write(msg); n > len(msg) { + t.Errorf("Write() = %d, want %d or less", n, len(msg)) + } + } +} diff --git a/libgo/go/compress/gzip/issue14937_test.go b/libgo/go/compress/gzip/issue14937_test.go index 30c1390..7a19672 100644 --- a/libgo/go/compress/gzip/issue14937_test.go +++ b/libgo/go/compress/gzip/issue14937_test.go @@ -21,6 +21,10 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) { if testenv.Builder() == "" { t.Skip("skipping test on non-builder") } + if !testenv.HasSrc() { + t.Skip("skipping; no GOROOT available") + } + goroot, err := filepath.EvalSymlinks(runtime.GOROOT()) if err != nil { t.Fatal("error evaluating GOROOT: ", err) diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go index f8974de..98bbfbb 100644 --- a/libgo/go/compress/lzw/reader_test.go +++ b/libgo/go/compress/lzw/reader_test.go @@ -66,7 +66,7 @@ var lzwTests = []lzwTest{ "\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04", io.ErrUnexpectedEOF, }, - // This example comes from http://en.wikipedia.org/wiki/Graphics_Interchange_Format. + // This example comes from https://en.wikipedia.org/wiki/Graphics_Interchange_Format. { "gif;LSB;8", "\x28\xff\xff\xff\x28\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go index 7e27aec..70e33ba 100644 --- a/libgo/go/compress/zlib/reader_test.go +++ b/libgo/go/compress/zlib/reader_test.go @@ -19,7 +19,7 @@ type zlibTest struct { } // Compare-to-golden test data was generated by the ZLIB example program at -// http://www.zlib.net/zpipe.c +// https://www.zlib.net/zpipe.c var zlibTests = []zlibTest{ { diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go index 1620c00..a7b2194 100644 --- a/libgo/go/compress/zlib/writer.go +++ b/libgo/go/compress/zlib/writer.go @@ -38,7 +38,7 @@ type Writer struct { // NewWriter creates a new Writer. // Writes to the returned Writer are compressed and written to w. // -// It is the caller's responsibility to call Close on the WriteCloser when done. +// It is the caller's responsibility to call Close on the Writer when done. // Writes may be buffered and not flushed until Close. func NewWriter(w io.Writer) *Writer { z, _ := NewWriterLevelDict(w, DefaultCompression, nil) |