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

View File

@ -1,5 +1,10 @@
package json
import (
"reflect"
"unsafe"
)
type encodeCompileContext struct {
typ *rtype
withIndent bool
@ -52,3 +57,14 @@ func (c *encodeCompileContext) 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
}
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() {
for code := c; code.op != opEnd; {
code.idx--

View File

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