package json import ( "fmt" "reflect" "strings" "unsafe" ) func copyOpcode(code *opcode) *opcode { codeMap := map[uintptr]*opcode{} return code.copy(codeMap) } type opcodeHeader struct { op opType typ *rtype idx int indent int next *opcode } func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader { return &opcodeHeader{ op: h.op, typ: h.typ, idx: h.idx, indent: h.indent, next: h.next.copy(codeMap), } } type opcode struct { *opcodeHeader } func newOpCode(ctx *encodeCompileContext, op opType) *opcode { return newOpCodeWithNext(ctx, op, newEndOp(ctx)) } func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { return &opcode{ opcodeHeader: &opcodeHeader{ op: op, typ: ctx.typ, idx: ctx.opcodeIndex, indent: ctx.indent, next: next, }, } } func newEndOp(ctx *encodeCompileContext) *opcode { return newOpCodeWithNext(ctx, opEnd, nil) } func (c *opcode) beforeLastCode() *opcode { code := c 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.op == opEnd { return code } code = nextCode } return nil } func (c *opcode) length() int { var idx int for code := c; code.op != opEnd; { idx = code.idx switch code.op.codeType() { case codeArrayElem: code = code.toArrayElemCode().end case codeSliceElem: code = code.toSliceElemCode().end case codeMapKey: code = code.toMapKeyCode().end default: code = code.next } } return idx + 1 } func (c *opcode) decOpcodeIndex() { for code := c; code.op != opEnd; { code.idx-- 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 } } } 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 switch c.op.codeType() { 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) } return code } func (c *opcode) dump() string { codes := []string{} for code := c; code.op != opEnd; { indent := strings.Repeat(" ", code.indent) switch code.op.codeType() { case codeArrayElem: codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) code = code.toArrayElemCode().end case codeSliceElem: codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) code = code.toSliceElemCode().end case codeMapKey: codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) code = code.toMapKeyCode().end case codeStructField: sf := code.toStructFieldCode() key := sf.displayKey offset := sf.offset codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.idx, indent, code.op, key, offset, unsafe.Pointer(code))) code = code.next default: codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) code = code.next } } return strings.Join(codes, "\n") } func (c *opcode) toSliceHeaderCode() *sliceHeaderCode { 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, 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, }, 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, idx: ctx.opcodeIndex, indent: ctx.indent, }, len: uintptr(alen), } } func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *arrayElemCode { return &arrayElemCode{ opcodeHeader: &opcodeHeader{ op: opArrayElem, idx: ctx.opcodeIndex, }, 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 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)) } 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{ 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 { *opcodeHeader key *mapKeyCode value *mapValueCode end *opcode } 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 } 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 if withLoad { op = opMapHeadLoad } else { op = opMapHead } return &mapHeaderCode{ opcodeHeader: &opcodeHeader{ op: op, typ: ctx.typ, idx: ctx.opcodeIndex, indent: ctx.indent, }, } } func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { return &mapKeyCode{ opcodeHeader: &opcodeHeader{ op: opMapKey, idx: ctx.opcodeIndex, indent: ctx.indent, }, } } func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { return &mapValueCode{ opcodeHeader: &opcodeHeader{ op: opMapValue, idx: ctx.opcodeIndex, indent: ctx.indent, }, } } 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 seenPtr uintptr } 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{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 }