From 66bf979e47bbca486f46f3d7ca63dfb84acd6af8 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sat, 26 Jun 2021 15:49:13 +0900 Subject: [PATCH] Improve encoding performance for empty interface type --- internal/cmd/generator/vm.go.tmpl | 13 +++++++++---- internal/encoder/vm/vm.go | 13 +++++++++---- internal/encoder/vm_color/vm.go | 13 +++++++++---- internal/encoder/vm_color_indent/vm.go | 13 +++++++++---- internal/encoder/vm_indent/vm.go | 13 +++++++++---- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 17374ba..78da5e4 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 17374ba..78da5e4 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 33bea71..0d4c472 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 523cb45..de8b858 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 2d2dcb5..d10ce75 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]