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