mirror of https://github.com/goccy/go-json.git
Remove state variables from opcode
This commit is contained in:
parent
a6276c4d8e
commit
72bc598dd4
|
@ -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{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
671
encode_opcode.go
671
encode_opcode.go
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
3132
encode_vm.go
3132
encode_vm.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue