Home | History | Annotate | Download | only in gcprog
      1 // Do not edit. Bootstrap copy of /usr/local/google/buildbot/src/android/build-tools/out/obj/go/src/cmd/internal/gcprog/gcprog.go
      2 
      3 //line /usr/local/google/buildbot/src/android/build-tools/out/obj/go/src/cmd/internal/gcprog/gcprog.go:1
      4 // Copyright 2015 The Go Authors.  All rights reserved.
      5 // Use of this source code is governed by a BSD-style
      6 // license that can be found in the LICENSE file.
      7 
      8 // Package gcprog implements an encoder for packed GC pointer bitmaps,
      9 // known as GC programs.
     10 //
     11 // Program Format
     12 //
     13 // The GC program encodes a sequence of 0 and 1 bits indicating scalar or pointer words in an object.
     14 // The encoding is a simple Lempel-Ziv program, with codes to emit literal bits and to repeat the
     15 // last n bits c times.
     16 //
     17 // The possible codes are:
     18 //
     19 //	00000000: stop
     20 //	0nnnnnnn: emit n bits copied from the next (n+7)/8 bytes, least significant bit first
     21 //	10000000 n c: repeat the previous n bits c times; n, c are varints
     22 //	1nnnnnnn c: repeat the previous n bits c times; c is a varint
     23 //
     24 // The numbers n and c, when they follow a code, are encoded as varints
     25 // using the same encoding as encoding/binary's Uvarint.
     26 //
     27 package gcprog
     28 
     29 import (
     30 	"fmt"
     31 	"io"
     32 )
     33 
     34 const progMaxLiteral = 127 // maximum n for literal n bit code
     35 
     36 // A Writer is an encoder for GC programs.
     37 //
     38 // The typical use of a Writer is to call Init, maybe call Debug,
     39 // make a sequence of Ptr, Advance, Repeat, and Append calls
     40 // to describe the data type, and then finally call End.
     41 type Writer struct {
     42 	writeByte func(byte)
     43 	symoff    int
     44 	index     int64
     45 	b         [progMaxLiteral]byte
     46 	nb        int
     47 	debug     io.Writer
     48 	debugBuf  []byte
     49 }
     50 
     51 // Init initializes w to write a new GC program
     52 // by calling writeByte for each byte in the program.
     53 func (w *Writer) Init(writeByte func(byte)) {
     54 	w.writeByte = writeByte
     55 }
     56 
     57 // Debug causes the writer to print a debugging trace to out
     58 // during future calls to methods like Ptr, Advance, and End.
     59 // It also enables debugging checks during the encoding.
     60 func (w *Writer) Debug(out io.Writer) {
     61 	w.debug = out
     62 }
     63 
     64 // BitIndex returns the number of bits written to the bit stream so far.
     65 func (w *Writer) BitIndex() int64 {
     66 	return w.index
     67 }
     68 
     69 // byte writes the byte x to the output.
     70 func (w *Writer) byte(x byte) {
     71 	if w.debug != nil {
     72 		w.debugBuf = append(w.debugBuf, x)
     73 	}
     74 	w.writeByte(x)
     75 }
     76 
     77 // End marks the end of the program, writing any remaining bytes.
     78 func (w *Writer) End() {
     79 	w.flushlit()
     80 	w.byte(0)
     81 	if w.debug != nil {
     82 		index := progbits(w.debugBuf)
     83 		if index != w.index {
     84 			println("gcprog: End wrote program for", index, "bits, but current index is", w.index)
     85 			panic("gcprog: out of sync")
     86 		}
     87 	}
     88 }
     89 
     90 // Ptr emits a 1 into the bit stream at the given bit index.
     91 // that is, it records that the index'th word in the object memory is a pointer.
     92 // Any bits between the current index and the new index
     93 // are set to zero, meaning the corresponding words are scalars.
     94 func (w *Writer) Ptr(index int64) {
     95 	if index < w.index {
     96 		println("gcprog: Ptr at index", index, "but current index is", w.index)
     97 		panic("gcprog: invalid Ptr index")
     98 	}
     99 	w.ZeroUntil(index)
    100 	if w.debug != nil {
    101 		fmt.Fprintf(w.debug, "gcprog: ptr at %d\n", index)
    102 	}
    103 	w.lit(1)
    104 }
    105 
    106 // ShouldRepeat reports whether it would be worthwhile to
    107 // use a Repeat to describe c elements of n bits each,
    108 // compared to just emitting c copies of the n-bit description.
    109 func (w *Writer) ShouldRepeat(n, c int64) bool {
    110 	// Should we lay out the bits directly instead of
    111 	// encoding them as a repetition? Certainly if count==1,
    112 	// since there's nothing to repeat, but also if the total
    113 	// size of the plain pointer bits for the type will fit in
    114 	// 4 or fewer bytes, since using a repetition will require
    115 	// flushing the current bits plus at least one byte for
    116 	// the repeat size and one for the repeat count.
    117 	return c > 1 && c*n > 4*8
    118 }
    119 
    120 // Repeat emits an instruction to repeat the description
    121 // of the last n words c times (including the initial description, c+1 times in total).
    122 func (w *Writer) Repeat(n, c int64) {
    123 	if n == 0 || c == 0 {
    124 		return
    125 	}
    126 	w.flushlit()
    127 	if w.debug != nil {
    128 		fmt.Fprintf(w.debug, "gcprog: repeat %d  %d\n", n, c)
    129 	}
    130 	if n < 128 {
    131 		w.byte(0x80 | byte(n))
    132 	} else {
    133 		w.byte(0x80)
    134 		w.varint(n)
    135 	}
    136 	w.varint(c)
    137 	w.index += n * c
    138 }
    139 
    140 // ZeroUntil adds zeros to the bit stream until reaching the given index;
    141 // that is, it records that the words from the most recent pointer until
    142 // the index'th word are scalars.
    143 // ZeroUntil is usually called in preparation for a call to Repeat, Append, or End.
    144 func (w *Writer) ZeroUntil(index int64) {
    145 	if index < w.index {
    146 		println("gcprog: Advance", index, "but index is", w.index)
    147 		panic("gcprog: invalid Advance index")
    148 	}
    149 	skip := (index - w.index)
    150 	if skip == 0 {
    151 		return
    152 	}
    153 	if skip < 4*8 {
    154 		if w.debug != nil {
    155 			fmt.Fprintf(w.debug, "gcprog: advance to %d by literals\n", index)
    156 		}
    157 		for i := int64(0); i < skip; i++ {
    158 			w.lit(0)
    159 		}
    160 		return
    161 	}
    162 
    163 	if w.debug != nil {
    164 		fmt.Fprintf(w.debug, "gcprog: advance to %d by repeat\n", index)
    165 	}
    166 	w.lit(0)
    167 	w.flushlit()
    168 	w.Repeat(1, skip-1)
    169 }
    170 
    171 // Append emits the given GC program into the current output.
    172 // The caller asserts that the program emits n bits (describes n words),
    173 // and Append panics if that is not true.
    174 func (w *Writer) Append(prog []byte, n int64) {
    175 	w.flushlit()
    176 	if w.debug != nil {
    177 		fmt.Fprintf(w.debug, "gcprog: append prog for %d ptrs\n", n)
    178 		fmt.Fprintf(w.debug, "\t")
    179 	}
    180 	n1 := progbits(prog)
    181 	if n1 != n {
    182 		panic("gcprog: wrong bit count in append")
    183 	}
    184 	// The last byte of the prog terminates the program.
    185 	// Don't emit that, or else our own program will end.
    186 	for i, x := range prog[:len(prog)-1] {
    187 		if w.debug != nil {
    188 			if i > 0 {
    189 				fmt.Fprintf(w.debug, " ")
    190 			}
    191 			fmt.Fprintf(w.debug, "%02x", x)
    192 		}
    193 		w.byte(x)
    194 	}
    195 	if w.debug != nil {
    196 		fmt.Fprintf(w.debug, "\n")
    197 	}
    198 	w.index += n
    199 }
    200 
    201 // progbits returns the length of the bit stream encoded by the program p.
    202 func progbits(p []byte) int64 {
    203 	var n int64
    204 	for len(p) > 0 {
    205 		x := p[0]
    206 		p = p[1:]
    207 		if x == 0 {
    208 			break
    209 		}
    210 		if x&0x80 == 0 {
    211 			count := x &^ 0x80
    212 			n += int64(count)
    213 			p = p[(count+7)/8:]
    214 			continue
    215 		}
    216 		nbit := int64(x &^ 0x80)
    217 		if nbit == 0 {
    218 			nbit, p = readvarint(p)
    219 		}
    220 		var count int64
    221 		count, p = readvarint(p)
    222 		n += nbit * count
    223 	}
    224 	if len(p) > 0 {
    225 		println("gcprog: found end instruction after", n, "ptrs, with", len(p), "bytes remaining")
    226 		panic("gcprog: extra data at end of program")
    227 	}
    228 	return n
    229 }
    230 
    231 // readvarint reads a varint from p, returning the value and the remainder of p.
    232 func readvarint(p []byte) (int64, []byte) {
    233 	var v int64
    234 	var nb uint
    235 	for {
    236 		c := p[0]
    237 		p = p[1:]
    238 		v |= int64(c&^0x80) << nb
    239 		nb += 7
    240 		if c&0x80 == 0 {
    241 			break
    242 		}
    243 	}
    244 	return v, p
    245 }
    246 
    247 // lit adds a single literal bit to w.
    248 func (w *Writer) lit(x byte) {
    249 	if w.nb == progMaxLiteral {
    250 		w.flushlit()
    251 	}
    252 	w.b[w.nb] = x
    253 	w.nb++
    254 	w.index++
    255 }
    256 
    257 // varint emits the varint encoding of x.
    258 func (w *Writer) varint(x int64) {
    259 	if x < 0 {
    260 		panic("gcprog: negative varint")
    261 	}
    262 	for x >= 0x80 {
    263 		w.byte(byte(0x80 | x))
    264 		x >>= 7
    265 	}
    266 	w.byte(byte(x))
    267 }
    268 
    269 // flushlit flushes any pending literal bits.
    270 func (w *Writer) flushlit() {
    271 	if w.nb == 0 {
    272 		return
    273 	}
    274 	if w.debug != nil {
    275 		fmt.Fprintf(w.debug, "gcprog: flush %d literals\n", w.nb)
    276 		fmt.Fprintf(w.debug, "\t%v\n", w.b[:w.nb])
    277 		fmt.Fprintf(w.debug, "\t%02x", byte(w.nb))
    278 	}
    279 	w.byte(byte(w.nb))
    280 	var bits uint8
    281 	for i := 0; i < w.nb; i++ {
    282 		bits |= w.b[i] << uint(i%8)
    283 		if (i+1)%8 == 0 {
    284 			if w.debug != nil {
    285 				fmt.Fprintf(w.debug, " %02x", bits)
    286 			}
    287 			w.byte(bits)
    288 			bits = 0
    289 		}
    290 	}
    291 	if w.nb%8 != 0 {
    292 		if w.debug != nil {
    293 			fmt.Fprintf(w.debug, " %02x", bits)
    294 		}
    295 		w.byte(bits)
    296 	}
    297 	if w.debug != nil {
    298 		fmt.Fprintf(w.debug, "\n")
    299 	}
    300 	w.nb = 0
    301 }
    302