}
return 1 + count(n-1)
}
+
+func BenchmarkStackCopyNoCache(b *testing.B) {
+ c := make(chan bool)
+ for i := 0; i < b.N; i++ {
+ go func() {
+ count1(1000000)
+ c <- true
+ }()
+ <-c
+ }
+}
+
+func count1(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count2(n-1)
+}
+
+func count2(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count3(n-1)
+}
+
+func count3(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count4(n-1)
+}
+
+func count4(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count5(n-1)
+}
+
+func count5(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count6(n-1)
+}
+
+func count6(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count7(n-1)
+}
+
+func count7(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count8(n-1)
+}
+
+func count8(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count9(n-1)
+}
+
+func count9(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count10(n-1)
+}
+
+func count10(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count11(n-1)
+}
+
+func count11(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count12(n-1)
+}
+
+func count12(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count13(n-1)
+}
+
+func count13(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count14(n-1)
+}
+
+func count14(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count15(n-1)
+}
+
+func count15(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count16(n-1)
+}
+
+func count16(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count17(n-1)
+}
+
+func count17(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count18(n-1)
+}
+
+func count18(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count19(n-1)
+}
+
+func count19(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count20(n-1)
+}
+
+func count20(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count21(n-1)
+}
+
+func count21(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count22(n-1)
+}
+
+func count22(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count23(n-1)
+}
+
+func count23(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return 1 + count1(n-1)
+}
// cheaper than doing the hashing for a less associative
// cache.
if cache != nil {
- for _, ent := range cache.entries {
+ for i := range cache.entries {
// We check off first because we're more
// likely to have multiple entries with
// different offsets for the same targetpc
// than the other way around, so we'll usually
// fail in the first clause.
+ ent := &cache.entries[i]
if ent.off == off && ent.targetpc == targetpc {
return ent.val
}
// step advances to the next pc, value pair in the encoded table.
func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
- p, uvdelta := readvarint(p)
+ // For both uvdelta and pcdelta, the common case (~70%)
+ // is that they are a single byte. If so, avoid calling readvarint.
+ uvdelta := uint32(p[0])
if uvdelta == 0 && !first {
return nil, false
}
+ n := uint32(1)
+ if uvdelta&0x80 != 0 {
+ n, uvdelta = readvarint(p)
+ }
+ p = p[n:]
if uvdelta&1 != 0 {
uvdelta = ^(uvdelta >> 1)
} else {
uvdelta >>= 1
}
vdelta := int32(uvdelta)
- p, pcdelta := readvarint(p)
+ pcdelta := uint32(p[0])
+ n = 1
+ if pcdelta&0x80 != 0 {
+ n, pcdelta = readvarint(p)
+ }
+ p = p[n:]
*pc += uintptr(pcdelta * sys.PCQuantum)
*val += vdelta
return p, true
}
// readvarint reads a varint from p.
-func readvarint(p []byte) (newp []byte, val uint32) {
- var v, shift uint32
+func readvarint(p []byte) (read uint32, val uint32) {
+ var v, shift, n uint32
for {
- b := p[0]
- p = p[1:]
- v |= (uint32(b) & 0x7F) << shift
+ b := p[n]
+ n++
+ v |= uint32(b&0x7F) << (shift & 31)
if b&0x80 == 0 {
break
}
shift += 7
}
- return p, v
+ return n, v
}
type stackmap struct {
if n < 0 || n >= stkmap.n {
throw("stackmapdata: index out of range")
}
- return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+7)/8))))}
+ return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+7)>>3))))}
}
// inlinedCall is the encoding of entries in the FUNCDATA_InlTree table.