forked from mirror/go-json
Add encodeRuntimeContext
This commit is contained in:
parent
a9e2386e42
commit
cb194687a0
17
encode.go
17
encode.go
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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--
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue