go-json/encode_opcode.go

512 lines
10 KiB
Go
Raw Permalink 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
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,
ptr: h.ptr,
indent: h.indent,
next: h.next.copy(codeMap),
}
}
2020-04-29 18:31:50 +03:00
type opcode struct {
*opcodeHeader
}
2020-05-02 17:35:41 +03:00
func newOpCode(op opType, typ *rtype, indent int, next *opcode) *opcode {
2020-04-29 18:31:50 +03:00
return &opcode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: op,
typ: typ,
indent: indent,
next: next,
2020-04-29 18:31:50 +03:00
},
}
}
2020-05-02 17:35:41 +03:00
func newEndOp(indent int) *opcode {
return newOpCode(opEnd, nil, indent, nil)
2020-04-29 18:31:50 +03:00
}
func (c *opcode) beforeLastCode() *opcode {
code := c
for {
var nextCode *opcode
switch code.op {
2020-05-02 17:35:41 +03:00
case opArrayElem, opArrayElemIndent:
nextCode = code.toArrayElemCode().end
2020-08-12 10:54:15 +03:00
case opSliceElem, opSliceElemIndent, opRootSliceElemIndent:
2020-04-29 18:31:50 +03:00
nextCode = code.toSliceElemCode().end
2020-08-12 10:54:15 +03:00
case opMapKey, opMapKeyIndent, opRootMapKeyIndent:
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-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)
codes = append(codes, fmt.Sprintf("%s%s", indent, code.op))
switch code.op {
2020-05-02 17:35:41 +03:00
case opArrayElem, opArrayElemIndent:
code = code.toArrayElemCode().end
2020-08-12 10:54:15 +03:00
case opSliceElem, opSliceElemIndent, opRootSliceElemIndent:
2020-04-29 18:31:50 +03:00
code = code.toSliceElemCode().end
2020-08-12 10:54:15 +03:00
case opMapKey, opMapKeyIndent, opRootMapKeyIndent:
code = code.toMapKeyCode().end
default:
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-05-02 17:35:41 +03:00
func newSliceHeaderCode(indent int) *sliceHeaderCode {
2020-04-29 19:44:48 +03:00
return &sliceHeaderCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opSliceHead,
indent: indent,
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-05-02 17:35:41 +03:00
func newArrayHeaderCode(indent, alen int) *arrayHeaderCode {
return &arrayHeaderCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opArrayHead,
indent: indent,
},
len: uintptr(alen),
}
}
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
offset uintptr
anonymousKey bool
nextField *opcode
end *opcode
2020-04-29 18:31:50 +03:00
}
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,
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
}
func newMapHeaderCode(typ *rtype, withLoad bool, indent int) *mapHeaderCode {
var op opType
if withLoad {
op = opMapHeadLoad
} else {
op = opMapHead
}
return &mapHeaderCode{
opcodeHeader: &opcodeHeader{
op: op,
2020-05-02 17:35:41 +03:00
typ: typ,
indent: indent,
},
}
}
2020-05-02 17:35:41 +03:00
func newMapKeyCode(indent int) *mapKeyCode {
return &mapKeyCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opMapKey,
indent: indent,
},
}
}
2020-05-02 17:35:41 +03:00
func newMapValueCode(indent int) *mapValueCode {
return &mapValueCode{
opcodeHeader: &opcodeHeader{
2020-05-02 17:35:41 +03:00
op: opMapValue,
indent: 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
jmp *compiledCode
}
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
}
recur := &recursiveCode{}
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))
head.end.next = newEndOp(0)
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
}