Bläddra i källkod

codec: decRd: eliminate one unnecessary function call trampoline in IO path

Ugorji Nwoke 6 år sedan
förälder
incheckning
7a87ebc0e4
1 ändrade filer med 193 tillägg och 116 borttagningar
  1. 193 116
      codec/reader.go

+ 193 - 116
codec/reader.go

@@ -1030,178 +1030,149 @@ type decRd struct {
 
 // numread, track and stopTrack are always inlined, as they just check int fields, etc.
 
-/*
-func (z *decRd) numread() int {
-	switch z.typ {
-	case entryTypeBytes:
+// the if/else-if/else block is expensive to inline.
+// Each node of this construct costs a lot and dominates the budget.
+// Best to only do an if fast-path else block (so fast-path is inlined).
+// This is irrespective of inlineExtraCallCost set in $GOROOT/src/cmd/compile/internal/gc/inl.go
+//
+// In decRd methods below, we delegate all IO functions into their own methods.
+// This allows for the inlining of the common path when z.bytes=true.
+// Go 1.12+ supports inlining methods with up to 1 inlined function (or 2 if no other constructs).
+//
+// However, up through Go 1.13, decRd's readXXX, skip and unreadXXX methods are not inlined.
+// Consequently, there is no benefit to do the xxxIO methods for decRd at this time.
+// Instead, we have a if/else-if/else block so that IO calls do not have to jump through
+// a second unnecessary function call.
+
+// func (z *decRd) release() {
+// 	if z.bytes {
+// 	} else if z.bufio {
+// 		z.bi.release()
+// 	} else {
+// 		z.ri.release()
+// 	}
+// }
+func (z *decRd) numread() uint {
+	if z.bytes {
 		return z.rb.numread()
-	case entryTypeIo:
-		return z.ri.numread()
-	default:
+	} else if z.bufio {
 		return z.bi.numread()
+	} else {
+		return z.ri.numread()
 	}
 }
 func (z *decRd) track() {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		z.rb.track()
-	case entryTypeIo:
-		z.ri.track()
-	default:
+	} else if z.bufio {
 		z.bi.track()
+	} else {
+		z.ri.track()
 	}
 }
 func (z *decRd) stopTrack() []byte {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		return z.rb.stopTrack()
-	case entryTypeIo:
-		return z.ri.stopTrack()
-	default:
+	} else if z.bufio {
 		return z.bi.stopTrack()
+	} else {
+		return z.ri.stopTrack()
 	}
 }
 
 func (z *decRd) unreadn1() {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		z.rb.unreadn1()
-	case entryTypeIo:
-		z.ri.unreadn1()
-	default:
+	} else if z.bufio {
 		z.bi.unreadn1()
+	} else {
+		z.ri.unreadn1() // not inlined
 	}
 }
-func (z *decRd) readx(n int) []byte {
-	switch z.typ {
-	case entryTypeBytes:
+
+func (z *decRd) readn(num uint8) [7]byte {
+	if z.bytes {
+		return z.rb.readn(num)
+	}
+	if z.bufio {
+		return z.bi.readn(num)
+	}
+	return z.ri.readn(num)
+}
+
+func (z *decRd) readx(n uint) []byte {
+	if z.bytes {
 		return z.rb.readx(n)
-	case entryTypeIo:
-		return z.ri.readx(n)
-	default:
+	}
+	if z.bufio {
 		return z.bi.readx(n)
 	}
+	return z.ri.readx(n)
 }
+
 func (z *decRd) readb(s []byte) {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		z.rb.readb(s)
-	case entryTypeIo:
-		z.ri.readb(s)
-	default:
+	} else if z.bufio {
 		z.bi.readb(s)
+	} else {
+		z.ri.readb(s)
 	}
 }
+
 func (z *decRd) readn1() uint8 {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		return z.rb.readn1()
-	case entryTypeIo:
-		return z.ri.readn1()
-	default:
+	}
+	if z.bufio {
 		return z.bi.readn1()
 	}
+	return z.ri.readn1()
 }
+
 func (z *decRd) skip(accept *bitset256) (token byte) {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		return z.rb.skip(accept)
-	case entryTypeIo:
-		return z.ri.skip(accept)
-	default:
+	}
+	if z.bufio {
 		return z.bi.skip(accept)
 	}
+	return z.ri.skip(accept)
 }
+
 func (z *decRd) readTo(accept *bitset256) (out []byte) {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		return z.rb.readTo(accept)
-	case entryTypeIo:
-		return z.ri.readTo(accept)
-	default:
+	}
+	if z.bufio {
 		return z.bi.readTo(accept)
 	}
+	return z.ri.readTo(accept)
 }
+
 func (z *decRd) readUntil(stop byte) (out []byte) {
-	switch z.typ {
-	case entryTypeBytes:
+	if z.bytes {
 		return z.rb.readUntil(stop)
-	case entryTypeIo:
-		return z.ri.readUntil(stop)
-	default:
+	}
+	if z.bufio {
 		return z.bi.readUntil(stop)
 	}
+	return z.ri.readUntil(stop)
 }
 
-*/
-
-// the if/else-if/else block is expensive to inline.
-// Each node of this construct costs a lot and dominates the budget.
-// Best to only do an if fast-path else block (so fast-path is inlined).
-// This is irrespective of inlineExtraCallCost set in $GOROOT/src/cmd/compile/internal/gc/inl.go
-//
-// In decRd methods below, we delegate all IO functions into their own methods.
-// This allows for the inlining of the common path when z.bytes=true.
-// Go 1.12+ supports inlining methods with up to 1 inlined function (or 2 if no other constructs).
-
-// func (z *decRd) release() {
-// 	if z.bytes {
-// 	} else if z.bufio {
-// 		z.bi.release()
-// 	} else {
-// 		z.ri.release()
-// 	}
-// }
-func (z *decRd) numread() uint {
-	if z.bytes {
-		return z.rb.numread()
-	} else if z.bufio {
-		return z.bi.numread()
-	} else {
-		return z.ri.numread()
-	}
-}
-func (z *decRd) track() {
-	if z.bytes {
-		z.rb.track()
-	} else if z.bufio {
-		z.bi.track()
-	} else {
-		z.ri.track()
-	}
-}
-func (z *decRd) stopTrack() []byte {
+/*
+func (z *decRd) unreadn1() {
 	if z.bytes {
-		return z.rb.stopTrack()
-	} else if z.bufio {
-		return z.bi.stopTrack()
+		z.rb.unreadn1()
 	} else {
-		return z.ri.stopTrack()
+		z.unreadn1IO()
 	}
 }
-
-// func (z *decRd) unreadn1() {
-// 	if z.bytes {
-// 		z.rb.unreadn1()
-// 	} else {
-// 		z.unreadn1IO()
-// 	}
-// }
-// func (z *decRd) unreadn1IO() {
-// 	if z.bufio {
-// 		z.bi.unreadn1()
-// 	} else {
-// 		z.ri.unreadn1()
-// 	}
-// }
-
-func (z *decRd) unreadn1() {
-	if z.bytes {
-		z.rb.unreadn1()
-	} else if z.bufio {
+func (z *decRd) unreadn1IO() {
+	if z.bufio {
 		z.bi.unreadn1()
 	} else {
-		z.ri.unreadn1() // not inlined
+		z.ri.unreadn1()
 	}
 }
 
@@ -1299,6 +1270,112 @@ func (z *decRd) readUntilIO(stop byte) (out []byte) {
 	}
 	return z.ri.readUntil(stop)
 }
+*/
+
+/*
+func (z *decRd) numread() int {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.numread()
+	case entryTypeIo:
+		return z.ri.numread()
+	default:
+		return z.bi.numread()
+	}
+}
+func (z *decRd) track() {
+	switch z.typ {
+	case entryTypeBytes:
+		z.rb.track()
+	case entryTypeIo:
+		z.ri.track()
+	default:
+		z.bi.track()
+	}
+}
+func (z *decRd) stopTrack() []byte {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.stopTrack()
+	case entryTypeIo:
+		return z.ri.stopTrack()
+	default:
+		return z.bi.stopTrack()
+	}
+}
+
+func (z *decRd) unreadn1() {
+	switch z.typ {
+	case entryTypeBytes:
+		z.rb.unreadn1()
+	case entryTypeIo:
+		z.ri.unreadn1()
+	default:
+		z.bi.unreadn1()
+	}
+}
+func (z *decRd) readx(n int) []byte {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.readx(n)
+	case entryTypeIo:
+		return z.ri.readx(n)
+	default:
+		return z.bi.readx(n)
+	}
+}
+func (z *decRd) readb(s []byte) {
+	switch z.typ {
+	case entryTypeBytes:
+		z.rb.readb(s)
+	case entryTypeIo:
+		z.ri.readb(s)
+	default:
+		z.bi.readb(s)
+	}
+}
+func (z *decRd) readn1() uint8 {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.readn1()
+	case entryTypeIo:
+		return z.ri.readn1()
+	default:
+		return z.bi.readn1()
+	}
+}
+func (z *decRd) skip(accept *bitset256) (token byte) {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.skip(accept)
+	case entryTypeIo:
+		return z.ri.skip(accept)
+	default:
+		return z.bi.skip(accept)
+	}
+}
+func (z *decRd) readTo(accept *bitset256) (out []byte) {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.readTo(accept)
+	case entryTypeIo:
+		return z.ri.readTo(accept)
+	default:
+		return z.bi.readTo(accept)
+	}
+}
+func (z *decRd) readUntil(stop byte) (out []byte) {
+	switch z.typ {
+	case entryTypeBytes:
+		return z.rb.readUntil(stop)
+	case entryTypeIo:
+		return z.ri.readUntil(stop)
+	default:
+		return z.bi.readUntil(stop)
+	}
+}
+
+*/
 
 var _ decReader = (*decRd)(nil)