binary: reduces allocation during code section decoding (#1352)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
Takeshi Yoneda
2023-04-10 05:48:09 -07:00
committed by GitHub
parent 3cbd881201
commit 84ea9efc14

View File

@@ -17,7 +17,7 @@ func decodeCode(r *bytes.Reader, codeSectionStart uint64, ret *wasm.Code) (err e
}
remaining := int64(ss)
// parse locals
// Parse #locals.
ls, bytesRead, err := leb128.DecodeUint32(r)
remaining -= int64(bytesRead)
if err != nil {
@@ -26,30 +26,28 @@ func decodeCode(r *bytes.Reader, codeSectionStart uint64, ret *wasm.Code) (err e
return io.EOF
}
var nums []uint64
var types []wasm.ValueType
// Validate the locals.
bytesRead = 0
var sum uint64
var n uint32
for i := uint32(0); i < ls; i++ {
n, bytesRead, err = leb128.DecodeUint32(r)
remaining -= int64(bytesRead) + 1 // +1 for the subsequent ReadByte
num, n, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("read n of locals: %v", err)
} else if remaining < 0 {
return io.EOF
}
sum += uint64(n)
nums = append(nums, uint64(n))
sum += uint64(num)
b, err := r.ReadByte()
if err != nil {
return fmt.Errorf("read type of local: %v", err)
}
bytesRead += n + 1
switch vt := b; vt {
case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64,
wasm.ValueTypeFuncref, wasm.ValueTypeExternref, wasm.ValueTypeV128:
types = append(types, vt)
default:
return fmt.Errorf("invalid local type: 0x%x", vt)
}
@@ -59,11 +57,29 @@ func decodeCode(r *bytes.Reader, codeSectionStart uint64, ret *wasm.Code) (err e
return fmt.Errorf("too many locals: %d", sum)
}
var localTypes []wasm.ValueType
for i, num := range nums {
t := types[i]
for j := uint64(0); j < num; j++ {
localTypes = append(localTypes, t)
// Rewind the buffer.
_, err = r.Seek(-int64(bytesRead), io.SeekCurrent)
if err != nil {
return err
}
localTypes := make([]wasm.ValueType, 0, sum)
for i := uint32(0); i < ls; i++ {
num, bytesRead, err := leb128.DecodeUint32(r)
remaining -= int64(bytesRead) + 1 // +1 for the subsequent ReadByte
if err != nil {
return fmt.Errorf("read n of locals: %v", err)
} else if remaining < 0 {
return io.EOF
}
b, err := r.ReadByte()
if err != nil {
return fmt.Errorf("read type of local: %v", err)
}
for j := uint32(0); j < num; j++ {
localTypes = append(localTypes, b)
}
}