Remove state variables from opcode

This commit is contained in:
Masaaki Goshima 2020-08-31 21:59:22 +09:00
parent a6276c4d8e
commit 72bc598dd4
5 changed files with 1511 additions and 2418 deletions

View File

@ -195,16 +195,16 @@ func (e *Encoder) encode(v interface{}) error {
if err != nil { if err != nil {
return err return err
} }
codeLength := code.length() codeLength := code.totalLength()
codeSet := &opcodeSet{ codeSet := &opcodeSet{
codeIndent: sync.Pool{ codeIndent: sync.Pool{
New: func() interface{} { New: func() interface{} {
return copyOpcode(codeIndent) return codeIndent
}, },
}, },
code: sync.Pool{ code: sync.Pool{
New: func() interface{} { New: func() interface{} {
return copyOpcode(code) return code
}, },
}, },
ctx: sync.Pool{ ctx: sync.Pool{

View File

@ -265,17 +265,7 @@ func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) {
} }
func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) {
code := (*opcode)(unsafe.Pointer(&interfaceCode{ code := newInterfaceCode(ctx)
opcodeHeader: &opcodeHeader{
op: opInterface,
typ: ctx.typ,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
indent: ctx.indent,
next: newEndOp(ctx),
},
root: ctx.root,
}))
ctx.incOpcodeIndex() ctx.incOpcodeIndex()
return code, nil return code, nil
} }
@ -406,8 +396,8 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode,
ctx = ctx.decIndent() ctx = ctx.decIndent()
header.key = key header.mapKey = key
header.value = value header.mapValue = value
end := newOpCode(ctx, opMapEnd) end := newOpCode(ctx, opMapEnd)
ctx.incOpcodeIndex() ctx.incOpcodeIndex()
@ -586,20 +576,10 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool
return fieldType return fieldType
} }
func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { func (e *Encoder) recursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode {
c := (*opcode)(unsafe.Pointer(&recursiveCode{ code := newRecursiveCode(ctx, jmp)
opcodeHeader: &opcodeHeader{
op: opStructFieldRecursive,
typ: ctx.typ,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
indent: ctx.indent,
next: newEndOp(ctx),
},
jmp: code,
}))
ctx.incOpcodeIndex() ctx.incOpcodeIndex()
return c return code
} }
func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
@ -617,7 +597,7 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
return nil return nil
} }
func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *structFieldCode, valueCode *opcode, tag *structTag) *opcode { func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode {
fieldCode.indent-- fieldCode.indent--
op := e.optimizeStructHeader(valueCode.op, tag, ctx.withIndent) op := e.optimizeStructHeader(valueCode.op, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
@ -654,7 +634,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *structField
return (*opcode)(unsafe.Pointer(fieldCode)) return (*opcode)(unsafe.Pointer(fieldCode))
} }
func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *structFieldCode, valueCode *opcode, tag *structTag) *opcode { func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode {
code := (*opcode)(unsafe.Pointer(fieldCode)) code := (*opcode)(unsafe.Pointer(fieldCode))
op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent) op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
@ -691,7 +671,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *structFieldC
return code return code
} }
func (e *Encoder) isNotExistsField(head *structFieldCode) bool { func (e *Encoder) isNotExistsField(head *opcode) bool {
if head == nil { if head == nil {
return false return false
} }
@ -713,12 +693,12 @@ func (e *Encoder) isNotExistsField(head *structFieldCode) bool {
if head.next.op.codeType() != codeStructField { if head.next.op.codeType() != codeStructField {
return false return false
} }
return e.isNotExistsField(head.next.toStructFieldCode()) return e.isNotExistsField(head.next)
} }
func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { func (e *Encoder) optimizeAnonymousFields(head *opcode) {
code := head code := head
var prev *structFieldCode var prev *opcode
for { for {
if code.op == opStructEnd || code.op == opStructEndIndent { if code.op == opStructEnd || code.op == opStructEndIndent {
break break
@ -726,7 +706,7 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) {
if code.op == opStructField || code.op == opStructFieldIndent { if code.op == opStructField || code.op == opStructFieldIndent {
codeType := code.next.op.codeType() codeType := code.next.op.codeType()
if codeType == codeStructField { if codeType == codeStructField {
if e.isNotExistsField(code.next.toStructFieldCode()) { if e.isNotExistsField(code.next) {
code.next = code.nextField code.next = code.nextField
diff := code.next.displayIdx - code.displayIdx diff := code.next.displayIdx - code.displayIdx
for i := 0; i < diff; i++ { for i := 0; i < diff; i++ {
@ -738,21 +718,21 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) {
} }
} }
prev = code prev = code
code = code.nextField.toStructFieldCode() code = code.nextField
} }
} }
type structFieldPair struct { type structFieldPair struct {
prevField *structFieldCode prevField *opcode
curField *structFieldCode curField *opcode
isTaggedKey bool isTaggedKey bool
linked bool linked bool
} }
func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *structFieldCode) map[string][]structFieldPair { func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *opcode) map[string][]structFieldPair {
anonymousFields := map[string][]structFieldPair{} anonymousFields := map[string][]structFieldPair{}
f := valueCode f := valueCode
var prevAnonymousField *structFieldCode var prevAnonymousField *opcode
for { for {
existsKey := tags.existsKey(f.displayKey) existsKey := tags.existsKey(f.displayKey)
op := f.op.headToAnonymousHead() op := f.op.headToAnonymousHead()
@ -777,7 +757,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
break break
} }
prevAnonymousField = f prevAnonymousField = f
f = f.nextField.toStructFieldCode() f = f.nextField
continue continue
} }
@ -787,7 +767,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
isTaggedKey: f.isTaggedKey, isTaggedKey: f.isTaggedKey,
}) })
if f.next != nil && f.nextField != f.next && f.next.op.codeType() == codeStructField { if f.next != nil && f.nextField != f.next && f.next.op.codeType() == codeStructField {
for k, v := range e.anonymousStructFieldPairMap(typ, tags, f.next.toStructFieldCode()) { for k, v := range e.anonymousStructFieldPairMap(typ, tags, f.next) {
anonymousFields[k] = append(anonymousFields[k], v...) anonymousFields[k] = append(anonymousFields[k], v...)
} }
} }
@ -795,7 +775,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
break break
} }
prevAnonymousField = f prevAnonymousField = f
f = f.nextField.toStructFieldCode() f = f.nextField
} }
return anonymousFields return anonymousFields
} }
@ -869,9 +849,9 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
fieldNum := typ.NumField() fieldNum := typ.NumField()
fieldIdx := 0 fieldIdx := 0
var ( var (
head *structFieldCode head *opcode
code *opcode code *opcode
prevField *structFieldCode prevField *opcode
) )
ctx = ctx.incIndent() ctx = ctx.incIndent()
tags := structTags{} tags := structTags{}
@ -903,7 +883,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
} }
if field.Anonymous { if field.Anonymous {
for k, v := range e.anonymousStructFieldPairMap(typ, tags, valueCode.toStructFieldCode()) { for k, v := range e.anonymousStructFieldPairMap(typ, tags, valueCode) {
anonymousFields[k] = append(anonymousFields[k], v...) anonymousFields[k] = append(anonymousFields[k], v...)
} }
} }
@ -919,14 +899,12 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
} }
} }
key := fmt.Sprintf(`"%s":`, tag.key) key := fmt.Sprintf(`"%s":`, tag.key)
fieldCode := &structFieldCode{ fieldCode := &opcode{
opcodeHeader: &opcodeHeader{ typ: valueCode.typ,
typ: valueCode.typ, displayIdx: fieldOpcodeIndex,
displayIdx: fieldOpcodeIndex, idx: opcodeOffset(fieldOpcodeIndex),
idx: uintptr(fieldOpcodeIndex) * 8, next: valueCode,
next: valueCode, indent: ctx.indent,
indent: ctx.indent,
},
anonymousKey: field.Anonymous, anonymousKey: field.Anonymous,
key: []byte(key), key: []byte(key),
isTaggedKey: tag.isTaggedKey, isTaggedKey: tag.isTaggedKey,
@ -948,36 +926,32 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
} }
ctx = ctx.decIndent() ctx = ctx.decIndent()
structEndCode := (*opcode)(unsafe.Pointer(&structFieldCode{ structEndCode := &opcode{
opcodeHeader: &opcodeHeader{ op: opStructEnd,
op: opStructEnd, typ: nil,
typ: nil, indent: ctx.indent,
indent: ctx.indent, next: newEndOp(ctx),
next: newEndOp(ctx), }
},
}))
// no struct field // no struct field
if head == nil { if head == nil {
head = &structFieldCode{ head = &opcode{
opcodeHeader: &opcodeHeader{ op: opStructFieldHead,
op: opStructFieldHead, typ: typ,
typ: typ, displayIdx: ctx.opcodeIndex,
displayIdx: ctx.opcodeIndex, idx: opcodeOffset(ctx.opcodeIndex),
idx: uintptr(ctx.opcodeIndex) * 8, indent: ctx.indent,
indent: ctx.indent, nextField: structEndCode,
},
nextField: structEndCode,
} }
ctx.incOpcodeIndex() ctx.incOpcodeIndex()
if ctx.withIndent { if ctx.withIndent {
head.op = opStructFieldHeadIndent head.op = opStructFieldHeadIndent
} }
code = (*opcode)(unsafe.Pointer(head)) code = head
} }
structEndCode.displayIdx = ctx.opcodeIndex structEndCode.displayIdx = ctx.opcodeIndex
structEndCode.idx = uintptr(ctx.opcodeIndex) * 8 structEndCode.idx = opcodeOffset(ctx.opcodeIndex)
ctx.incOpcodeIndex() ctx.incOpcodeIndex()
if ctx.withIndent { if ctx.withIndent {

View File

@ -10,6 +10,7 @@ type encodeCompileContext struct {
withIndent bool withIndent bool
root bool root bool
opcodeIndex int opcodeIndex int
ptrIndex int
indent int indent int
parent *encodeCompileContext parent *encodeCompileContext
@ -21,6 +22,7 @@ func (c *encodeCompileContext) context() *encodeCompileContext {
withIndent: c.withIndent, withIndent: c.withIndent,
root: c.root, root: c.root,
opcodeIndex: c.opcodeIndex, opcodeIndex: c.opcodeIndex,
ptrIndex: c.ptrIndex,
indent: c.indent, indent: c.indent,
parent: c, parent: c,
} }
@ -46,6 +48,7 @@ func (c *encodeCompileContext) decIndent() *encodeCompileContext {
func (c *encodeCompileContext) incOpcodeIndex() { func (c *encodeCompileContext) incOpcodeIndex() {
c.opcodeIndex++ c.opcodeIndex++
c.ptrIndex++
if c.parent != nil { if c.parent != nil {
c.parent.incOpcodeIndex() c.parent.incOpcodeIndex()
} }
@ -53,6 +56,7 @@ func (c *encodeCompileContext) incOpcodeIndex() {
func (c *encodeCompileContext) decOpcodeIndex() { func (c *encodeCompileContext) decOpcodeIndex() {
c.opcodeIndex-- c.opcodeIndex--
c.ptrIndex--
if c.parent != nil { if c.parent != nil {
c.parent.decOpcodeIndex() c.parent.decOpcodeIndex()
} }

View File

@ -2,54 +2,56 @@ package json
import ( import (
"fmt" "fmt"
"reflect"
"strings" "strings"
"unsafe" "unsafe"
) )
func copyOpcode(code *opcode) *opcode { var uintptrSize = unsafe.Sizeof(uintptr(0))
codeMap := map[uintptr]*opcode{}
return code.copy(codeMap)
}
type opcodeHeader struct {
op opType
typ *rtype
displayIdx int
idx uintptr
indent int
next *opcode
}
func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader {
return &opcodeHeader{
op: h.op,
typ: h.typ,
displayIdx: h.displayIdx,
idx: h.idx,
indent: h.indent,
next: h.next.copy(codeMap),
}
}
type opcode struct { type opcode struct {
*opcodeHeader op opType // operation type
typ *rtype // go type
displayIdx int // opcode index
key []byte // struct field key
displayKey string // key text to display
isTaggedKey bool // whether tagged key
anonymousKey bool // whether anonymous key
root bool // whether root
indent int // indent number
idx uintptr // offset to access ptr
headIdx uintptr // offset to access slice/struct head
elemIdx uintptr // offset to access array/slice/map elem
length uintptr // offset to access slice/map length or array length
mapIter uintptr // offset to access map iterator
offset uintptr // offset size from struct header
size uintptr // array/slice elem size
mapKey *opcode // map key
mapValue *opcode // map value
elem *opcode // array/slice elem
end *opcode // array/slice/struct/map end
nextField *opcode // next struct field
next *opcode // next opcode
jmp *compiledCode // for recursive call
} }
func newOpCode(ctx *encodeCompileContext, op opType) *opcode { func newOpCode(ctx *encodeCompileContext, op opType) *opcode {
return newOpCodeWithNext(ctx, op, newEndOp(ctx)) return newOpCodeWithNext(ctx, op, newEndOp(ctx))
} }
func opcodeOffset(idx int) uintptr {
return uintptr(idx) * uintptrSize
}
func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode {
return &opcode{ return &opcode{
opcodeHeader: &opcodeHeader{ op: op,
op: op, typ: ctx.typ,
typ: ctx.typ, displayIdx: ctx.opcodeIndex,
displayIdx: ctx.opcodeIndex, indent: ctx.indent,
idx: uintptr(ctx.opcodeIndex) * 8, idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent, next: next,
next: next,
},
} }
} }
@ -62,12 +64,8 @@ func (c *opcode) beforeLastCode() *opcode {
for { for {
var nextCode *opcode var nextCode *opcode
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: case codeArrayElem, codeSliceElem, codeMapKey:
nextCode = code.toArrayElemCode().end nextCode = code.end
case codeSliceElem:
nextCode = code.toSliceElemCode().end
case codeMapKey:
nextCode = code.toMapKeyCode().end
default: default:
nextCode = code.next nextCode = code.next
} }
@ -79,17 +77,13 @@ func (c *opcode) beforeLastCode() *opcode {
return nil return nil
} }
func (c *opcode) length() int { func (c *opcode) totalLength() int {
var idx int var idx int
for code := c; code.op != opEnd; { for code := c; code.op != opEnd; {
idx = code.displayIdx idx = code.displayIdx
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: case codeArrayElem, codeSliceElem, codeMapKey:
code = code.toArrayElemCode().end code = code.end
case codeSliceElem:
code = code.toSliceElemCode().end
case codeMapKey:
code = code.toMapKeyCode().end
default: default:
code = code.next code = code.next
} }
@ -102,310 +96,86 @@ func (c *opcode) decOpcodeIndex() {
code.displayIdx-- code.displayIdx--
code.idx -= 8 code.idx -= 8
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: case codeArrayElem, codeSliceElem, codeMapKey:
code = code.toArrayElemCode().end code = code.end
case codeSliceElem:
code = code.toSliceElemCode().end
case codeMapKey:
code = code.toMapKeyCode().end
default: default:
code = code.next code = code.next
} }
} }
} }
func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode { func (c *opcode) dumpElem(code *opcode) string {
if c == nil { return fmt.Sprintf(
return nil `[%d]%s%s ([headIdx:%d][elemIdx:%d][length:%d][size:%d])`,
} code.displayIdx,
addr := uintptr(unsafe.Pointer(c)) strings.Repeat("-", code.indent),
if code, exists := codeMap[addr]; exists { code.op,
return code code.headIdx,
} code.elemIdx,
var code *opcode code.length,
switch c.op.codeType() { code.size,
case codeArrayHead: )
code = c.toArrayHeaderCode().copy(codeMap) }
case codeArrayElem:
code = c.toArrayElemCode().copy(codeMap)
case codeSliceHead:
code = c.toSliceHeaderCode().copy(codeMap)
case codeSliceElem:
code = c.toSliceElemCode().copy(codeMap)
case codeMapHead:
code = c.toMapHeadCode().copy(codeMap)
case codeMapKey:
code = c.toMapKeyCode().copy(codeMap)
case codeMapValue:
code = c.toMapValueCode().copy(codeMap)
case codeStructFieldRecursive:
code = c.toRecursiveCode().copy(codeMap)
case codeStructField:
code = c.toStructFieldCode().copy(codeMap)
default:
code = &opcode{}
codeMap[addr] = code
code.opcodeHeader = c.opcodeHeader.copy(codeMap) func (c *opcode) dumpField(code *opcode) string {
} return fmt.Sprintf(
return code `[%d]%s%s ([key:%s][offset:%d][headIdx:%d])`,
code.displayIdx,
strings.Repeat("-", code.indent),
code.op,
code.displayKey,
code.offset,
code.headIdx,
)
}
func (c *opcode) dumpKey(code *opcode) string {
return fmt.Sprintf(
`[%d]%s%s ([elemIdx:%d][length:%d][mapIter:%d])`,
code.displayIdx,
strings.Repeat("-", code.indent),
code.op,
code.elemIdx,
code.length,
code.mapIter,
)
} }
func (c *opcode) dump() string { func (c *opcode) dump() string {
codes := []string{} codes := []string{}
for code := c; code.op != opEnd; { for code := c; code.op != opEnd; {
indent := strings.Repeat(" ", code.indent)
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: case codeArrayElem, codeSliceElem:
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) codes = append(codes, c.dumpElem(code))
code = code.toArrayElemCode().end code = code.end
case codeSliceElem:
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code)))
code = code.toSliceElemCode().end
case codeMapKey: case codeMapKey:
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) codes = append(codes, c.dumpKey(code))
code = code.toMapKeyCode().end code = code.end
case codeStructField: case codeStructField:
sf := code.toStructFieldCode() codes = append(codes, c.dumpField(code))
key := sf.displayKey
offset := sf.offset
codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.displayIdx, indent, code.op, key, offset, unsafe.Pointer(code)))
code = code.next code = code.next
default: default:
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) codes = append(codes, fmt.Sprintf(
"[%d]%s%s",
code.displayIdx,
strings.Repeat("-", code.indent),
code.op,
))
code = code.next code = code.next
} }
} }
return strings.Join(codes, "\n") return strings.Join(codes, "\n")
} }
func (c *opcode) toSliceHeaderCode() *sliceHeaderCode { func linkPrevToNextField(prev, cur *opcode) {
return (*sliceHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toSliceElemCode() *sliceElemCode {
return (*sliceElemCode)(unsafe.Pointer(c))
}
func (c *opcode) toArrayHeaderCode() *arrayHeaderCode {
return (*arrayHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toArrayElemCode() *arrayElemCode {
return (*arrayElemCode)(unsafe.Pointer(c))
}
func (c *opcode) toStructFieldCode() *structFieldCode {
return (*structFieldCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapHeadCode() *mapHeaderCode {
return (*mapHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapKeyCode() *mapKeyCode {
return (*mapKeyCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapValueCode() *mapValueCode {
return (*mapValueCode)(unsafe.Pointer(c))
}
func (c *opcode) toInterfaceCode() *interfaceCode {
return (*interfaceCode)(unsafe.Pointer(c))
}
func (c *opcode) toRecursiveCode() *recursiveCode {
return (*recursiveCode)(unsafe.Pointer(c))
}
type sliceHeaderCode struct {
*opcodeHeader
elem *sliceElemCode
end *opcode
}
func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode {
return &sliceHeaderCode{
opcodeHeader: &opcodeHeader{
op: opSliceHead,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
indent: ctx.indent,
},
}
}
func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *sliceElemCode {
return &sliceElemCode{
opcodeHeader: &opcodeHeader{
op: opSliceElem,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
indent: ctx.indent,
},
size: size,
}
}
func (c *sliceHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
header := &sliceHeaderCode{}
code := (*opcode)(unsafe.Pointer(header))
codeMap[addr] = code
header.opcodeHeader = c.opcodeHeader.copy(codeMap)
header.elem = (*sliceElemCode)(unsafe.Pointer(c.elem.copy(codeMap)))
header.end = c.end.copy(codeMap)
return code
}
type sliceElemCode struct {
*opcodeHeader
idx uintptr
len uintptr
size uintptr
data uintptr
end *opcode
}
func (c *sliceElemCode) set(header *reflect.SliceHeader) {
c.idx = uintptr(0)
c.len = uintptr(header.Len)
c.data = header.Data
}
func (c *sliceElemCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
elem := &sliceElemCode{
idx: c.idx,
len: c.len,
size: c.size,
data: c.data,
}
code := (*opcode)(unsafe.Pointer(elem))
codeMap[addr] = code
elem.opcodeHeader = c.opcodeHeader.copy(codeMap)
elem.end = c.end.copy(codeMap)
return code
}
type arrayHeaderCode struct {
*opcodeHeader
len uintptr
elem *arrayElemCode
end *opcode
}
func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode {
return &arrayHeaderCode{
opcodeHeader: &opcodeHeader{
op: opArrayHead,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
indent: ctx.indent,
},
len: uintptr(alen),
}
}
func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *arrayElemCode {
return &arrayElemCode{
opcodeHeader: &opcodeHeader{
op: opArrayElem,
displayIdx: ctx.opcodeIndex,
idx: uintptr(ctx.opcodeIndex) * 8,
},
len: uintptr(alen),
size: size,
}
}
func (c *arrayHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
header := &arrayHeaderCode{}
code := (*opcode)(unsafe.Pointer(header))
codeMap[addr] = code
header.opcodeHeader = c.opcodeHeader.copy(codeMap)
header.len = c.len
header.elem = (*arrayElemCode)(unsafe.Pointer(c.elem.copy(codeMap)))
header.end = c.end.copy(codeMap)
return code
}
type arrayElemCode struct {
*opcodeHeader
idx uintptr
len uintptr
size uintptr
end *opcode
}
func (c *arrayElemCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
elem := &arrayElemCode{
idx: c.idx,
len: c.len,
size: c.size,
}
code := (*opcode)(unsafe.Pointer(elem))
codeMap[addr] = code
elem.opcodeHeader = c.opcodeHeader.copy(codeMap)
elem.end = c.end.copy(codeMap)
return code
}
type structFieldCode struct {
*opcodeHeader
key []byte
displayKey string
isTaggedKey bool
offset uintptr
anonymousKey bool
nextField *opcode
end *opcode
}
func linkPrevToNextField(prev, cur *structFieldCode) {
prev.nextField = cur.nextField prev.nextField = cur.nextField
code := prev.toOpcode() code := prev
fcode := cur.toOpcode() fcode := cur
for { for {
var nextCode *opcode var nextCode *opcode
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: case codeArrayElem, codeSliceElem, codeMapKey:
nextCode = code.toArrayElemCode().end nextCode = code.end
case codeSliceElem:
nextCode = code.toSliceElemCode().end
case codeMapKey:
nextCode = code.toMapKeyCode().end
default: default:
nextCode = code.next nextCode = code.next
} }
@ -419,213 +189,108 @@ func linkPrevToNextField(prev, cur *structFieldCode) {
} }
} }
func (c *structFieldCode) toOpcode() *opcode { func newSliceHeaderCode(ctx *encodeCompileContext) *opcode {
return (*opcode)(unsafe.Pointer(c)) return &opcode{
op: opSliceHead,
displayIdx: ctx.opcodeIndex,
idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent,
}
} }
func (c *structFieldCode) copy(codeMap map[uintptr]*opcode) *opcode { func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *opcode {
if c == nil { return &opcode{
return nil op: opSliceElem,
displayIdx: ctx.opcodeIndex,
idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent,
size: size,
} }
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
field := &structFieldCode{
key: c.key,
isTaggedKey: c.isTaggedKey,
displayKey: c.displayKey,
anonymousKey: c.anonymousKey,
offset: c.offset,
}
code := (*opcode)(unsafe.Pointer(field))
codeMap[addr] = code
field.opcodeHeader = c.opcodeHeader.copy(codeMap)
field.nextField = c.nextField.copy(codeMap)
field.end = c.end.copy(codeMap)
return code
} }
type mapHeaderCode struct { func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *opcode {
*opcodeHeader return &opcode{
key *mapKeyCode op: opArrayHead,
value *mapValueCode displayIdx: ctx.opcodeIndex,
end *opcode idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent,
length: uintptr(alen),
}
} }
func (c *mapHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode { func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *opcode {
if c == nil { return &opcode{
return nil op: opArrayElem,
displayIdx: ctx.opcodeIndex,
idx: opcodeOffset(ctx.opcodeIndex),
length: uintptr(alen),
size: size,
} }
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
header := &mapHeaderCode{}
code := (*opcode)(unsafe.Pointer(header))
codeMap[addr] = code
header.opcodeHeader = c.opcodeHeader.copy(codeMap)
header.key = (*mapKeyCode)(unsafe.Pointer(c.key.copy(codeMap)))
header.value = (*mapValueCode)(unsafe.Pointer(c.value.copy(codeMap)))
header.end = c.end.copy(codeMap)
return code
} }
type mapKeyCode struct { func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *opcode {
*opcodeHeader
idx int
len int
iter unsafe.Pointer
end *opcode
}
func (c *mapKeyCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
key := &mapKeyCode{
idx: c.idx,
len: c.len,
iter: c.iter,
}
code := (*opcode)(unsafe.Pointer(key))
codeMap[addr] = code
key.opcodeHeader = c.opcodeHeader.copy(codeMap)
key.end = c.end.copy(codeMap)
return code
}
func (c *mapKeyCode) set(len int, iter unsafe.Pointer) {
c.idx = 0
c.len = len
c.iter = iter
}
type mapValueCode struct {
*opcodeHeader
iter unsafe.Pointer
}
func (c *mapValueCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
value := &mapValueCode{
iter: c.iter,
}
code := (*opcode)(unsafe.Pointer(value))
codeMap[addr] = code
value.opcodeHeader = c.opcodeHeader.copy(codeMap)
return code
}
func (c *mapValueCode) set(iter unsafe.Pointer) {
c.iter = iter
}
func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode {
var op opType var op opType
if withLoad { if withLoad {
op = opMapHeadLoad op = opMapHeadLoad
} else { } else {
op = opMapHead op = opMapHead
} }
return &mapHeaderCode{ return &opcode{
opcodeHeader: &opcodeHeader{ op: op,
op: op, typ: ctx.typ,
typ: ctx.typ, displayIdx: ctx.opcodeIndex,
displayIdx: ctx.opcodeIndex, idx: opcodeOffset(ctx.opcodeIndex),
idx: uintptr(ctx.opcodeIndex) * 8, indent: ctx.indent,
indent: ctx.indent,
},
} }
} }
func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { func newMapKeyCode(ctx *encodeCompileContext) *opcode {
return &mapKeyCode{ return &opcode{
opcodeHeader: &opcodeHeader{ op: opMapKey,
op: opMapKey, displayIdx: ctx.opcodeIndex,
displayIdx: ctx.opcodeIndex, idx: opcodeOffset(ctx.opcodeIndex),
idx: uintptr(ctx.opcodeIndex) * 8, indent: ctx.indent,
indent: ctx.indent,
},
} }
} }
func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { func newMapValueCode(ctx *encodeCompileContext) *opcode {
return &mapValueCode{ return &opcode{
opcodeHeader: &opcodeHeader{ op: opMapValue,
op: opMapValue, displayIdx: ctx.opcodeIndex,
displayIdx: ctx.opcodeIndex, idx: opcodeOffset(ctx.opcodeIndex),
idx: uintptr(ctx.opcodeIndex) * 8, indent: ctx.indent,
indent: ctx.indent,
},
} }
} }
type interfaceCode struct { func newInterfaceCode(ctx *encodeCompileContext) *opcode {
*opcodeHeader return &opcode{
root bool op: opInterface,
typ: ctx.typ,
displayIdx: ctx.opcodeIndex,
idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent,
next: newEndOp(ctx),
root: ctx.root,
}
} }
func (c *interfaceCode) copy(codeMap map[uintptr]*opcode) *opcode { func newRecursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode {
if c == nil { return &opcode{
return nil op: opStructFieldRecursive,
typ: ctx.typ,
displayIdx: ctx.opcodeIndex,
idx: opcodeOffset(ctx.opcodeIndex),
indent: ctx.indent,
next: newEndOp(ctx),
jmp: jmp,
} }
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
iface := &interfaceCode{}
code := (*opcode)(unsafe.Pointer(iface))
codeMap[addr] = code
iface.opcodeHeader = c.opcodeHeader.copy(codeMap)
return code
} }
type recursiveCode struct { //func newRecursiveCode(recursive *recursiveCode) *opcode {
*opcodeHeader //code := copyOpcode(recursive.jmp.code)
jmp *compiledCode //head := (*structFieldCode)(unsafe.Pointer(code))
seenPtr uintptr //head.end.next = newEndOp(&encodeCompileContext{})
}
func (c *recursiveCode) copy(codeMap map[uintptr]*opcode) *opcode { //code.op = code.op.ptrHeadToHead()
if c == nil { // return code
return nil //}
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
recur := &recursiveCode{seenPtr: c.seenPtr}
code := (*opcode)(unsafe.Pointer(recur))
codeMap[addr] = code
recur.opcodeHeader = c.opcodeHeader.copy(codeMap)
recur.jmp = &compiledCode{
code: c.jmp.code.copy(codeMap),
}
return code
}
func newRecursiveCode(recursive *recursiveCode) *opcode {
code := copyOpcode(recursive.jmp.code)
head := (*structFieldCode)(unsafe.Pointer(code))
head.end.next = newEndOp(&encodeCompileContext{})
code.op = code.op.ptrHeadToHead()
return code
}

File diff suppressed because it is too large Load Diff