go-json/encode_opcode.go

606 lines
13 KiB
Go
Raw Normal View History

2020-04-29 18:31:50 +03:00
package json
import (
"fmt"
"reflect"
"strings"
"unsafe"
)
2020-08-09 11:48:28 +03:00
func copyOpcode(code *opcode) *opcode {
codeMap := map[uintptr]*opcode{}
return code.copy(codeMap)
}
2020-04-29 18:31:50 +03:00
type opcodeHeader struct {
2020-05-02 17:35:41 +03:00
op opType
typ *rtype
2020-08-30 11:32:26 +03:00
idx int
2020-05-02 17:35:41 +03:00
ptr uintptr
indent int
next *opcode
2020-04-29 18:31:50 +03:00
}
2020-08-09 11:48:28 +03:00
func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader {
return &opcodeHeader{
op: h.op,
typ: h.typ,
2020-08-30 11:32:26 +03:00
idx: h.idx,
2020-08-09 11:48:28 +03:00
ptr: h.ptr,
indent: h.indent,
next: h.next.copy(codeMap),
}
}
2020-04-29 18:31:50 +03:00
type opcode struct {
*opcodeHeader
}
2020-08-29 09:35:03 +03:00
func newOpCode(ctx *encodeCompileContext, op opType) *opcode {
2020-08-30 11:32:26 +03:00
return newOpCodeWithNext(ctx, op, newEndOp(ctx))
2020-08-29 09:35:03 +03:00
}
func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode {
return &opcode{
opcodeHeader: &opcodeHeader{
op: op,
typ: ctx.typ,
2020-08-30 11:32:26 +03:00
idx: ctx.opcodeIndex,
2020-08-29 09:35:03 +03:00
indent: ctx.indent,
2020-05-02 17:35:41 +03:00
next: next,
2020-04-29 18:31:50 +03:00
},
}
}
2020-08-29 09:35:03 +03:00
func newEndOp(ctx *encodeCompileContext) *opcode {
return newOpCodeWithNext(ctx, opEnd, nil)
2020-04-29 18:31:50 +03:00
}
func (c *opcode) beforeLastCode() *opcode {
code := c
for {
var nextCode *opcode
2020-08-22 06:58:34 +03:00
switch code.op.codeType() {
case codeArrayElem:
nextCode = code.toArrayElemCode().end
2020-08-22 06:58:34 +03:00
case codeSliceElem:
2020-04-29 18:31:50 +03:00
nextCode = code.toSliceElemCode().end
2020-08-22 06:58:34 +03:00
case codeMapKey:
nextCode = code.toMapKeyCode().end
default:
2020-04-29 18:31:50 +03:00
nextCode = code.next
}
if nextCode.op == opEnd {
return code
}
code = nextCode
}
return nil
}
2020-08-30 11:32:26 +03:00
func (c *opcode) decOpcodeIndex() {
for code := c; code.op != opEnd; {
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
}
}
}
2020-08-09 11:48:28 +03:00
func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
var code *opcode
2020-08-15 11:41:38 +03:00
switch c.op.codeType() {
case codeArrayHead:
2020-08-09 11:48:28 +03:00
code = c.toArrayHeaderCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeArrayElem:
2020-08-09 11:48:28 +03:00
code = c.toArrayElemCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeSliceHead:
2020-08-09 11:48:28 +03:00
code = c.toSliceHeaderCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeSliceElem:
2020-08-09 11:48:28 +03:00
code = c.toSliceElemCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeMapHead:
2020-08-09 11:48:28 +03:00
code = c.toMapHeadCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeMapKey:
2020-08-09 11:48:28 +03:00
code = c.toMapKeyCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeMapValue:
2020-08-09 11:48:28 +03:00
code = c.toMapValueCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeStructFieldRecursive:
2020-08-12 12:42:29 +03:00
code = c.toRecursiveCode().copy(codeMap)
2020-08-15 11:41:38 +03:00
case codeStructField:
2020-08-09 11:48:28 +03:00
code = c.toStructFieldCode().copy(codeMap)
default:
code = &opcode{}
codeMap[addr] = code
code.opcodeHeader = c.opcodeHeader.copy(codeMap)
}
return code
}
2020-04-29 18:31:50 +03:00
func (c *opcode) dump() string {
codes := []string{}
for code := c; code.op != opEnd; {
2020-05-02 17:35:41 +03:00
indent := strings.Repeat(" ", code.indent)
2020-08-22 06:58:34 +03:00
switch code.op.codeType() {
case codeArrayElem:
2020-08-30 11:32:26 +03:00
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code)))
code = code.toArrayElemCode().end
2020-08-22 06:58:34 +03:00
case codeSliceElem:
2020-08-30 11:32:26 +03:00
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code)))
2020-04-29 18:31:50 +03:00
code = code.toSliceElemCode().end
2020-08-22 06:58:34 +03:00
case codeMapKey:
2020-08-30 11:32:26 +03:00
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code)))
code = code.toMapKeyCode().end
2020-08-22 12:13:44 +03:00
case codeStructField:
sf := code.toStructFieldCode()
key := sf.displayKey
offset := sf.offset
2020-08-30 11:32:26 +03:00
codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.idx, indent, code.op, key, offset, unsafe.Pointer(code)))
2020-08-22 12:13:44 +03:00
code = code.next
default:
2020-08-30 11:32:26 +03:00
codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code)))
2020-04-29 18:31:50 +03:00
code = code.next
}
}
return strings.Join(codes, "\n")
}
2020-04-29 19:44:48 +03:00
func (c *opcode) toSliceHeaderCode() *sliceHeaderCode {
return (*sliceHeaderCode)(unsafe.Pointer(c))
2020-04-29 18:31:50 +03:00
}
2020-04-29 19:44:48 +03:00
func (c *opcode) toSliceElemCode() *sliceElemCode {
return (*sliceElemCode)(unsafe.Pointer(c))
2020-04-29 18:31:50 +03:00
}
func (c *opcode) toArrayHeaderCode() *arrayHeaderCode {
return (*arrayHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toArrayElemCode() *arrayElemCode {
return (*arrayElemCode)(unsafe.Pointer(c))
}
2020-04-29 18:31:50 +03:00
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))
}
2020-08-12 10:54:15 +03:00
func (c *opcode) toInterfaceCode() *interfaceCode {
return (*interfaceCode)(unsafe.Pointer(c))
}
2020-08-12 12:42:29 +03:00
func (c *opcode) toRecursiveCode() *recursiveCode {
return (*recursiveCode)(unsafe.Pointer(c))
}
2020-04-29 19:44:48 +03:00
type sliceHeaderCode struct {
*opcodeHeader
elem *sliceElemCode
end *opcode
}
2020-08-30 11:32:26 +03:00
func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode {
2020-04-29 19:44:48 +03:00
return &sliceHeaderCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opSliceHead,
2020-08-30 11:32:26 +03:00
idx: ctx.opcodeIndex,
indent: ctx.indent,
},
}
}
func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *sliceElemCode {
return &sliceElemCode{
opcodeHeader: &opcodeHeader{
op: opSliceElem,
idx: ctx.opcodeIndex,
indent: ctx.indent,
2020-04-29 19:44:48 +03:00
},
2020-08-30 11:32:26 +03:00
size: size,
2020-04-29 19:44:48 +03:00
}
}
2020-08-09 11:48:28 +03:00
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
}
2020-04-29 18:31:50 +03:00
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
}
2020-08-09 11:48:28 +03:00
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
}
2020-08-30 11:32:26 +03:00
func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode {
return &arrayHeaderCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opArrayHead,
2020-08-30 11:32:26 +03:00
idx: ctx.opcodeIndex,
indent: ctx.indent,
},
len: uintptr(alen),
}
}
2020-08-30 11:32:26 +03:00
func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *arrayElemCode {
return &arrayElemCode{
opcodeHeader: &opcodeHeader{
op: opArrayElem,
idx: ctx.opcodeIndex,
},
len: uintptr(alen),
size: size,
}
}
2020-08-09 11:48:28 +03:00
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
}
2020-08-09 11:48:28 +03:00
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
}
2020-04-29 18:31:50 +03:00
type structFieldCode struct {
*opcodeHeader
2020-08-15 11:41:38 +03:00
key []byte
2020-08-22 06:58:34 +03:00
displayKey string
2020-08-22 09:40:18 +03:00
isTaggedKey bool
2020-08-15 11:41:38 +03:00
offset uintptr
anonymousKey bool
nextField *opcode
end *opcode
2020-04-29 18:31:50 +03:00
}
2020-08-22 06:58:34 +03:00
func linkPrevToNextField(prev, cur *structFieldCode) {
prev.nextField = cur.nextField
code := prev.toOpcode()
fcode := cur.toOpcode()
for {
var nextCode *opcode
switch code.op.codeType() {
case codeArrayElem:
nextCode = code.toArrayElemCode().end
case codeSliceElem:
nextCode = code.toSliceElemCode().end
case codeMapKey:
nextCode = code.toMapKeyCode().end
default:
nextCode = code.next
}
if nextCode == fcode {
code.next = fcode.next
break
} else if nextCode.op == opEnd {
break
}
code = nextCode
}
}
func (c *structFieldCode) toOpcode() *opcode {
return (*opcode)(unsafe.Pointer(c))
}
2020-08-09 11:48:28 +03:00
func (c *structFieldCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
field := &structFieldCode{
2020-08-15 11:41:38 +03:00
key: c.key,
2020-08-22 09:40:18 +03:00
isTaggedKey: c.isTaggedKey,
2020-08-22 06:58:34 +03:00
displayKey: c.displayKey,
2020-08-15 11:41:38 +03:00
anonymousKey: c.anonymousKey,
offset: c.offset,
2020-08-09 11:48:28 +03:00
}
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 {
*opcodeHeader
key *mapKeyCode
value *mapValueCode
end *opcode
}
2020-08-09 11:48:28 +03:00
func (c *mapHeaderCode) 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 := &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 {
*opcodeHeader
idx int
len int
iter unsafe.Pointer
end *opcode
}
2020-08-09 11:48:28 +03:00
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
}
2020-08-09 11:48:28 +03:00
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
}
2020-08-30 11:32:26 +03:00
func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode {
var op opType
if withLoad {
op = opMapHeadLoad
} else {
op = opMapHead
}
return &mapHeaderCode{
opcodeHeader: &opcodeHeader{
op: op,
2020-08-30 11:32:26 +03:00
typ: ctx.typ,
idx: ctx.opcodeIndex,
indent: ctx.indent,
},
}
}
2020-08-30 11:32:26 +03:00
func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode {
return &mapKeyCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opMapKey,
2020-08-30 11:32:26 +03:00
idx: ctx.opcodeIndex,
indent: ctx.indent,
},
}
}
2020-08-30 11:32:26 +03:00
func newMapValueCode(ctx *encodeCompileContext) *mapValueCode {
return &mapValueCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opMapValue,
2020-08-30 11:32:26 +03:00
idx: ctx.opcodeIndex,
indent: ctx.indent,
},
}
}
2020-08-12 12:42:29 +03:00
type interfaceCode struct {
*opcodeHeader
root bool
}
func (c *interfaceCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
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 {
*opcodeHeader
2020-08-20 19:01:24 +03:00
jmp *compiledCode
seenPtr uintptr
2020-08-12 12:42:29 +03:00
}
func (c *recursiveCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
2020-08-20 19:01:24 +03:00
recur := &recursiveCode{seenPtr: c.seenPtr}
2020-08-12 12:42:29 +03:00
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
}
2020-08-13 09:26:35 +03:00
func newRecursiveCode(recursive *recursiveCode) *opcode {
code := copyOpcode(recursive.jmp.code)
head := (*structFieldCode)(unsafe.Pointer(code))
2020-08-29 09:35:03 +03:00
head.end.next = newEndOp(&encodeCompileContext{})
2020-08-13 09:26:35 +03:00
code.ptr = recursive.ptr
2020-08-15 11:41:38 +03:00
code.op = code.op.ptrHeadToHead()
2020-08-13 09:26:35 +03:00
return code
}