forked from mirror/go-json
Replace vm and escaped vm codes with internal package
This commit is contained in:
parent
10c4118a45
commit
cccf9f9f33
|
@ -7,7 +7,7 @@ services:
|
|||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2048M
|
||||
memory: 1200M
|
||||
working_dir: /go/src/go-json
|
||||
command: |
|
||||
sh -c "go test -c . && ls go-json.test"
|
||||
|
|
75
encode.go
75
encode.go
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
"github.com/goccy/go-json/internal/encoder"
|
||||
"github.com/goccy/go-json/internal/encoder/vm"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_escaped"
|
||||
)
|
||||
|
||||
// An Encoder writes JSON values to an output stream.
|
||||
|
@ -48,6 +49,15 @@ var (
|
|||
}
|
||||
},
|
||||
}
|
||||
encRuntimeContextPool2 = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &encoder.RuntimeContext{
|
||||
Buf: make([]byte, 0, bufSize),
|
||||
Ptrs: make([]uintptr, 128),
|
||||
KeepRefs: make([]unsafe.Pointer, 0, 8),
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func takeEncodeRuntimeContext() *encodeRuntimeContext {
|
||||
|
@ -58,6 +68,14 @@ func releaseEncodeRuntimeContext(ctx *encodeRuntimeContext) {
|
|||
encRuntimeContextPool.Put(ctx)
|
||||
}
|
||||
|
||||
func takeEncodeRuntimeContext2() *encoder.RuntimeContext {
|
||||
return encRuntimeContextPool2.Get().(*encoder.RuntimeContext)
|
||||
}
|
||||
|
||||
func releaseEncodeRuntimeContext2(ctx *encoder.RuntimeContext) {
|
||||
encRuntimeContextPool2.Put(ctx)
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w, enabledHTMLEscape: true}
|
||||
|
@ -95,7 +113,9 @@ func (e *Encoder) encodeWithOption(ctx *encodeRuntimeContext, v interface{}, opt
|
|||
if e.enabledIndent {
|
||||
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr, opt)
|
||||
} else {
|
||||
ctx := takeEncodeRuntimeContext2()
|
||||
buf, err = encode(ctx, v, opt)
|
||||
releaseEncodeRuntimeContext2(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -133,11 +153,11 @@ func (e *Encoder) SetIndent(prefix, indent string) {
|
|||
}
|
||||
|
||||
func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
ctx := takeEncodeRuntimeContext()
|
||||
ctx := takeEncodeRuntimeContext2()
|
||||
|
||||
buf, err := encode(ctx, v, opt|EncodeOptionHTMLEscape)
|
||||
if err != nil {
|
||||
releaseEncodeRuntimeContext(ctx)
|
||||
releaseEncodeRuntimeContext2(ctx)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -149,16 +169,16 @@ func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
|||
copied := make([]byte, len(buf))
|
||||
copy(copied, buf)
|
||||
|
||||
releaseEncodeRuntimeContext(ctx)
|
||||
releaseEncodeRuntimeContext2(ctx)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
ctx := takeEncodeRuntimeContext()
|
||||
ctx := takeEncodeRuntimeContext2()
|
||||
|
||||
buf, err := encodeNoEscape(ctx, v, opt|EncodeOptionHTMLEscape)
|
||||
if err != nil {
|
||||
releaseEncodeRuntimeContext(ctx)
|
||||
releaseEncodeRuntimeContext2(ctx)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -170,7 +190,7 @@ func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
|||
copied := make([]byte, len(buf))
|
||||
copy(copied, buf)
|
||||
|
||||
releaseEncodeRuntimeContext(ctx)
|
||||
releaseEncodeRuntimeContext2(ctx)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
|
@ -191,8 +211,8 @@ func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]by
|
|||
return copied, nil
|
||||
}
|
||||
|
||||
func encode(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
b := ctx.buf[:0]
|
||||
func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
b := ctx.Buf[:0]
|
||||
if v == nil {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -202,40 +222,25 @@ func encode(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption) ([]byte,
|
|||
typ := header.typ
|
||||
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
codeSet, err := encodeCompileToGetCodeSet(typeptr)
|
||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := uintptr(header.ptr)
|
||||
ctx.init(p, codeSet.codeLength)
|
||||
ctx.keepRefs = append(ctx.keepRefs, header.ptr)
|
||||
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.buf = buf
|
||||
return buf, nil
|
||||
} else {
|
||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx := &encoder.RuntimeContext{}
|
||||
ctx.Init(p, codeSet.CodeLength)
|
||||
buf, err := vm.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
||||
|
||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.Buf = buf
|
||||
return buf, nil
|
||||
}
|
||||
}
|
||||
|
||||
func encodeNoEscape(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
b := ctx.buf[:0]
|
||||
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
b := ctx.Buf[:0]
|
||||
if v == nil {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -245,19 +250,19 @@ func encodeNoEscape(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption)
|
|||
typ := header.typ
|
||||
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
codeSet, err := encodeCompileToGetCodeSet(typeptr)
|
||||
codeSet, err := encoder.CompileToGetCodeSet(typeptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := uintptr(header.ptr)
|
||||
ctx.init(p, codeSet.codeLength)
|
||||
ctx.Init(p, codeSet.CodeLength)
|
||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.buf = buf
|
||||
ctx.Buf = buf
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
|
@ -291,11 +296,11 @@ func encodeIndent(ctx *encodeRuntimeContext, v interface{}, prefix, indent strin
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
func encodeRunCode(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt EncodeOption) ([]byte, error) {
|
||||
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
return encodeRunEscaped(ctx, b, codeSet, opt)
|
||||
return vm_escaped.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
return encodeRun(ctx, b, codeSet, opt)
|
||||
return vm.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
|
||||
func encodeRunIndentCode(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
||||
|
|
4050
encode_vm.go
4050
encode_vm.go
File diff suppressed because it is too large
Load Diff
4091
encode_vm_escaped.go
4091
encode_vm_escaped.go
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
var setsMu sync.RWMutex
|
||||
|
||||
func CompileToGetCodeSet(typeptr uintptr) (*opcodeSet, error) {
|
||||
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
||||
if typeptr > typeAddr.MaxTypeAddr {
|
||||
return compileToGetCodeSetSlowPath(typeptr)
|
||||
}
|
||||
|
|
|
@ -476,3 +476,14 @@ func AppendComma(b []byte) []byte {
|
|||
func AppendStructEnd(b []byte) []byte {
|
||||
return append(b, '}', ',')
|
||||
}
|
||||
|
||||
func IsNilForMarshaler(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
switch rv.Kind() {
|
||||
case reflect.Interface, reflect.Map, reflect.Ptr:
|
||||
return rv.IsNil()
|
||||
case reflect.Slice:
|
||||
return rv.IsNil() || rv.Len() == 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -269,14 +269,14 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
|||
b = bb
|
||||
code = code.Next
|
||||
case encoder.OpMarshalJSONPtr:
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
p := load(ctxptr, code.Idx)
|
||||
if p == 0 {
|
||||
b = appendNull(b)
|
||||
b = appendComma(b)
|
||||
code = code.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
store(ctxptr, code.Idx, ptrToPtr(p))
|
||||
fallthrough
|
||||
case encoder.OpMarshalJSON:
|
||||
p := load(ctxptr, code.Idx)
|
||||
|
@ -293,14 +293,14 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
|||
b = appendComma(bb)
|
||||
code = code.Next
|
||||
case encoder.OpMarshalTextPtr:
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
p := load(ctxptr, code.Idx)
|
||||
if p == 0 {
|
||||
b = appendNull(b)
|
||||
b = appendComma(b)
|
||||
code = code.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
store(ctxptr, code.Idx, ptrToPtr(p))
|
||||
fallthrough
|
||||
case encoder.OpMarshalText:
|
||||
p := load(ctxptr, code.Idx)
|
||||
|
@ -337,6 +337,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
|||
}
|
||||
store(ctxptr, code.ElemIdx, 0)
|
||||
store(ctxptr, code.Length, uintptr(slice.Len))
|
||||
store(ctxptr, code.Idx, uintptr(slice.Data))
|
||||
if slice.Len > 0 {
|
||||
b = append(b, '[')
|
||||
code = code.Next
|
||||
|
@ -2815,11 +2816,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
|||
p = ptrToPtr(p + code.Offset)
|
||||
}
|
||||
}
|
||||
if p == 0 && code.Nilcheck {
|
||||
iface := ptrToInterface(code, p)
|
||||
if code.Nilcheck && encoder.IsNilForMarshaler(iface) {
|
||||
code = code.NextField
|
||||
} else {
|
||||
b = append(b, code.Key...)
|
||||
bb, err := appendMarshalJSON(code, b, ptrToInterface(code, p), false)
|
||||
bb, err := appendMarshalJSON(code, b, iface, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue