Commit 93447c73 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent daa5bbe8
...@@ -126,16 +126,14 @@ func main() { ...@@ -126,16 +126,14 @@ func main() {
// prologue // prologue
f := fv[0] // proto.go comes first f := fv[0] // proto.go comes first
buf := Buffer{} buf := Buffer{}
// XXX vvv -> emit buf.emit(`// DO NOT EDIT - AUTOGENERATED (by protogen.go)
buf.WriteString(`// DO NOT EDIT - AUTOGENERATED (by protogen.go)
package neo package neo
import ( import (
"encoding/binary" "encoding/binary"
"reflect" "reflect"
"sort" "sort"
) )`)
`)
pktTypeRegistry := map[int]string{} // pktCode -> typename pktTypeRegistry := map[int]string{} // pktCode -> typename
...@@ -474,6 +472,7 @@ type decoder struct { ...@@ -474,6 +472,7 @@ type decoder struct {
n int // current read position in data. n int // current read position in data.
nread int // numeric part of total nread return nread int // numeric part of total nread return
nreadStk []int // stack to push/pop nread on loops
// overflow check state and size that will be checked for overflow at // overflow check state and size that will be checked for overflow at
// current overflow check point // current overflow check point
...@@ -529,7 +528,6 @@ func (d *decoder) resetPos() { ...@@ -529,7 +528,6 @@ func (d *decoder) resetPos() {
} }
} }
// XXX place?
// mark current place for delayed insertion of overflow check code // mark current place for delayed insertion of overflow check code
// //
// delayed: because we go forward in decode path scanning ahead as far as we // delayed: because we go forward in decode path scanning ahead as far as we
...@@ -543,8 +541,8 @@ func (d *decoder) resetPos() { ...@@ -543,8 +541,8 @@ func (d *decoder) resetPos() {
// //
// it is inserted // it is inserted
// - before reading a variable sized item // - before reading a variable sized item
// - in the beginning of a loop inside // - in the beginning of a loop inside (via overflowCheckLoopEntry)
// - right after loop exit // - right after loop exit (via overflowCheckLoopExit)
func (d *decoder) overflowCheck() { func (d *decoder) overflowCheck() {
// nop if we know overflow was already checked // nop if we know overflow was already checked
if d.overflow.checked { if d.overflow.checked {
...@@ -561,7 +559,7 @@ func (d *decoder) overflowCheck() { ...@@ -561,7 +559,7 @@ func (d *decoder) overflowCheck() {
// otherwise accumulate into var(nread) at runtime. // otherwise accumulate into var(nread) at runtime.
// we do not break runtime accumulation into numeric & symbolic // we do not break runtime accumulation into numeric & symbolic
// parts, because just above whole expression num + symbolic // parts, because just above whole expression num + symbolic
// was just given to compiler so compiler shoud have it just computed. // was just given to compiler so compiler should have it just computed.
// XXX recheck ^^^ actually good with the compiler // XXX recheck ^^^ actually good with the compiler
if d.overflow.checkSize.IsNumeric() { if d.overflow.checkSize.IsNumeric() {
d.nread += d.overflow.checkSize.num d.nread += d.overflow.checkSize.num
...@@ -576,6 +574,39 @@ func (d *decoder) overflowCheck() { ...@@ -576,6 +574,39 @@ func (d *decoder) overflowCheck() {
d.buf.Reset() d.buf.Reset()
} }
// overflowCheck variant that should be called at the beginning of a loop inside
func (d *decoder) overflowCheckLoopEntry() {
if d.overflow.checked {
return
}
d.overflowCheck()
// upon entering a loop organize new nread, because what was statically
// read inside loop should be multiplied by loop len in parent context.
d.nreadStk = append(d.nreadStk, d.nread)
d.nread = 0
}
// overflowCheck variant that should be called right after loop exit
func (d *decoder) overflowCheckLoopExit(loopLenExpr string) {
if d.overflow.checked {
return
}
d.overflowCheck()
// merge-in numeric nread updates from loop
if d.nread != 0 {
d.emit("%v += %v * %v", d.var_("nread"), loopLenExpr, d.nread)
}
l := len(d.nreadStk)
d.nread = d.nreadStk[l-1]
d.nreadStk = d.nreadStk[:l-1]
}
func (d *decoder) generatedCode() string { func (d *decoder) generatedCode() string {
// flush for last overflow check point // flush for last overflow check point
d.overflowCheck() d.overflowCheck()
...@@ -590,7 +621,6 @@ func (d *decoder) generatedCode() string { ...@@ -590,7 +621,6 @@ func (d *decoder) generatedCode() string {
code.Write(d.bufDone.Bytes()) code.Write(d.bufDone.Bytes())
// epilogue // epilogue
//retexpr := fmt.Sprintf("%v", d.n)
retexpr := fmt.Sprintf("%v", d.nread) retexpr := fmt.Sprintf("%v", d.nread)
if d.varUsed["nread"] { if d.varUsed["nread"] {
retexpr += fmt.Sprintf(" + int(%v)", d.var_("nread")) retexpr += fmt.Sprintf(" + int(%v)", d.var_("nread"))
...@@ -772,28 +802,13 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) ...@@ -772,28 +802,13 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object)
d.emit("%v= make(%v, l)", assignto, typeName(typ)) d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("for i := 0; uint32(i) < l; i++ {") d.emit("for i := 0; uint32(i) < l; i++ {")
d.emit("a := &%s[i]", assignto) d.emit("a := &%s[i]", assignto)
d.overflowCheckLoopEntry()
d.overflowCheck() // -> overflowCheckLoopEntry ?
var nreadCur int
if !d.overflow.checked { // TODO merge-in into overflow checker
nreadCur = d.nread
d.nread = 0
}
codegenType("(*a)", typ.Elem(), obj, d) codegenType("(*a)", typ.Elem(), obj, d)
d.resetPos() d.resetPos()
d.emit("}") d.emit("}")
d.overflowCheck() // -> overflowCheckPointLoopExit("l") ? d.overflowCheckLoopExit("l")
// merge-in numeric nread updates from loop
if !d.overflow.checked {
if d.nread != 0 {
d.emit("%v += l * %v", d.var_("nread"), d.nread)
}
d.nread = nreadCur
}
d.emit("}") d.emit("}")
} }
...@@ -871,13 +886,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -871,13 +886,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
d.emit("%v= make(%v, l)", assignto, typeName(typ)) d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("m := %v", assignto) d.emit("m := %v", assignto)
d.emit("for i := 0; uint32(i) < l; i++ {") d.emit("for i := 0; uint32(i) < l; i++ {")
d.overflowCheckLoopEntry()
d.overflowCheck() // -> overflowCheckPointLoopEntry ?
var nreadCur int
if !d.overflow.checked { // TODO merge-in into overflow checker
nreadCur = d.nread
d.nread = 0
}
codegenType("key:", typ.Key(), obj, d) codegenType("key:", typ.Key(), obj, d)
...@@ -894,17 +903,8 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -894,17 +903,8 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
} }
d.resetPos() d.resetPos()
d.emit("}") d.emit("}")
d.overflowCheck() // -> overflowCheckPointLoopExit("l") ? d.overflowCheckLoopExit("l")
// merge-in numeric nread updates from loop
if !d.overflow.checked {
if d.nread != 0 {
d.emit("%v += l * %v", d.var_("nread"), d.nread)
}
d.nread = nreadCur
}
d.emit("}") d.emit("}")
} }
...@@ -912,7 +912,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -912,7 +912,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
// top-level driver for emitting size/encode/decode code for a type // top-level driver for emitting size/encode/decode code for a type
// //
// obj is object that uses this type in source program (so in case of an error // obj is object that uses this type in source program (so in case of an error
// we can point to source location for where it happenned) // we can point to source location for where it happened)
func codegenType(path string, typ types.Type, obj types.Object, codegen CodeGenerator) { func codegenType(path string, typ types.Type, obj types.Object, codegen CodeGenerator) {
switch u := typ.Underlying().(type) { switch u := typ.Underlying().(type) {
case *types.Basic: case *types.Basic:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment