Add encodeRuntimeContext

This commit is contained in:
Masaaki Goshima 2020-08-30 17:52:59 +09:00
parent a9e2386e42
commit cb194687a0
4 changed files with 50 additions and 5 deletions

View File

@ -38,6 +38,7 @@ type opcodeMap struct {
type opcodeSet struct { type opcodeSet struct {
codeIndent sync.Pool codeIndent sync.Pool
code sync.Pool code sync.Pool
ctx sync.Pool
} }
func (m *opcodeMap) get(k uintptr) *opcodeSet { func (m *opcodeMap) get(k uintptr) *opcodeSet {
@ -161,9 +162,11 @@ func (e *Encoder) encode(v interface{}) error {
} else { } else {
code = codeSet.code.Get().(*opcode) code = codeSet.code.Get().(*opcode)
} }
ctx := codeSet.ctx.Get().(encodeRuntimeContext)
p := uintptr(header.ptr) p := uintptr(header.ptr)
ctx.init(p)
code.ptr = p code.ptr = p
if err := e.run(code); err != nil { if err := e.run(ctx, code); err != nil {
return err return err
} }
if e.enabledIndent { if e.enabledIndent {
@ -193,6 +196,7 @@ func (e *Encoder) encode(v interface{}) error {
if err != nil { if err != nil {
return err return err
} }
codeLength := code.length()
codeSet := &opcodeSet{ codeSet := &opcodeSet{
codeIndent: sync.Pool{ codeIndent: sync.Pool{
New: func() interface{} { New: func() interface{} {
@ -204,15 +208,22 @@ func (e *Encoder) encode(v interface{}) error {
return copyOpcode(code) return copyOpcode(code)
}, },
}, },
ctx: sync.Pool{
New: func() interface{} {
return make(encodeRuntimeContext, codeLength)
},
},
} }
cachedOpcode.set(typeptr, codeSet) cachedOpcode.set(typeptr, codeSet)
p := uintptr(header.ptr) p := uintptr(header.ptr)
ctx := codeSet.ctx.Get().(encodeRuntimeContext)
ctx.init(p)
if e.enabledIndent { if e.enabledIndent {
codeIndent.ptr = p codeIndent.ptr = p
return e.run(codeIndent) return e.run(ctx, codeIndent)
} }
code.ptr = p code.ptr = p
return e.run(code) return e.run(ctx, code)
} }
func (e *Encoder) encodeInt(v int) { func (e *Encoder) encodeInt(v int) {

View File

@ -1,5 +1,10 @@
package json package json
import (
"reflect"
"unsafe"
)
type encodeCompileContext struct { type encodeCompileContext struct {
typ *rtype typ *rtype
withIndent bool withIndent bool
@ -52,3 +57,14 @@ func (c *encodeCompileContext) decOpcodeIndex() {
c.parent.decOpcodeIndex() c.parent.decOpcodeIndex()
} }
} }
type encodeRuntimeContext []uintptr
func (c *encodeRuntimeContext) init(p uintptr) {
(*c)[0] = p
}
func (c *encodeRuntimeContext) ptr() *uintptr {
header := (*reflect.SliceHeader)(unsafe.Pointer(c))
return (*uintptr)(unsafe.Pointer(&header.Data))
}

View File

@ -78,6 +78,24 @@ func (c *opcode) beforeLastCode() *opcode {
return nil return nil
} }
func (c *opcode) length() int {
var idx int
for code := c; code.op != opEnd; {
idx = code.idx
switch code.op.codeType() {
case codeArrayElem:
code = code.toArrayElemCode().end
case codeSliceElem:
code = code.toSliceElemCode().end
case codeMapKey:
code = code.toMapKeyCode().end
default:
code = code.next
}
}
return idx + 1
}
func (c *opcode) decOpcodeIndex() { func (c *opcode) decOpcodeIndex() {
for code := c; code.op != opEnd; { for code := c; code.op != opEnd; {
code.idx-- code.idx--

View File

@ -11,7 +11,7 @@ import (
"unsafe" "unsafe"
) )
func (e *Encoder) run(code *opcode) error { func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error {
seenPtr := map[uintptr]struct{}{} seenPtr := map[uintptr]struct{}{}
for { for {
switch code.op { switch code.op {
@ -546,7 +546,7 @@ func (e *Encoder) run(code *opcode) error {
} }
} }
recursive.seenPtr = recursive.ptr recursive.seenPtr = recursive.ptr
if err := e.run(newRecursiveCode(recursive)); err != nil { if err := e.run(nil, newRecursiveCode(recursive)); err != nil {
return err return err
} }
code = recursive.next code = recursive.next