diff --git a/dev/decoder/compile_struct.go b/dev/decoder/compile_struct.go index a9befd9b5..3bd20d4db 100644 --- a/dev/decoder/compile_struct.go +++ b/dev/decoder/compile_struct.go @@ -9,6 +9,10 @@ import ( "github.com/bytedance/sonic/dev/internal/caching" ) +const ( + _MAX_FIELDS = 50 // cutoff at 50 fields struct +) + func (c *compiler) compileIntStringOption(vt reflect.Type) decFunc { switch vt.Size() { case 4: @@ -80,9 +84,20 @@ func (c *compiler) compileFieldStringOption(vt reflect.Type) decFunc { } } + func (c *compiler) compileStruct(vt reflect.Type) decFunc { c.enter(vt) defer c.exit(vt) + if c.depth >= c.opts.MaxInlineDepth || (c.counts > 0 && vt.NumField() >= _MAX_FIELDS) { + return &recuriveDecoder{ + typ: rt.UnpackType(vt), + } + } else { + return c.compileStructBody(vt) + } +} + +func (c *compiler) compileStructBody(vt reflect.Type) decFunc { fv := resolver.ResolveStruct(vt) fm := caching.CreateFieldMap(len(fv)) diff --git a/dev/decoder/compiler.go b/dev/decoder/compiler.go index 2a42ed5e0..b8c0ea417 100644 --- a/dev/decoder/compiler.go +++ b/dev/decoder/compiler.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" + "github.com/bytedance/sonic/option" "github.com/bytedance/sonic/dev/internal/rt" "github.com/bytedance/sonic/dev/internal/caching" ) @@ -30,15 +31,22 @@ func findOrCompile(vt *rt.GoType) (decFunc, error) { type compiler struct { visited map[reflect.Type]bool depth int + counts int + opts option.CompileOptions } func newCompiler() *compiler { return &compiler{ visited: make(map[reflect.Type]bool), - depth: 0, + opts: option.DefaultCompileOptions(), } } +func (self *compiler) apply(opts option.CompileOptions) *compiler { + self.opts = opts + return self +} + const _CompileMaxDepth = 4096 func (c *compiler) enter(vt reflect.Type) { @@ -113,6 +121,9 @@ func (c *compiler) compile(vt reflect.Type) decFunc { } func (c *compiler) compileBasic(vt reflect.Type) decFunc { + defer func() { + c.counts += 1 + }() switch vt.Kind() { case reflect.Bool: return &boolDecoder{} @@ -279,6 +290,8 @@ func (c *compiler) compileSliceBytes(vt reflect.Type) decFunc { } func (c *compiler) compileInterface(vt reflect.Type) decFunc { + c.enter(vt) + defer c.exit(vt) if vt.NumMethod() == 0 { return &efaceDecoder{} } diff --git a/dev/internal/link/libsonic_rs_x86_64-unknown-linux-gnu.so b/dev/internal/link/libsonic_rs_x86_64-unknown-linux-gnu.so index 47bea8bad..35874c179 100755 Binary files a/dev/internal/link/libsonic_rs_x86_64-unknown-linux-gnu.so and b/dev/internal/link/libsonic_rs_x86_64-unknown-linux-gnu.so differ