From 7dcadbd6ce696fe3101e7f77ffa759aaa3e3b7f9 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sat, 29 Aug 2020 15:11:31 +0900 Subject: [PATCH 01/18] Refactor with encodeCompileContext --- encode.go | 12 ++- encode_compile.go | 236 +++++++++++++++++++++------------------------- encode_vm.go | 12 ++- 3 files changed, 129 insertions(+), 131 deletions(-) diff --git a/encode.go b/encode.go index 58f019a..2247322 100644 --- a/encode.go +++ b/encode.go @@ -179,11 +179,19 @@ func (e *Encoder) encode(v interface{}) error { // noescape trick for header.typ ( reflect.*rtype ) copiedType := (*rtype)(unsafe.Pointer(typeptr)) - codeIndent, err := e.compileHead(copiedType, true) + codeIndent, err := e.compileHead(&encodeCompileContext{ + typ: copiedType, + root: true, + withIndent: true, + }) if err != nil { return err } - code, err := e.compileHead(copiedType, false) + code, err := e.compileHead(&encodeCompileContext{ + typ: copiedType, + root: true, + withIndent: false, + }) if err != nil { return err } diff --git a/encode_compile.go b/encode_compile.go index 9dc7ec2..229c485 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -6,8 +6,8 @@ import ( "unsafe" ) -func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) { - root := true +func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) { + typ := ctx.typ switch { case typ.Implements(marshalJSONType): return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil @@ -24,11 +24,11 @@ func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) { isPtr = true } if typ.Kind() == reflect.Map { - return e.compileMap(typ, isPtr, root, withIndent) + return e.compileMap(ctx.withType(typ), isPtr) } else if typ.Kind() == reflect.Struct { - return e.compileStruct(typ, isPtr, root, withIndent) + return e.compileStruct(ctx.withType(typ), isPtr) } - return e.compile(typ, root, withIndent) + return e.compile(ctx.withType(typ)) } func (e *Encoder) implementsMarshaler(typ *rtype) bool { @@ -45,7 +45,8 @@ func (e *Encoder) implementsMarshaler(typ *rtype) bool { return false } -func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) { +func (e *Encoder) compile(ctx *encodeCompileContext) (*opcode, error) { + typ := ctx.typ switch { case typ.Implements(marshalJSONType): return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil @@ -58,56 +59,57 @@ func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) { } switch typ.Kind() { case reflect.Ptr: - return e.compilePtr(typ, root, withIndent) + return e.compilePtr(ctx) case reflect.Slice: elem := typ.Elem() if !e.implementsMarshaler(elem) && elem.Kind() == reflect.Uint8 { - return e.compileBytes(typ) + return e.compileBytes(ctx) } - return e.compileSlice(typ, root, withIndent) + return e.compileSlice(ctx) case reflect.Array: - return e.compileArray(typ, root, withIndent) + return e.compileArray(ctx) case reflect.Map: - return e.compileMap(typ, true, root, withIndent) + return e.compileMap(ctx, true) case reflect.Struct: - return e.compileStruct(typ, false, root, withIndent) + return e.compileStruct(ctx, false) case reflect.Interface: - return e.compileInterface(typ, root) + return e.compileInterface(ctx) case reflect.Int: - return e.compileInt(typ) + return e.compileInt(ctx) case reflect.Int8: - return e.compileInt8(typ) + return e.compileInt8(ctx) case reflect.Int16: - return e.compileInt16(typ) + return e.compileInt16(ctx) case reflect.Int32: - return e.compileInt32(typ) + return e.compileInt32(ctx) case reflect.Int64: - return e.compileInt64(typ) + return e.compileInt64(ctx) case reflect.Uint: - return e.compileUint(typ) + return e.compileUint(ctx) case reflect.Uint8: - return e.compileUint8(typ) + return e.compileUint8(ctx) case reflect.Uint16: - return e.compileUint16(typ) + return e.compileUint16(ctx) case reflect.Uint32: - return e.compileUint32(typ) + return e.compileUint32(ctx) case reflect.Uint64: - return e.compileUint64(typ) + return e.compileUint64(ctx) case reflect.Uintptr: - return e.compileUint(typ) + return e.compileUint(ctx) case reflect.Float32: - return e.compileFloat32(typ) + return e.compileFloat32(ctx) case reflect.Float64: - return e.compileFloat64(typ) + return e.compileFloat64(ctx) case reflect.String: - return e.compileString(typ) + return e.compileString(ctx) case reflect.Bool: - return e.compileBool(typ) + return e.compileBool(ctx) } return nil, &UnsupportedTypeError{Type: rtype2type(typ)} } -func (e *Encoder) compileKey(typ *rtype, root, withIndent bool) (*opcode, error) { +func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { + typ := ctx.typ switch { case typ.Implements(marshalJSONType): return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil @@ -120,44 +122,17 @@ func (e *Encoder) compileKey(typ *rtype, root, withIndent bool) (*opcode, error) } switch typ.Kind() { case reflect.Ptr: - return e.compilePtr(typ, root, withIndent) + return e.compilePtr(ctx) case reflect.Interface: - return e.compileInterface(typ, root) - case reflect.Int: - return e.compileInt(typ) - case reflect.Int8: - return e.compileInt8(typ) - case reflect.Int16: - return e.compileInt16(typ) - case reflect.Int32: - return e.compileInt32(typ) - case reflect.Int64: - return e.compileInt64(typ) - case reflect.Uint: - return e.compileUint(typ) - case reflect.Uint8: - return e.compileUint8(typ) - case reflect.Uint16: - return e.compileUint16(typ) - case reflect.Uint32: - return e.compileUint32(typ) - case reflect.Uint64: - return e.compileUint64(typ) - case reflect.Uintptr: - return e.compileUint(typ) - case reflect.Float32: - return e.compileFloat32(typ) - case reflect.Float64: - return e.compileFloat64(typ) + return e.compileInterface(ctx) case reflect.String: - return e.compileString(typ) - case reflect.Bool: - return e.compileBool(typ) + return e.compileString(ctx) } return nil, &UnsupportedTypeError{Type: rtype2type(typ)} } -func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode { +func (e *Encoder) optimizeStructFieldPtrHead(ctx *encodeCompileContext, code *opcode) *opcode { + typ := ctx.typ ptrHeadOp := code.op.headToPtrHead() if code.op != ptrHeadOp { code.op = ptrHeadOp @@ -166,92 +141,93 @@ func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode { return newOpCode(opPtr, typ, e.indent, code) } -func (e *Encoder) compilePtr(typ *rtype, root, withIndent bool) (*opcode, error) { - code, err := e.compile(typ.Elem(), root, withIndent) +func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { + code, err := e.compile(ctx.withType(ctx.typ.Elem())) if err != nil { return nil, err } - return e.optimizeStructFieldPtrHead(typ, code), nil + return e.optimizeStructFieldPtrHead(ctx, code), nil } -func (e *Encoder) compileInt(typ *rtype) (*opcode, error) { - return newOpCode(opInt, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileInt(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opInt, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileInt8(typ *rtype) (*opcode, error) { - return newOpCode(opInt8, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileInt8(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opInt8, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileInt16(typ *rtype) (*opcode, error) { - return newOpCode(opInt16, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileInt16(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opInt16, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileInt32(typ *rtype) (*opcode, error) { - return newOpCode(opInt32, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileInt32(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opInt32, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileInt64(typ *rtype) (*opcode, error) { - return newOpCode(opInt64, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileInt64(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opInt64, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileUint(typ *rtype) (*opcode, error) { - return newOpCode(opUint, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileUint(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opUint, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileUint8(typ *rtype) (*opcode, error) { - return newOpCode(opUint8, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileUint8(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opUint8, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileUint16(typ *rtype) (*opcode, error) { - return newOpCode(opUint16, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileUint16(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opUint16, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileUint32(typ *rtype) (*opcode, error) { - return newOpCode(opUint32, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileUint32(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opUint32, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileUint64(typ *rtype) (*opcode, error) { - return newOpCode(opUint64, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opUint64, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileFloat32(typ *rtype) (*opcode, error) { - return newOpCode(opFloat32, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opFloat32, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileFloat64(typ *rtype) (*opcode, error) { - return newOpCode(opFloat64, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileFloat64(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opFloat64, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileString(typ *rtype) (*opcode, error) { - return newOpCode(opString, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileString(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opString, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileBool(typ *rtype) (*opcode, error) { - return newOpCode(opBool, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileBool(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opBool, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileBytes(typ *rtype) (*opcode, error) { - return newOpCode(opBytes, typ, e.indent, newEndOp(e.indent)), nil +func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { + return newOpCode(opBytes, ctx.typ, e.indent, newEndOp(e.indent)), nil } -func (e *Encoder) compileInterface(typ *rtype, root bool) (*opcode, error) { +func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { return (*opcode)(unsafe.Pointer(&interfaceCode{ opcodeHeader: &opcodeHeader{ op: opInterface, - typ: typ, + typ: ctx.typ, indent: e.indent, next: newEndOp(e.indent), }, - root: root, + root: ctx.root, })), nil } -func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, error) { - elem := typ.Elem() +func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { + ctx.root = false + elem := ctx.typ.Elem() size := elem.Size() e.indent++ - code, err := e.compile(elem, false, withIndent) + code, err := e.compile(ctx.withType(ctx.typ.Elem())) e.indent-- if err != nil { @@ -271,8 +247,8 @@ func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, erro size: size, } end := newOpCode(opSliceEnd, nil, e.indent, newEndOp(e.indent)) - if withIndent { - if root { + if ctx.withIndent { + if ctx.root { header.op = opRootSliceHeadIndent elemCode.op = opRootSliceElemIndent } else { @@ -291,13 +267,15 @@ func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, erro return (*opcode)(unsafe.Pointer(header)), nil } -func (e *Encoder) compileArray(typ *rtype, root, withIndent bool) (*opcode, error) { +func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { + ctx.root = false + typ := ctx.typ elem := typ.Elem() alen := typ.Len() size := elem.Size() e.indent++ - code, err := e.compile(elem, false, withIndent) + code, err := e.compile(ctx.withType(elem)) e.indent-- if err != nil { @@ -317,7 +295,7 @@ func (e *Encoder) compileArray(typ *rtype, root, withIndent bool) (*opcode, erro } end := newOpCode(opArrayEnd, nil, e.indent, newEndOp(e.indent)) - if withIndent { + if ctx.withIndent { header.op = opArrayHeadIndent elemCode.op = opArrayElemIndent end.op = opArrayEndIndent @@ -348,18 +326,19 @@ func mapiternext(it unsafe.Pointer) //go:noescape func maplen(m unsafe.Pointer) int -func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opcode, error) { +func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, error) { // header => code => value => code => key => code => value => code => end // ^ | // |_______________________| e.indent++ - keyType := typ.Key() - keyCode, err := e.compileKey(keyType, false, withIndent) + typ := ctx.typ + keyType := ctx.typ.Key() + keyCode, err := e.compileKey(ctx.withType(keyType)) if err != nil { return nil, err } valueType := typ.Elem() - valueCode, err := e.compile(valueType, false, withIndent) + valueCode, err := e.compile(ctx.withType(valueType)) if err != nil { return nil, err } @@ -374,9 +353,9 @@ func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opco header.value = value end := newOpCode(opMapEnd, nil, e.indent, newEndOp(e.indent)) - if withIndent { + if ctx.withIndent { if header.op == opMapHead { - if root { + if ctx.root { header.op = opRootMapHeadIndent } else { header.op = opMapHeadIndent @@ -384,7 +363,7 @@ func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opco } else { header.op = opMapHeadLoadIndent } - if root { + if ctx.root { key.op = opRootMapKeyIndent } else { key.op = opMapKeyIndent @@ -549,11 +528,11 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool return fieldType } -func (e *Encoder) recursiveCode(typ *rtype, code *compiledCode) *opcode { +func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { return (*opcode)(unsafe.Pointer(&recursiveCode{ opcodeHeader: &opcodeHeader{ op: opStructFieldRecursive, - typ: typ, + typ: ctx.typ, indent: e.indent, next: newEndOp(e.indent), }, @@ -561,15 +540,16 @@ func (e *Encoder) recursiveCode(typ *rtype, code *compiledCode) *opcode { })) } -func (e *Encoder) compiledCode(typ *rtype, withIndent bool) *opcode { +func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { + typ := ctx.typ typeptr := uintptr(unsafe.Pointer(typ)) - if withIndent { + if ctx.withIndent { if compiledCode, exists := e.structTypeToCompiledIndentCode[typeptr]; exists { - return e.recursiveCode(typ, compiledCode) + return e.recursiveCode(ctx, compiledCode) } } else { if compiledCode, exists := e.structTypeToCompiledCode[typeptr]; exists { - return e.recursiveCode(typ, compiledCode) + return e.recursiveCode(ctx, compiledCode) } } return nil @@ -790,13 +770,15 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s } } -func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opcode, error) { - if code := e.compiledCode(typ, withIndent); code != nil { +func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error) { + ctx.root = false + if code := e.compiledCode(ctx); code != nil { return code, nil } + typ := ctx.typ typeptr := uintptr(unsafe.Pointer(typ)) compiled := &compiledCode{} - if withIndent { + if ctx.withIndent { e.structTypeToCompiledIndentCode[typeptr] = compiled } else { e.structTypeToCompiledCode[typeptr] = compiled @@ -833,7 +815,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco fieldType = rtype_ptrTo(fieldType) } } - valueCode, err := e.compile(fieldType, false, withIndent) + valueCode, err := e.compile(ctx.withType(fieldType)) if err != nil { return nil, err } @@ -866,13 +848,13 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco offset: field.Offset, } if fieldIdx == 0 { - code = e.structHeader(fieldCode, valueCode, tag, withIndent) + code = e.structHeader(fieldCode, valueCode, tag, ctx.withIndent) head = fieldCode prevField = fieldCode } else { fcode := (*opcode)(unsafe.Pointer(fieldCode)) code.next = fcode - code = e.structField(fieldCode, valueCode, tag, withIndent) + code = e.structField(fieldCode, valueCode, tag, ctx.withIndent) prevField.nextField = fcode prevField = fieldCode } @@ -888,7 +870,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco }, })) structEndCode.next = newEndOp(e.indent) - if withIndent { + if ctx.withIndent { structEndCode.op = opStructEndIndent } @@ -906,7 +888,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco }, nextField: structEndCode, } - if withIndent { + if ctx.withIndent { head.op = opStructFieldHeadIndent } code = (*opcode)(unsafe.Pointer(head)) @@ -920,7 +902,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco ret := (*opcode)(unsafe.Pointer(head)) compiled.code = ret - if withIndent { + if ctx.withIndent { delete(e.structTypeToCompiledIndentCode, typeptr) } else { delete(e.structTypeToCompiledCode, typeptr) diff --git a/encode_vm.go b/encode_vm.go index 7126476..1873cdc 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -112,13 +112,21 @@ func (e *Encoder) run(code *opcode) error { e.indent = ifaceCode.indent var c *opcode if typ.Kind() == reflect.Map { - code, err := e.compileMap(typ, false, ifaceCode.root, e.enabledIndent) + code, err := e.compileMap(&encodeCompileContext{ + typ: typ, + root: ifaceCode.root, + withIndent: e.enabledIndent, + }, false) if err != nil { return err } c = code } else { - code, err := e.compile(typ, ifaceCode.root, e.enabledIndent) + code, err := e.compile(&encodeCompileContext{ + typ: typ, + root: ifaceCode.root, + withIndent: e.enabledIndent, + }) if err != nil { return err } From e508ad41ba65ec1c8ad94a07b38dcacee25bd4d9 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sat, 29 Aug 2020 15:35:03 +0900 Subject: [PATCH 02/18] Refactor indent parameter --- encode.go | 2 - encode_compile.go | 109 ++++++++++++++++++++++------------------------ encode_context.go | 37 ++++++++++++++++ encode_opcode.go | 23 +++++++--- encode_vm.go | 3 +- 5 files changed, 107 insertions(+), 67 deletions(-) create mode 100644 encode_context.go diff --git a/encode.go b/encode.go index 2247322..05b15d9 100644 --- a/encode.go +++ b/encode.go @@ -19,7 +19,6 @@ type Encoder struct { enabledHTMLEscape bool prefix []byte indentStr []byte - indent int structTypeToCompiledCode map[uintptr]*compiledCode structTypeToCompiledIndentCode map[uintptr]*compiledCode } @@ -123,7 +122,6 @@ func (e *Encoder) release() { func (e *Encoder) reset() { e.buf = e.buf[:0] - e.indent = 0 e.enabledHTMLEscape = true e.enabledIndent = false } diff --git a/encode_compile.go b/encode_compile.go index 229c485..b0e8800 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -10,13 +10,13 @@ func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalJSON), nil case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(opMarshalJSON, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil case typ.Implements(marshalTextType): - return newOpCode(opMarshalText, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalText), nil case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(opMarshalText, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil } isPtr := false if typ.Kind() == reflect.Ptr { @@ -49,13 +49,13 @@ func (e *Encoder) compile(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalJSON), nil case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(opMarshalJSON, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil case typ.Implements(marshalTextType): - return newOpCode(opMarshalText, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalText), nil case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(opMarshalText, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil } switch typ.Kind() { case reflect.Ptr: @@ -112,13 +112,13 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalJSON), nil case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(opMarshalJSON, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil case typ.Implements(marshalTextType): - return newOpCode(opMarshalText, typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opMarshalText), nil case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(opMarshalText, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil } switch typ.Kind() { case reflect.Ptr: @@ -132,13 +132,12 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { } func (e *Encoder) optimizeStructFieldPtrHead(ctx *encodeCompileContext, code *opcode) *opcode { - typ := ctx.typ ptrHeadOp := code.op.headToPtrHead() if code.op != ptrHeadOp { code.op = ptrHeadOp return code } - return newOpCode(opPtr, typ, e.indent, code) + return newOpCodeWithNext(ctx, opPtr, code) } func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { @@ -150,63 +149,63 @@ func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { } func (e *Encoder) compileInt(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opInt, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opInt), nil } func (e *Encoder) compileInt8(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opInt8, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opInt8), nil } func (e *Encoder) compileInt16(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opInt16, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opInt16), nil } func (e *Encoder) compileInt32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opInt32, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opInt32), nil } func (e *Encoder) compileInt64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opInt64, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opInt64), nil } func (e *Encoder) compileUint(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opUint, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opUint), nil } func (e *Encoder) compileUint8(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opUint8, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opUint8), nil } func (e *Encoder) compileUint16(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opUint16, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opUint16), nil } func (e *Encoder) compileUint32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opUint32, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opUint32), nil } func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opUint64, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opUint64), nil } func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opFloat32, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opFloat32), nil } func (e *Encoder) compileFloat64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opFloat64, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opFloat64), nil } func (e *Encoder) compileString(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opString, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opString), nil } func (e *Encoder) compileBool(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opBool, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opBool), nil } func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(opBytes, ctx.typ, e.indent, newEndOp(e.indent)), nil + return newOpCode(ctx, opBytes), nil } func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { @@ -214,8 +213,8 @@ func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { opcodeHeader: &opcodeHeader{ op: opInterface, typ: ctx.typ, - indent: e.indent, - next: newEndOp(e.indent), + indent: ctx.indent, + next: newEndOp(ctx), }, root: ctx.root, })), nil @@ -226,10 +225,7 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { elem := ctx.typ.Elem() size := elem.Size() - e.indent++ - code, err := e.compile(ctx.withType(ctx.typ.Elem())) - e.indent-- - + code, err := e.compile(ctx.withType(ctx.typ.Elem()).incIndent()) if err != nil { return nil, err } @@ -238,15 +234,15 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - header := newSliceHeaderCode(e.indent) + header := newSliceHeaderCode(ctx.indent) elemCode := &sliceElemCode{ opcodeHeader: &opcodeHeader{ op: opSliceElem, - indent: e.indent, + indent: ctx.indent, }, size: size, } - end := newOpCode(opSliceEnd, nil, e.indent, newEndOp(e.indent)) + end := newOpCode(ctx, opSliceEnd) if ctx.withIndent { if ctx.root { header.op = opRootSliceHeadIndent @@ -274,10 +270,7 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { alen := typ.Len() size := elem.Size() - e.indent++ - code, err := e.compile(ctx.withType(elem)) - e.indent-- - + code, err := e.compile(ctx.withType(elem).incIndent()) if err != nil { return nil, err } @@ -285,7 +278,7 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - header := newArrayHeaderCode(e.indent, alen) + header := newArrayHeaderCode(ctx.indent, alen) elemCode := &arrayElemCode{ opcodeHeader: &opcodeHeader{ op: opArrayElem, @@ -293,7 +286,7 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { len: uintptr(alen), size: size, } - end := newOpCode(opArrayEnd, nil, e.indent, newEndOp(e.indent)) + end := newOpCode(ctx, opArrayEnd) if ctx.withIndent { header.op = opArrayHeadIndent @@ -330,7 +323,7 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, // header => code => value => code => key => code => value => code => end // ^ | // |_______________________| - e.indent++ + ctx = ctx.incIndent() typ := ctx.typ keyType := ctx.typ.Key() keyCode, err := e.compileKey(ctx.withType(keyType)) @@ -343,15 +336,15 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, return nil, err } - key := newMapKeyCode(e.indent) - value := newMapValueCode(e.indent) + key := newMapKeyCode(ctx.indent) + value := newMapValueCode(ctx.indent) - e.indent-- + ctx = ctx.decIndent() - header := newMapHeaderCode(typ, withLoad, e.indent) + header := newMapHeaderCode(typ, withLoad, ctx.indent) header.key = key header.value = value - end := newOpCode(opMapEnd, nil, e.indent, newEndOp(e.indent)) + end := newOpCode(ctx, opMapEnd) if ctx.withIndent { if header.op == opMapHead { @@ -533,8 +526,8 @@ func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) * opcodeHeader: &opcodeHeader{ op: opStructFieldRecursive, typ: ctx.typ, - indent: e.indent, - next: newEndOp(e.indent), + indent: ctx.indent, + next: newEndOp(ctx), }, jmp: code, })) @@ -793,7 +786,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, code *opcode prevField *structFieldCode ) - e.indent++ + ctx = ctx.incIndent() tags := structTags{} anonymousFields := map[string][]structFieldPair{} for i := 0; i < fieldNum; i++ { @@ -839,7 +832,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, opcodeHeader: &opcodeHeader{ typ: valueCode.typ, next: valueCode, - indent: e.indent, + indent: ctx.indent, }, anonymousKey: field.Anonymous, key: []byte(key), @@ -860,16 +853,16 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } fieldIdx++ } - e.indent-- + ctx = ctx.decIndent() structEndCode := (*opcode)(unsafe.Pointer(&structFieldCode{ opcodeHeader: &opcodeHeader{ op: opStructEnd, typ: nil, - indent: e.indent, + indent: ctx.indent, }, })) - structEndCode.next = newEndOp(e.indent) + structEndCode.next = newEndOp(ctx) if ctx.withIndent { structEndCode.op = opStructEndIndent } @@ -884,7 +877,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, opcodeHeader: &opcodeHeader{ op: opStructFieldHead, typ: typ, - indent: e.indent, + indent: ctx.indent, }, nextField: structEndCode, } diff --git a/encode_context.go b/encode_context.go new file mode 100644 index 0000000..0d25884 --- /dev/null +++ b/encode_context.go @@ -0,0 +1,37 @@ +package json + +type encodeCompileContext struct { + typ *rtype + withIndent bool + root bool + opcodeIndex int + indent int +} + +func (c *encodeCompileContext) context() *encodeCompileContext { + return &encodeCompileContext{ + typ: c.typ, + withIndent: c.withIndent, + root: c.root, + opcodeIndex: c.opcodeIndex, + indent: c.indent, + } +} + +func (c *encodeCompileContext) withType(typ *rtype) *encodeCompileContext { + ctx := c.context() + ctx.typ = typ + return ctx +} + +func (c *encodeCompileContext) incIndent() *encodeCompileContext { + ctx := c.context() + ctx.indent++ + return ctx +} + +func (c *encodeCompileContext) decIndent() *encodeCompileContext { + ctx := c.context() + ctx.indent-- + return ctx +} diff --git a/encode_opcode.go b/encode_opcode.go index 3b78686..b95d1e2 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -34,19 +34,30 @@ type opcode struct { *opcodeHeader } -func newOpCode(op opType, typ *rtype, indent int, next *opcode) *opcode { +func newOpCode(ctx *encodeCompileContext, op opType) *opcode { return &opcode{ opcodeHeader: &opcodeHeader{ op: op, - typ: typ, - indent: indent, + typ: ctx.typ, + indent: ctx.indent, + next: newEndOp(ctx), + }, + } +} + +func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { + return &opcode{ + opcodeHeader: &opcodeHeader{ + op: op, + typ: ctx.typ, + indent: ctx.indent, next: next, }, } } -func newEndOp(indent int) *opcode { - return newOpCode(opEnd, nil, indent, nil) +func newEndOp(ctx *encodeCompileContext) *opcode { + return newOpCodeWithNext(ctx, opEnd, nil) } func (c *opcode) beforeLastCode() *opcode { @@ -547,7 +558,7 @@ func (c *recursiveCode) copy(codeMap map[uintptr]*opcode) *opcode { func newRecursiveCode(recursive *recursiveCode) *opcode { code := copyOpcode(recursive.jmp.code) head := (*structFieldCode)(unsafe.Pointer(code)) - head.end.next = newEndOp(0) + head.end.next = newEndOp(&encodeCompileContext{}) code.ptr = recursive.ptr code.op = code.op.ptrHeadToHead() diff --git a/encode_vm.go b/encode_vm.go index 1873cdc..3f8f012 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -109,13 +109,13 @@ func (e *Encoder) run(code *opcode) error { if typ.Kind() == reflect.Ptr { typ = typ.Elem() } - e.indent = ifaceCode.indent var c *opcode if typ.Kind() == reflect.Map { code, err := e.compileMap(&encodeCompileContext{ typ: typ, root: ifaceCode.root, withIndent: e.enabledIndent, + indent: ifaceCode.indent, }, false) if err != nil { return err @@ -126,6 +126,7 @@ func (e *Encoder) run(code *opcode) error { typ: typ, root: ifaceCode.root, withIndent: e.enabledIndent, + indent: ifaceCode.indent, }) if err != nil { return err From a9e2386e4297d1dda8428f59931abc4c52343b2f Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sun, 30 Aug 2020 17:32:26 +0900 Subject: [PATCH 03/18] Add opcodeIndex to opcode --- encode_compile.go | 259 +++++++++++++++++++++++++++++++--------------- encode_context.go | 17 +++ encode_opcode.go | 87 +++++++++++----- 3 files changed, 258 insertions(+), 105 deletions(-) diff --git a/encode_compile.go b/encode_compile.go index b0e8800..c2e6ed7 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -10,13 +10,13 @@ func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(ctx, opMarshalJSON), nil + return e.compileMarshalJSON(ctx) case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil + return e.compileMarshalJSONPtr(ctx) case typ.Implements(marshalTextType): - return newOpCode(ctx, opMarshalText), nil + return e.compileMarshalText(ctx) case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil + return e.compileMarshalTextPtr(ctx) } isPtr := false if typ.Kind() == reflect.Ptr { @@ -49,13 +49,13 @@ func (e *Encoder) compile(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(ctx, opMarshalJSON), nil + return e.compileMarshalJSON(ctx) case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil + return e.compileMarshalJSONPtr(ctx) case typ.Implements(marshalTextType): - return newOpCode(ctx, opMarshalText), nil + return e.compileMarshalText(ctx) case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil + return e.compileMarshalTextPtr(ctx) } switch typ.Kind() { case reflect.Ptr: @@ -112,13 +112,13 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { typ := ctx.typ switch { case typ.Implements(marshalJSONType): - return newOpCode(ctx, opMarshalJSON), nil + return e.compileMarshalJSON(ctx) case rtype_ptrTo(typ).Implements(marshalJSONType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil + return e.compileMarshalJSONPtr(ctx) case typ.Implements(marshalTextType): - return newOpCode(ctx, opMarshalText), nil + return e.compileMarshalText(ctx) case rtype_ptrTo(typ).Implements(marshalTextType): - return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil + return e.compileMarshalTextPtr(ctx) } switch typ.Kind() { case reflect.Ptr: @@ -131,93 +131,152 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { return nil, &UnsupportedTypeError{Type: rtype2type(typ)} } -func (e *Encoder) optimizeStructFieldPtrHead(ctx *encodeCompileContext, code *opcode) *opcode { - ptrHeadOp := code.op.headToPtrHead() - if code.op != ptrHeadOp { - code.op = ptrHeadOp - return code - } - return newOpCodeWithNext(ctx, opPtr, code) -} - func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { + ptrOpcodeIndex := ctx.opcodeIndex + ctx.incOpcodeIndex() code, err := e.compile(ctx.withType(ctx.typ.Elem())) if err != nil { return nil, err } - return e.optimizeStructFieldPtrHead(ctx, code), nil + ptrHeadOp := code.op.headToPtrHead() + if code.op != ptrHeadOp { + code.op = ptrHeadOp + code.decOpcodeIndex() + ctx.decOpcodeIndex() + return code, nil + } + c := ctx.context() + c.opcodeIndex = ptrOpcodeIndex + return newOpCodeWithNext(c, opPtr, code), nil +} + +func (e *Encoder) compileMarshalJSON(ctx *encodeCompileContext) (*opcode, error) { + code := newOpCode(ctx, opMarshalJSON) + ctx.incOpcodeIndex() + return code, nil +} + +func (e *Encoder) compileMarshalJSONPtr(ctx *encodeCompileContext) (*opcode, error) { + code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalJSON) + ctx.incOpcodeIndex() + return code, nil +} + +func (e *Encoder) compileMarshalText(ctx *encodeCompileContext) (*opcode, error) { + code := newOpCode(ctx, opMarshalText) + ctx.incOpcodeIndex() + return code, nil +} + +func (e *Encoder) compileMarshalTextPtr(ctx *encodeCompileContext) (*opcode, error) { + code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalText) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInt(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opInt), nil + code := newOpCode(ctx, opInt) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInt8(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opInt8), nil + code := newOpCode(ctx, opInt8) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInt16(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opInt16), nil + code := newOpCode(ctx, opInt16) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInt32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opInt32), nil + code := newOpCode(ctx, opInt32) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInt64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opInt64), nil + code := newOpCode(ctx, opInt64) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileUint(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opUint), nil + code := newOpCode(ctx, opUint) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileUint8(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opUint8), nil + code := newOpCode(ctx, opUint8) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileUint16(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opUint16), nil + code := newOpCode(ctx, opUint16) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileUint32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opUint32), nil + code := newOpCode(ctx, opUint32) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opUint64), nil + code := newOpCode(ctx, opUint64) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opFloat32), nil + code := newOpCode(ctx, opFloat32) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileFloat64(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opFloat64), nil + code := newOpCode(ctx, opFloat64) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileString(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opString), nil + code := newOpCode(ctx, opString) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileBool(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opBool), nil + code := newOpCode(ctx, opBool) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { - return newOpCode(ctx, opBytes), nil + code := newOpCode(ctx, opBytes) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { - return (*opcode)(unsafe.Pointer(&interfaceCode{ + code := (*opcode)(unsafe.Pointer(&interfaceCode{ opcodeHeader: &opcodeHeader{ op: opInterface, typ: ctx.typ, + idx: ctx.opcodeIndex, indent: ctx.indent, next: newEndOp(ctx), }, root: ctx.root, - })), nil + })) + ctx.incOpcodeIndex() + return code, nil } func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { @@ -225,6 +284,9 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { elem := ctx.typ.Elem() size := elem.Size() + header := newSliceHeaderCode(ctx) + ctx.incOpcodeIndex() + code, err := e.compile(ctx.withType(ctx.typ.Elem()).incIndent()) if err != nil { return nil, err @@ -234,15 +296,11 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - header := newSliceHeaderCode(ctx.indent) - elemCode := &sliceElemCode{ - opcodeHeader: &opcodeHeader{ - op: opSliceElem, - indent: ctx.indent, - }, - size: size, - } + elemCode := newSliceElemCode(ctx, size) + ctx.incOpcodeIndex() + end := newOpCode(ctx, opSliceEnd) + ctx.incOpcodeIndex() if ctx.withIndent { if ctx.root { header.op = opRootSliceHeadIndent @@ -270,6 +328,9 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { alen := typ.Len() size := elem.Size() + header := newArrayHeaderCode(ctx, alen) + ctx.incOpcodeIndex() + code, err := e.compile(ctx.withType(elem).incIndent()) if err != nil { return nil, err @@ -278,15 +339,11 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - header := newArrayHeaderCode(ctx.indent, alen) - elemCode := &arrayElemCode{ - opcodeHeader: &opcodeHeader{ - op: opArrayElem, - }, - len: uintptr(alen), - size: size, - } + elemCode := newArrayElemCode(ctx, alen, size) + ctx.incOpcodeIndex() + end := newOpCode(ctx, opArrayEnd) + ctx.incOpcodeIndex() if ctx.withIndent { header.op = opArrayHeadIndent @@ -324,27 +381,34 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, // ^ | // |_______________________| ctx = ctx.incIndent() + header := newMapHeaderCode(ctx, withLoad) + ctx.incOpcodeIndex() + typ := ctx.typ keyType := ctx.typ.Key() keyCode, err := e.compileKey(ctx.withType(keyType)) if err != nil { return nil, err } + + value := newMapValueCode(ctx) + ctx.incOpcodeIndex() + valueType := typ.Elem() valueCode, err := e.compile(ctx.withType(valueType)) if err != nil { return nil, err } - key := newMapKeyCode(ctx.indent) - value := newMapValueCode(ctx.indent) + key := newMapKeyCode(ctx) + ctx.incOpcodeIndex() ctx = ctx.decIndent() - header := newMapHeaderCode(typ, withLoad, ctx.indent) header.key = key header.value = value end := newOpCode(ctx, opMapEnd) + ctx.incOpcodeIndex() if ctx.withIndent { if header.op == opMapHead { @@ -522,15 +586,18 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool } func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { - return (*opcode)(unsafe.Pointer(&recursiveCode{ + c := (*opcode)(unsafe.Pointer(&recursiveCode{ opcodeHeader: &opcodeHeader{ op: opStructFieldRecursive, typ: ctx.typ, + idx: ctx.opcodeIndex, indent: ctx.indent, next: newEndOp(ctx), }, jmp: code, })) + ctx.incOpcodeIndex() + return c } func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { @@ -548,9 +615,9 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { return nil } -func (e *Encoder) structHeader(fieldCode *structFieldCode, valueCode *opcode, tag *structTag, withIndent bool) *opcode { +func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *structFieldCode, valueCode *opcode, tag *structTag) *opcode { fieldCode.indent-- - op := e.optimizeStructHeader(valueCode.op, tag, withIndent) + op := e.optimizeStructHeader(valueCode.op, tag, ctx.withIndent) fieldCode.op = op switch op { case opStructFieldHead, @@ -581,12 +648,13 @@ func (e *Encoder) structHeader(fieldCode *structFieldCode, valueCode *opcode, ta opStructFieldHeadStringTagIndent: return valueCode.beforeLastCode() } + ctx.decOpcodeIndex() return (*opcode)(unsafe.Pointer(fieldCode)) } -func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, tag *structTag, withIndent bool) *opcode { +func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *structFieldCode, valueCode *opcode, tag *structTag) *opcode { code := (*opcode)(unsafe.Pointer(fieldCode)) - op := e.optimizeStructField(valueCode.op, tag, withIndent) + op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent) fieldCode.op = op switch op { case opStructField, @@ -617,6 +685,7 @@ func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, tag opStructFieldStringTagIndent: return valueCode.beforeLastCode() } + ctx.decOpcodeIndex() return code } @@ -657,6 +726,10 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { if codeType == codeStructField { if e.isNotExistsField(code.next.toStructFieldCode()) { code.next = code.nextField + diff := code.next.idx - code.idx + for i := 0; i < diff; i++ { + code.next.decOpcodeIndex() + } linkPrevToNextField(prev, code) code = prev } @@ -690,6 +763,10 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value } else if f.op == opStructEnd { f.op = opStructAnonymousEnd } else if existsKey { + diff := f.nextField.idx - f.idx + for i := 0; i < diff; i++ { + f.nextField.decOpcodeIndex() + } linkPrevToNextField(prevAnonymousField, f) } @@ -737,6 +814,10 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { + diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + for i := 0; i < diff; i++ { + fieldPair.curField.nextField.decOpcodeIndex() + } linkPrevToNextField(fieldPair.prevField, fieldPair.curField) } fieldPair.linked = true @@ -750,6 +831,10 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { + diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + for i := 0; i < diff; i++ { + fieldPair.curField.nextField.decOpcodeIndex() + } linkPrevToNextField(fieldPair.prevField, fieldPair.curField) } fieldPair.linked = true @@ -808,10 +893,13 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, fieldType = rtype_ptrTo(fieldType) } } + fieldOpcodeIndex := ctx.opcodeIndex + ctx.incOpcodeIndex() valueCode, err := e.compile(ctx.withType(fieldType)) if err != nil { return nil, err } + if field.Anonymous { for k, v := range e.anonymousStructFieldPairMap(typ, tags, valueCode.toStructFieldCode()) { anonymousFields[k] = append(anonymousFields[k], v...) @@ -825,12 +913,14 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, opUint, opUint8, opUint16, opUint32, opUint64, opFloat32, opFloat64, opBool, opString, opBytes: valueCode = valueCode.next + ctx.decOpcodeIndex() } } key := fmt.Sprintf(`"%s":`, tag.key) fieldCode := &structFieldCode{ opcodeHeader: &opcodeHeader{ typ: valueCode.typ, + idx: fieldOpcodeIndex, next: valueCode, indent: ctx.indent, }, @@ -841,13 +931,13 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, offset: field.Offset, } if fieldIdx == 0 { - code = e.structHeader(fieldCode, valueCode, tag, ctx.withIndent) + code = e.structHeader(ctx, fieldCode, valueCode, tag) head = fieldCode prevField = fieldCode } else { fcode := (*opcode)(unsafe.Pointer(fieldCode)) code.next = fcode - code = e.structField(fieldCode, valueCode, tag, ctx.withIndent) + code = e.structField(ctx, fieldCode, valueCode, tag) prevField.nextField = fcode prevField = fieldCode } @@ -860,9 +950,31 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, op: opStructEnd, typ: nil, indent: ctx.indent, + next: newEndOp(ctx), }, })) - structEndCode.next = newEndOp(ctx) + + // no struct field + if head == nil { + head = &structFieldCode{ + opcodeHeader: &opcodeHeader{ + op: opStructFieldHead, + typ: typ, + idx: ctx.opcodeIndex, + indent: ctx.indent, + }, + nextField: structEndCode, + } + ctx.incOpcodeIndex() + if ctx.withIndent { + head.op = opStructFieldHeadIndent + } + code = (*opcode)(unsafe.Pointer(head)) + } + + structEndCode.idx = ctx.opcodeIndex + ctx.incOpcodeIndex() + if ctx.withIndent { structEndCode.op = opStructEndIndent } @@ -871,21 +983,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, prevField.nextField = structEndCode } - // no struct field - if head == nil { - head = &structFieldCode{ - opcodeHeader: &opcodeHeader{ - op: opStructFieldHead, - typ: typ, - indent: ctx.indent, - }, - nextField: structEndCode, - } - if ctx.withIndent { - head.op = opStructFieldHeadIndent - } - code = (*opcode)(unsafe.Pointer(head)) - } head.end = structEndCode code.next = structEndCode diff --git a/encode_context.go b/encode_context.go index 0d25884..6c6f4a0 100644 --- a/encode_context.go +++ b/encode_context.go @@ -6,6 +6,8 @@ type encodeCompileContext struct { root bool opcodeIndex int indent int + + parent *encodeCompileContext } func (c *encodeCompileContext) context() *encodeCompileContext { @@ -15,6 +17,7 @@ func (c *encodeCompileContext) context() *encodeCompileContext { root: c.root, opcodeIndex: c.opcodeIndex, indent: c.indent, + parent: c, } } @@ -35,3 +38,17 @@ func (c *encodeCompileContext) decIndent() *encodeCompileContext { ctx.indent-- return ctx } + +func (c *encodeCompileContext) incOpcodeIndex() { + c.opcodeIndex++ + if c.parent != nil { + c.parent.incOpcodeIndex() + } +} + +func (c *encodeCompileContext) decOpcodeIndex() { + c.opcodeIndex-- + if c.parent != nil { + c.parent.decOpcodeIndex() + } +} diff --git a/encode_opcode.go b/encode_opcode.go index b95d1e2..6740f67 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -15,6 +15,7 @@ func copyOpcode(code *opcode) *opcode { type opcodeHeader struct { op opType typ *rtype + idx int ptr uintptr indent int next *opcode @@ -24,6 +25,7 @@ func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader { return &opcodeHeader{ op: h.op, typ: h.typ, + idx: h.idx, ptr: h.ptr, indent: h.indent, next: h.next.copy(codeMap), @@ -35,14 +37,7 @@ type opcode struct { } func newOpCode(ctx *encodeCompileContext, op opType) *opcode { - return &opcode{ - opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - indent: ctx.indent, - next: newEndOp(ctx), - }, - } + return newOpCodeWithNext(ctx, op, newEndOp(ctx)) } func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { @@ -50,6 +45,7 @@ func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opco opcodeHeader: &opcodeHeader{ op: op, typ: ctx.typ, + idx: ctx.opcodeIndex, indent: ctx.indent, next: next, }, @@ -82,6 +78,22 @@ func (c *opcode) beforeLastCode() *opcode { return nil } +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 @@ -125,22 +137,22 @@ func (c *opcode) dump() string { indent := strings.Repeat(" ", code.indent) switch code.op.codeType() { case codeArrayElem: - codes = append(codes, fmt.Sprintf("%s%s ( %p )", indent, code.op, unsafe.Pointer(code))) + 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("%s%s ( %p )", indent, code.op, unsafe.Pointer(code))) + 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("%s%s ( %p )", indent, code.op, unsafe.Pointer(code))) + 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("%s%s [%s:%d] ( %p )", indent, code.op, key, offset, unsafe.Pointer(code))) + 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("%s%s ( %p )", indent, code.op, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) code = code.next } } @@ -193,15 +205,27 @@ type sliceHeaderCode struct { end *opcode } -func newSliceHeaderCode(indent int) *sliceHeaderCode { +func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode { return &sliceHeaderCode{ opcodeHeader: &opcodeHeader{ op: opSliceHead, - indent: indent, + 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 @@ -264,16 +288,28 @@ type arrayHeaderCode struct { end *opcode } -func newArrayHeaderCode(indent, alen int) *arrayHeaderCode { +func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode { return &arrayHeaderCode{ opcodeHeader: &opcodeHeader{ op: opArrayHead, - indent: indent, + 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 @@ -475,7 +511,7 @@ func (c *mapValueCode) set(iter unsafe.Pointer) { c.iter = iter } -func newMapHeaderCode(typ *rtype, withLoad bool, indent int) *mapHeaderCode { +func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode { var op opType if withLoad { op = opMapHeadLoad @@ -485,26 +521,29 @@ func newMapHeaderCode(typ *rtype, withLoad bool, indent int) *mapHeaderCode { return &mapHeaderCode{ opcodeHeader: &opcodeHeader{ op: op, - typ: typ, - indent: indent, + typ: ctx.typ, + idx: ctx.opcodeIndex, + indent: ctx.indent, }, } } -func newMapKeyCode(indent int) *mapKeyCode { +func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { return &mapKeyCode{ opcodeHeader: &opcodeHeader{ op: opMapKey, - indent: indent, + idx: ctx.opcodeIndex, + indent: ctx.indent, }, } } -func newMapValueCode(indent int) *mapValueCode { +func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { return &mapValueCode{ opcodeHeader: &opcodeHeader{ op: opMapValue, - indent: indent, + idx: ctx.opcodeIndex, + indent: ctx.indent, }, } } From cb194687a0a04f65d05944a062cf49bfeef5afac Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sun, 30 Aug 2020 17:52:59 +0900 Subject: [PATCH 04/18] Add encodeRuntimeContext --- encode.go | 17 ++++++++++++++--- encode_context.go | 16 ++++++++++++++++ encode_opcode.go | 18 ++++++++++++++++++ encode_vm.go | 4 ++-- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/encode.go b/encode.go index 05b15d9..ed77942 100644 --- a/encode.go +++ b/encode.go @@ -38,6 +38,7 @@ type opcodeMap struct { type opcodeSet struct { codeIndent sync.Pool code sync.Pool + ctx sync.Pool } func (m *opcodeMap) get(k uintptr) *opcodeSet { @@ -161,9 +162,11 @@ func (e *Encoder) encode(v interface{}) error { } else { code = codeSet.code.Get().(*opcode) } + ctx := codeSet.ctx.Get().(encodeRuntimeContext) p := uintptr(header.ptr) + ctx.init(p) code.ptr = p - if err := e.run(code); err != nil { + if err := e.run(ctx, code); err != nil { return err } if e.enabledIndent { @@ -193,6 +196,7 @@ func (e *Encoder) encode(v interface{}) error { if err != nil { return err } + codeLength := code.length() codeSet := &opcodeSet{ codeIndent: sync.Pool{ New: func() interface{} { @@ -204,15 +208,22 @@ func (e *Encoder) encode(v interface{}) error { return copyOpcode(code) }, }, + ctx: sync.Pool{ + New: func() interface{} { + return make(encodeRuntimeContext, codeLength) + }, + }, } cachedOpcode.set(typeptr, codeSet) p := uintptr(header.ptr) + ctx := codeSet.ctx.Get().(encodeRuntimeContext) + ctx.init(p) if e.enabledIndent { codeIndent.ptr = p - return e.run(codeIndent) + return e.run(ctx, codeIndent) } code.ptr = p - return e.run(code) + return e.run(ctx, code) } func (e *Encoder) encodeInt(v int) { diff --git a/encode_context.go b/encode_context.go index 6c6f4a0..458bb4c 100644 --- a/encode_context.go +++ b/encode_context.go @@ -1,5 +1,10 @@ package json +import ( + "reflect" + "unsafe" +) + type encodeCompileContext struct { typ *rtype withIndent bool @@ -52,3 +57,14 @@ func (c *encodeCompileContext) decOpcodeIndex() { c.parent.decOpcodeIndex() } } + +type encodeRuntimeContext []uintptr + +func (c *encodeRuntimeContext) init(p uintptr) { + (*c)[0] = p +} + +func (c *encodeRuntimeContext) ptr() *uintptr { + header := (*reflect.SliceHeader)(unsafe.Pointer(c)) + return (*uintptr)(unsafe.Pointer(&header.Data)) +} diff --git a/encode_opcode.go b/encode_opcode.go index 6740f67..04f7c23 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -78,6 +78,24 @@ func (c *opcode) beforeLastCode() *opcode { 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-- diff --git a/encode_vm.go b/encode_vm.go index 3f8f012..b8d0dbf 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -11,7 +11,7 @@ import ( "unsafe" ) -func (e *Encoder) run(code *opcode) error { +func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { seenPtr := map[uintptr]struct{}{} for { switch code.op { @@ -546,7 +546,7 @@ func (e *Encoder) run(code *opcode) error { } } recursive.seenPtr = recursive.ptr - if err := e.run(newRecursiveCode(recursive)); err != nil { + if err := e.run(nil, newRecursiveCode(recursive)); err != nil { return err } code = recursive.next From 70f8f01ef3ed9d7c0e3a5e87fae746c31837c30e Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sun, 30 Aug 2020 23:58:58 +0900 Subject: [PATCH 05/18] Use encodeRuntimeContext.ptrs instead of opcode.ptr --- encode.go | 30 +- encode_context.go | 13 +- encode_opcode.go | 3 - encode_vm.go | 2114 +++++++++++++++++++++++++-------------------- 4 files changed, 1211 insertions(+), 949 deletions(-) diff --git a/encode.go b/encode.go index ed77942..1fff880 100644 --- a/encode.go +++ b/encode.go @@ -162,19 +162,17 @@ func (e *Encoder) encode(v interface{}) error { } else { code = codeSet.code.Get().(*opcode) } - ctx := codeSet.ctx.Get().(encodeRuntimeContext) + ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) ctx.init(p) - code.ptr = p - if err := e.run(ctx, code); err != nil { - return err - } + err := e.run(ctx, code) if e.enabledIndent { codeSet.codeIndent.Put(code) } else { codeSet.code.Put(code) } - return nil + codeSet.ctx.Put(ctx) + return err } // noescape trick for header.typ ( reflect.*rtype ) @@ -210,20 +208,28 @@ func (e *Encoder) encode(v interface{}) error { }, ctx: sync.Pool{ New: func() interface{} { - return make(encodeRuntimeContext, codeLength) + return &encodeRuntimeContext{ + ptrs: make([]uintptr, codeLength), + seenPtr: map[uintptr]struct{}{}, + } }, }, } cachedOpcode.set(typeptr, codeSet) p := uintptr(header.ptr) - ctx := codeSet.ctx.Get().(encodeRuntimeContext) + ctx := codeSet.ctx.Get().(*encodeRuntimeContext) ctx.init(p) if e.enabledIndent { - codeIndent.ptr = p - return e.run(ctx, codeIndent) + err := e.run(ctx, codeIndent) + codeSet.ctx.Put(ctx) + return err } - code.ptr = p - return e.run(ctx, code) + if err := e.run(ctx, code); err != nil { + codeSet.ctx.Put(ctx) + return err + } + codeSet.ctx.Put(ctx) + return err } func (e *Encoder) encodeInt(v int) { diff --git a/encode_context.go b/encode_context.go index 458bb4c..da3d233 100644 --- a/encode_context.go +++ b/encode_context.go @@ -58,13 +58,16 @@ func (c *encodeCompileContext) decOpcodeIndex() { } } -type encodeRuntimeContext []uintptr +type encodeRuntimeContext struct { + ptrs []uintptr + seenPtr map[uintptr]struct{} +} func (c *encodeRuntimeContext) init(p uintptr) { - (*c)[0] = p + c.ptrs[0] = p } -func (c *encodeRuntimeContext) ptr() *uintptr { - header := (*reflect.SliceHeader)(unsafe.Pointer(c)) - return (*uintptr)(unsafe.Pointer(&header.Data)) +func (c *encodeRuntimeContext) ptr() uintptr { + header := (*reflect.SliceHeader)(unsafe.Pointer(&c.ptrs)) + return header.Data } diff --git a/encode_opcode.go b/encode_opcode.go index 04f7c23..0b49ed0 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -16,7 +16,6 @@ type opcodeHeader struct { op opType typ *rtype idx int - ptr uintptr indent int next *opcode } @@ -26,7 +25,6 @@ func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader { op: h.op, typ: h.typ, idx: h.idx, - ptr: h.ptr, indent: h.indent, next: h.next.copy(codeMap), } @@ -616,7 +614,6 @@ func newRecursiveCode(recursive *recursiveCode) *opcode { code := copyOpcode(recursive.jmp.code) head := (*structFieldCode)(unsafe.Pointer(code)) head.end.next = newEndOp(&encodeCompileContext{}) - code.ptr = recursive.ptr code.op = code.op.ptrHeadToHead() return code diff --git a/encode_vm.go b/encode_vm.go index b8d0dbf..bc02567 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -11,49 +11,58 @@ import ( "unsafe" ) -func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { - seenPtr := map[uintptr]struct{}{} +func load(base uintptr, idx int) uintptr { + return *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) +} + +func store(base uintptr, idx int, p uintptr) { + *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) = p +} + +func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { + ctxptr := ctx.ptr() + seenPtr := ctx.seenPtr for { switch code.op { case opPtr: - ptr := code.ptr + ptr := load(ctxptr, code.idx) code = code.next - code.ptr = e.ptrToPtr(ptr) + store(ctxptr, code.idx, e.ptrToPtr(ptr)) case opInt: - e.encodeInt(e.ptrToInt(code.ptr)) + e.encodeInt(e.ptrToInt(load(ctxptr, code.idx))) code = code.next case opInt8: - e.encodeInt8(e.ptrToInt8(code.ptr)) + e.encodeInt8(e.ptrToInt8(load(ctxptr, code.idx))) code = code.next case opInt16: - e.encodeInt16(e.ptrToInt16(code.ptr)) + e.encodeInt16(e.ptrToInt16(load(ctxptr, code.idx))) code = code.next case opInt32: - e.encodeInt32(e.ptrToInt32(code.ptr)) + e.encodeInt32(e.ptrToInt32(load(ctxptr, code.idx))) code = code.next case opInt64: - e.encodeInt64(e.ptrToInt64(code.ptr)) + e.encodeInt64(e.ptrToInt64(load(ctxptr, code.idx))) code = code.next case opUint: - e.encodeUint(e.ptrToUint(code.ptr)) + e.encodeUint(e.ptrToUint(load(ctxptr, code.idx))) code = code.next case opUint8: - e.encodeUint8(e.ptrToUint8(code.ptr)) + e.encodeUint8(e.ptrToUint8(load(ctxptr, code.idx))) code = code.next case opUint16: - e.encodeUint16(e.ptrToUint16(code.ptr)) + e.encodeUint16(e.ptrToUint16(load(ctxptr, code.idx))) code = code.next case opUint32: - e.encodeUint32(e.ptrToUint32(code.ptr)) + e.encodeUint32(e.ptrToUint32(load(ctxptr, code.idx))) code = code.next case opUint64: - e.encodeUint64(e.ptrToUint64(code.ptr)) + e.encodeUint64(e.ptrToUint64(load(ctxptr, code.idx))) code = code.next case opFloat32: - e.encodeFloat32(e.ptrToFloat32(code.ptr)) + e.encodeFloat32(e.ptrToFloat32(load(ctxptr, code.idx))) code = code.next case opFloat64: - v := e.ptrToFloat64(code.ptr) + v := e.ptrToFloat64(load(ctxptr, code.idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -63,18 +72,18 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) code = code.next case opString: - e.encodeString(e.ptrToString(code.ptr)) + e.encodeString(e.ptrToString(load(ctxptr, code.idx))) code = code.next case opBool: - e.encodeBool(e.ptrToBool(code.ptr)) + e.encodeBool(e.ptrToBool(load(ctxptr, code.idx))) code = code.next case opBytes: - ptr := code.ptr + ptr := load(ctxptr, code.idx) header := (*reflect.SliceHeader)(unsafe.Pointer(ptr)) if ptr == 0 || header.Data == 0 { e.encodeNull() } else { - b := e.ptrToBytes(code.ptr) + b := e.ptrToBytes(ptr) encodedLen := base64.StdEncoding.EncodedLen(len(b)) e.encodeByte('"') buf := make([]byte, encodedLen) @@ -85,7 +94,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next case opInterface: ifaceCode := code.toInterfaceCode() - ptr := ifaceCode.ptr + ptr := load(ctxptr, ifaceCode.idx) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: ifaceCode.typ, ptr: unsafe.Pointer(ptr), @@ -133,11 +142,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } c = code } - c.ptr = uintptr(header.ptr) - c.beforeLastCode().next = code.next - code = c + ctx := &encodeRuntimeContext{ + ptrs: make([]uintptr, c.length()), + seenPtr: seenPtr, + } + ctx.init(uintptr(header.ptr)) + if err := e.run(ctx, c); err != nil { + return err + } + code = ifaceCode.next case opMarshalJSON: - ptr := code.ptr + ptr := load(ctxptr, code.idx) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(ptr), @@ -173,7 +188,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(buf.Bytes()) code = code.next case opMarshalText: - ptr := code.ptr + ptr := load(ctxptr, code.idx) isPtr := code.typ.Kind() == reflect.Ptr p := unsafe.Pointer(ptr) if p == nil { @@ -199,7 +214,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } code = code.next case opSliceHead: - p := code.ptr + p := load(ctxptr, code.idx) headerCode := code.toSliceHeaderCode() header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { @@ -210,7 +225,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { headerCode.elem.set(header) if header.Len > 0 { code = code.next - code.ptr = header.Data + store(ctxptr, code.idx, header.Data) } else { e.encodeByte(']') code = headerCode.end.next @@ -222,13 +237,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { if c.idx < c.len { e.encodeByte(',') code = code.next - code.ptr = c.data + c.idx*c.size + store(ctxptr, code.idx, c.data+c.idx*c.size) } else { e.encodeByte(']') code = c.end.next } case opSliceHeadIndent: - p := code.ptr + p := load(ctxptr, code.idx) headerCode := code.toSliceHeaderCode() if p == 0 { e.encodeIndent(code.indent) @@ -241,7 +256,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{'[', '\n'}) e.encodeIndent(code.indent + 1) code = code.next - code.ptr = header.Data + store(ctxptr, code.idx, header.Data) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'[', ']'}) @@ -249,7 +264,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } case opRootSliceHeadIndent: - p := code.ptr + p := load(ctxptr, code.idx) headerCode := code.toSliceHeaderCode() if p == 0 { e.encodeIndent(code.indent) @@ -262,7 +277,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{'[', '\n'}) e.encodeIndent(code.indent + 1) code = code.next - code.ptr = header.Data + store(ctxptr, code.idx, header.Data) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'[', ']'}) @@ -276,7 +291,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) code = code.next - code.ptr = c.data + c.idx*c.size + store(ctxptr, code.idx, c.data+c.idx*c.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) @@ -290,7 +305,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) code = code.next - code.ptr = c.data + c.idx*c.size + store(ctxptr, code.idx, c.data+c.idx*c.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) @@ -298,7 +313,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = c.end.next } case opArrayHead: - p := code.ptr + p := load(ctxptr, code.idx) headerCode := code.toArrayHeaderCode() if p == 0 { e.encodeNull() @@ -307,8 +322,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('[') if headerCode.len > 0 { code = code.next - code.ptr = p - headerCode.elem.ptr = p + store(ctxptr, code.idx, p) + store(ctxptr, headerCode.elem.opcodeHeader.idx, p) } else { e.encodeByte(']') code = headerCode.end.next @@ -317,16 +332,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { case opArrayElem: c := code.toArrayElemCode() c.idx++ + p := load(ctxptr, c.opcodeHeader.idx) if c.idx < c.len { e.encodeByte(',') code = code.next - code.ptr = c.ptr + c.idx*c.size + store(ctxptr, code.idx, p+c.idx*c.size) } else { e.encodeByte(']') code = c.end.next } case opArrayHeadIndent: - p := code.ptr + p := load(ctxptr, code.idx) headerCode := code.toArrayHeaderCode() if p == 0 { e.encodeIndent(code.indent) @@ -337,8 +353,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { if headerCode.len > 0 { e.encodeIndent(code.indent + 1) code = code.next - code.ptr = p - headerCode.elem.ptr = p + store(ctxptr, code.idx, p) + store(ctxptr, headerCode.elem.opcodeHeader.idx, p) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{']', '\n'}) @@ -348,11 +364,12 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { case opArrayElemIndent: c := code.toArrayElemCode() c.idx++ + p := load(ctxptr, c.opcodeHeader.idx) if c.idx < c.len { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) code = code.next - code.ptr = c.ptr + c.idx*c.size + store(ctxptr, code.idx, p+c.idx*c.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) @@ -360,7 +377,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = c.end.next } case opMapHead: - ptr := code.ptr + ptr := load(ctxptr, code.idx) mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeNull() @@ -373,7 +390,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { mapHeadCode.key.set(mlen, iter) mapHeadCode.value.set(iter) key := mapiterkey(iter) - code.next.ptr = uintptr(key) + store(ctxptr, code.next.idx, uintptr(key)) code = code.next } else { e.encodeByte('}') @@ -381,7 +398,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } case opMapHeadLoad: - ptr := code.ptr + ptr := load(ctxptr, code.idx) mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeNull() @@ -396,7 +413,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { mapHeadCode.key.set(mlen, iter) mapHeadCode.value.set(iter) key := mapiterkey(iter) - code.next.ptr = uintptr(key) + store(ctxptr, code.next.idx, uintptr(key)) code = code.next } else { e.encodeByte('}') @@ -409,7 +426,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { if c.idx < c.len { e.encodeByte(',') key := mapiterkey(c.iter) - c.next.ptr = uintptr(key) + store(ctxptr, c.next.idx, uintptr(key)) code = c.next } else { e.encodeByte('}') @@ -419,11 +436,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(':') c := code.toMapValueCode() value := mapitervalue(c.iter) - c.next.ptr = uintptr(value) + store(ctxptr, c.next.idx, uintptr(value)) mapiternext(c.iter) code = c.next case opMapHeadIndent: - ptr := code.ptr + ptr := load(ctxptr, code.idx) mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) @@ -437,7 +454,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { mapHeadCode.key.set(mlen, iter) mapHeadCode.value.set(iter) key := mapiterkey(iter) - code.next.ptr = uintptr(key) + store(ctxptr, code.next.idx, uintptr(key)) code = code.next e.encodeIndent(code.indent) } else { @@ -447,7 +464,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } case opMapHeadLoadIndent: - ptr := code.ptr + ptr := load(ctxptr, code.idx) mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) @@ -463,7 +480,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { mapHeadCode.key.set(mlen, iter) mapHeadCode.value.set(iter) key := mapiterkey(iter) - code.next.ptr = uintptr(key) + store(ctxptr, code.next.idx, uintptr(key)) code = code.next e.encodeIndent(code.indent) } else { @@ -473,7 +490,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } case opRootMapHeadIndent: - ptr := code.ptr + ptr := load(ctxptr, code.idx) mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) @@ -487,7 +504,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { mapHeadCode.key.set(mlen, iter) mapHeadCode.value.set(iter) key := mapiterkey(iter) - code.next.ptr = uintptr(key) + store(ctxptr, code.next.idx, uintptr(key)) code = code.next e.encodeIndent(code.indent) } else { @@ -503,7 +520,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent) key := mapiterkey(c.iter) - c.next.ptr = uintptr(key) + store(ctxptr, c.next.idx, uintptr(key)) code = c.next } else { e.encodeByte('\n') @@ -518,7 +535,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent) key := mapiterkey(c.iter) - c.next.ptr = uintptr(key) + store(ctxptr, c.next.idx, uintptr(key)) code = c.next } else { e.encodeByte('\n') @@ -530,34 +547,42 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes([]byte{':', ' '}) c := code.toMapValueCode() value := mapitervalue(c.iter) - c.next.ptr = uintptr(value) + store(ctxptr, c.next.idx, uintptr(value)) mapiternext(c.iter) code = c.next case opStructFieldRecursive: recursive := code.toRecursiveCode() - if recursive.seenPtr != 0 && recursive.seenPtr == recursive.ptr { + ptr := load(ctxptr, code.idx) + if recursive.seenPtr != 0 && recursive.seenPtr == ptr { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(recursive.ptr), + ptr: unsafe.Pointer(ptr), })) return &UnsupportedValueError{ Value: reflect.ValueOf(v), Str: fmt.Sprintf("encountered a cycle via %s", code.typ), } } - recursive.seenPtr = recursive.ptr - if err := e.run(nil, newRecursiveCode(recursive)); err != nil { + recursive.seenPtr = ptr + recursiveCode := newRecursiveCode(recursive) + ctx := &encodeRuntimeContext{ + ptrs: make([]uintptr, recursiveCode.length()), + seenPtr: seenPtr, + } + ctx.init(ptr) + if err := e.run(ctx, recursiveCode); err != nil { return err } code = recursive.next case opStructFieldPtrHead: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHead: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHead { e.encodeNull() @@ -571,25 +596,25 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) } code = field.next - code.ptr = ptr + field.offset - field.nextField.ptr = ptr + store(ctxptr, code.idx, ptr+field.offset) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldAnonymousHead: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { code = field.next - code.ptr = ptr - field.nextField.ptr = ptr + store(ctxptr, code.idx, ptr) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadInt: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt { e.encodeNull() @@ -601,29 +626,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeInt(e.ptrToInt(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadInt: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeInt(e.ptrToInt(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt8: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt8 { e.encodeNull() @@ -635,29 +660,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeInt8(e.ptrToInt8(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadInt8: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeInt8(e.ptrToInt8(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt16: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt16 { e.encodeNull() @@ -669,29 +694,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeInt16(e.ptrToInt16(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadInt16: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeInt16(e.ptrToInt16(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt32 { e.encodeNull() @@ -703,29 +728,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeInt32(e.ptrToInt32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadInt32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeInt32(e.ptrToInt32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt64 { e.encodeNull() @@ -737,29 +762,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeInt64(e.ptrToInt64(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadInt64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeInt64(e.ptrToInt64(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint { e.encodeNull() @@ -771,29 +796,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeUint(e.ptrToUint(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadUint: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeUint(e.ptrToUint(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint8: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint8 { e.encodeNull() @@ -805,29 +830,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeUint8(e.ptrToUint8(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadUint8: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, field.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeUint8(e.ptrToUint8(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint16: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint16 { e.encodeNull() @@ -839,29 +864,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeUint16(e.ptrToUint16(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadUint16: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeUint16(e.ptrToUint16(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint32 { e.encodeNull() @@ -873,29 +898,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeUint32(e.ptrToUint32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadUint32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeUint32(e.ptrToUint32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint64 { e.encodeNull() @@ -907,29 +932,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeUint64(e.ptrToUint64(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadUint64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeUint64(e.ptrToUint64(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadFloat32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadFloat32 { e.encodeNull() @@ -941,29 +966,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeFloat32(e.ptrToFloat32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadFloat32: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeFloat32(e.ptrToFloat32(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadFloat64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadFloat64 { e.encodeNull() @@ -982,15 +1007,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeFloat64(v) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadFloat64: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { @@ -1003,15 +1028,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeBytes(field.key) e.encodeFloat64(v) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadString: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadString { e.encodeNull() @@ -1023,29 +1048,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeString(e.ptrToString(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadString: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeString(e.ptrToString(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadBool: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadBool { e.encodeNull() @@ -1057,29 +1082,29 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('{') e.encodeBytes(field.key) e.encodeBool(e.ptrToBool(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadBool: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) e.encodeBool(e.ptrToBool(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadBytes: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadBytes { e.encodeNull() @@ -1094,32 +1119,32 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadBytes: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { e.encodeBytes(field.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(code.ptr + field.offset)) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + field.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadArray: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadArray: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + c.offset if ptr == 0 { if code.op == opStructFieldPtrHeadArray { e.encodeNull() @@ -1133,30 +1158,31 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) } code = c.next - code.ptr = ptr - c.nextField.ptr = ptr + store(ctxptr, code.idx, ptr) + store(ctxptr, c.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadArray: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadArray: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, code.idx) + c.offset if ptr == 0 { code = c.end } else { e.encodeBytes(c.key) - code.ptr = ptr - c.nextField.ptr = ptr + store(ctxptr, code.idx, ptr) + store(ctxptr, c.nextField.idx, ptr) code = c.next } case opStructFieldPtrHeadSlice: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadSlice: c := code.toStructFieldCode() - ptr := c.ptr + c.offset - if ptr == 0 { + ptr := load(ctxptr, code.idx) + p := ptr + c.offset + if p == 0 { if code.op == opStructFieldPtrHeadSlice { e.encodeNull() } else { @@ -1169,29 +1195,30 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) } code = c.next - code.ptr = ptr - c.nextField.ptr = ptr + store(ctxptr, code.idx, p) + store(ctxptr, c.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadSlice: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadSlice: c := code.toStructFieldCode() - ptr := c.ptr + c.offset - if ptr == 0 { + ptr := load(ctxptr, code.idx) + p := ptr + c.offset + if p == 0 { code = c.end } else { e.encodeBytes(c.key) - code.ptr = ptr - c.nextField.ptr = ptr + store(ctxptr, code.idx, p) + store(ctxptr, c.nextField.idx, ptr) code = c.next } case opStructFieldPtrHeadMarshalJSON: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end @@ -1226,15 +1253,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { return err } e.encodeBytes(buf.Bytes()) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadMarshalJSON: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { @@ -1267,15 +1294,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { return err } e.encodeBytes(buf.Bytes()) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadMarshalText: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end @@ -1300,15 +1327,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrAnonymousHeadMarshalText: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end } else { @@ -1331,17 +1358,18 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1351,8 +1379,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) code = field.next - code.ptr = ptr - field.nextField.ptr = ptr + store(ctxptr, code.idx, ptr) + store(ctxptr, field.nextField.idx, ptr) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1360,15 +1388,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') code = field.next - code.ptr = ptr - field.nextField.ptr = ptr + store(ctxptr, code.idx, ptr) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadIntIndent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadIntIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadIntIndent { e.encodeIndent(code.indent) @@ -1383,15 +1411,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeInt(e.ptrToInt(ptr + field.offset)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt8Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1403,15 +1431,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeInt8(e.ptrToInt8(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt16Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end @@ -1422,15 +1450,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeInt16(e.ptrToInt16(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt32Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1442,15 +1470,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeInt32(e.ptrToInt32(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadInt64Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1462,15 +1490,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeInt64(e.ptrToInt64(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUintIndent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUintIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1482,15 +1510,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeUint(e.ptrToUint(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint8Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1502,15 +1530,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeUint8(e.ptrToUint8(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint16Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1522,15 +1550,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeUint16(e.ptrToUint16(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint32Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1542,15 +1570,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeUint32(e.ptrToUint32(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadUint64Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1562,15 +1590,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeUint64(e.ptrToUint64(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadFloat32Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1582,15 +1610,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeFloat32(e.ptrToFloat32(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadFloat64Indent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1609,15 +1637,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeFloat64(v) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadStringIndent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadStringIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1629,15 +1657,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeString(e.ptrToString(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadBoolIndent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBoolIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1649,15 +1677,15 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') e.encodeBool(e.ptrToBool(ptr)) - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadBytesIndent: - code.ptr = e.ptrToPtr(code.ptr) + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBytesIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -1672,17 +1700,18 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) code = field.next } case opStructFieldPtrHeadOmitEmpty: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmpty: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1694,18 +1723,19 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes(field.key) code = field.next - code.ptr = p + store(ctxptr, code.idx, p) } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmpty: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmpty: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1715,18 +1745,19 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes(field.key) code = field.next - code.ptr = p + store(ctxptr, code.idx, p) } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1740,16 +1771,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1761,16 +1793,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1784,16 +1817,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt8(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1805,16 +1839,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt8(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1828,16 +1863,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt16(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1849,16 +1885,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt16(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1872,16 +1909,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt32(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1893,16 +1931,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt32(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1916,16 +1955,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt64(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1937,16 +1977,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt64(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -1960,16 +2001,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -1981,16 +2023,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2004,16 +2047,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint8(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2025,16 +2069,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint8(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2048,16 +2093,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint16(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2069,16 +2115,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint16(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2092,16 +2139,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint32(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2113,16 +2161,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint32(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2136,16 +2185,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint64(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2157,16 +2207,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint64(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2180,16 +2231,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat32(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyFloat32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2201,16 +2253,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat32(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2230,16 +2283,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyFloat64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2257,16 +2311,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyString: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2280,16 +2335,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyString: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2301,16 +2357,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBool: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2324,16 +2381,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBool(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyBool: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2345,16 +2403,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBool(v) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBytes: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2371,16 +2430,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyBytes: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2395,16 +2455,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyMarshalJSON: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2441,16 +2502,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = field.next } } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSON: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2485,16 +2547,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = field.next } } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyMarshalText: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -2517,16 +2580,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyMarshalText: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadOmitEmptyMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -2547,16 +2611,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2572,18 +2637,19 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') code = field.next - code.ptr = p + store(ctxptr, code.idx, p) } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyIntIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyIntIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2601,16 +2667,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt8Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2628,16 +2695,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt8(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt16Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2655,16 +2723,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt16(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2682,16 +2751,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt32(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyInt64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2709,16 +2779,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt64(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUintIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUintIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2736,16 +2807,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint8Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2763,16 +2835,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint8(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint16Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2790,16 +2863,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint16(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2817,16 +2891,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint32(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyUint64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2844,16 +2919,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint64(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyFloat32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2871,16 +2947,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat32(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyFloat64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2904,16 +2981,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyStringIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyStringIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2931,16 +3009,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBoolIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyBoolIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2958,16 +3037,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBool(v) code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBytesIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadOmitEmptyBytesIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -2988,16 +3068,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') code = field.next } - field.nextField.ptr = field.ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTag: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTag: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3006,33 +3087,35 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { p := ptr + field.offset e.encodeBytes(field.key) code = field.next - code.ptr = p - field.nextField.ptr = ptr + store(ctxptr, code.idx, p) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTag: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTag: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) code = field.next - code.ptr = ptr + field.offset - field.nextField.ptr = ptr + store(ctxptr, code.idx, ptr+field.offset) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3041,32 +3124,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagInt: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagInt: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3075,32 +3160,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagInt8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagInt8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3109,32 +3196,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagInt16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagInt16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3143,32 +3232,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagInt32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagInt32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3177,32 +3268,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagInt64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagInt64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3211,32 +3304,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagUint: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagUint: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3245,32 +3340,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagUint8: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagUint8: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3279,32 +3376,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagUint16: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagUint16: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3313,32 +3412,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagUint32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagUint32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3347,32 +3448,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagUint64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagUint64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagFloat32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3381,32 +3484,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagFloat32: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagFloat32: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagFloat64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3422,16 +3527,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(v)) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagFloat64: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagFloat64: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -3445,16 +3551,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(v)) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagString: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3463,32 +3570,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagString: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagString: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagBool: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3497,32 +3606,34 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagBool: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagBool: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { e.encodeBytes(field.key) e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagBytes: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3536,16 +3647,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagBytes: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagBytes: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -3557,16 +3669,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagMarshalJSON: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3600,16 +3713,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(buf.String()) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagMarshalJSON: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagMarshalJSON: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -3642,16 +3756,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(buf.String()) code = field.next } - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagMarshalText: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() code = field.end.next @@ -3669,16 +3784,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagMarshalText: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldAnonymousHeadStringTagMarshalText: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { code = field.end.next } else { @@ -3694,16 +3810,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3715,17 +3832,18 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(field.key) e.encodeByte(' ') code = field.next - code.ptr = p - field.nextField.ptr = field.ptr + store(ctxptr, code.idx, p) + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagIntIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagIntIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3737,16 +3855,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt8Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3758,16 +3877,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt16Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3779,16 +3899,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3800,16 +3921,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagInt64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagInt64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3821,16 +3943,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUintIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUintIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3842,16 +3965,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint8Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint8Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3863,16 +3987,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint16Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint16Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3884,16 +4009,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3905,16 +4031,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagUint64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagUint64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3926,16 +4053,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagFloat32Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagFloat32Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3947,16 +4075,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagFloat64Indent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagFloat64Indent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3975,16 +4104,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(v)) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagStringIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagStringIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -3996,16 +4126,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagBoolIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagBoolIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -4017,16 +4148,17 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagBytesIndent: - if code.ptr != 0 { - code.ptr = e.ptrToPtr(code.ptr) + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) } fallthrough case opStructFieldHeadStringTagBytesIndent: field := code.toStructFieldCode() - ptr := field.ptr + ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() @@ -4043,7 +4175,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = field.next - field.nextField.ptr = ptr + store(ctxptr, field.nextField.idx, ptr) } case opStructField: if e.buf[len(e.buf)-1] != '{' { @@ -4054,115 +4186,128 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) } code = code.next - code.ptr = c.ptr + c.offset - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, code.idx, ptr+c.offset) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeInt(e.ptrToInt(c.ptr + c.offset)) + e.encodeInt(e.ptrToInt(ptr + c.offset)) code = code.next case opStructFieldInt8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeInt8(e.ptrToInt8(c.ptr + c.offset)) + e.encodeInt8(e.ptrToInt8(ptr + c.offset)) code = code.next case opStructFieldInt16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeInt16(e.ptrToInt16(c.ptr + c.offset)) + e.encodeInt16(e.ptrToInt16(ptr + c.offset)) code = code.next case opStructFieldInt32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeInt32(e.ptrToInt32(c.ptr + c.offset)) + e.encodeInt32(e.ptrToInt32(ptr + c.offset)) code = code.next case opStructFieldInt64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeInt64(e.ptrToInt64(c.ptr + c.offset)) + e.encodeInt64(e.ptrToInt64(ptr + c.offset)) code = code.next case opStructFieldUint: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeUint(e.ptrToUint(c.ptr + c.offset)) + e.encodeUint(e.ptrToUint(ptr + c.offset)) code = code.next case opStructFieldUint8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeUint8(e.ptrToUint8(c.ptr + c.offset)) + e.encodeUint8(e.ptrToUint8(ptr + c.offset)) code = code.next case opStructFieldUint16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeUint16(e.ptrToUint16(c.ptr + c.offset)) + e.encodeUint16(e.ptrToUint16(ptr + c.offset)) code = code.next case opStructFieldUint32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeUint32(e.ptrToUint32(c.ptr + c.offset)) + e.encodeUint32(e.ptrToUint32(ptr + c.offset)) code = code.next case opStructFieldUint64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeUint64(e.ptrToUint64(c.ptr + c.offset)) + e.encodeUint64(e.ptrToUint64(ptr + c.offset)) code = code.next case opStructFieldFloat32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeFloat32(e.ptrToFloat32(c.ptr + c.offset)) + e.encodeFloat32(e.ptrToFloat32(ptr + c.offset)) code = code.next case opStructFieldFloat64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - v := e.ptrToFloat64(c.ptr + c.offset) + v := e.ptrToFloat64(ptr + c.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -4176,27 +4321,30 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeString(e.ptrToString(c.ptr + c.offset)) + e.encodeString(e.ptrToString(ptr + c.offset)) code = code.next case opStructFieldBool: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - e.encodeBool(e.ptrToBool(c.ptr + c.offset)) + e.encodeBool(e.ptrToBool(ptr + c.offset)) code = code.next case opStructFieldBytes: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(c.ptr + c.offset)) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + c.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') @@ -4206,12 +4354,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - ptr := c.ptr + c.offset + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) b, err := v.(Marshaler).MarshalJSON() if err != nil { @@ -4231,12 +4380,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) e.encodeBytes(c.key) - ptr := c.ptr + c.offset + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -4252,46 +4402,51 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) code = code.next - code.ptr = c.ptr + c.offset + store(ctxptr, code.idx, ptr+c.offset) e.encodeBytes(c.key) case opStructFieldSlice: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, c.nextField.idx, ptr) code = code.next - code.ptr = c.ptr + c.offset + store(ctxptr, code.idx, ptr+c.offset) e.encodeBytes(c.key) case opStructFieldMap: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) e.encodeBytes(c.key) code = code.next - code.ptr = c.ptr + c.offset - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, ptr+c.offset) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldMapLoad: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) e.encodeBytes(c.key) code = code.next - code.ptr = c.ptr + c.offset - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, ptr+c.offset) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStruct: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) e.encodeBytes(c.key) code = code.next - code.ptr = c.ptr + c.offset - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, ptr+c.offset) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4301,8 +4456,9 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) e.encodeByte(' ') code = code.next - code.ptr = c.ptr + c.offset - c.nextField.ptr = c.ptr + ptr := load(ctxptr, c.idx) + store(ctxptr, code.idx, ptr+c.offset) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldIntIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4311,9 +4467,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeInt(e.ptrToInt(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeInt(e.ptrToInt(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt8Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4322,9 +4479,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeInt8(e.ptrToInt8(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeInt8(e.ptrToInt8(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt16Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4333,9 +4491,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeInt16(e.ptrToInt16(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeInt16(e.ptrToInt16(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt32Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4344,9 +4503,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeInt32(e.ptrToInt32(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeInt32(e.ptrToInt32(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt64Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4355,9 +4515,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeInt64(e.ptrToInt64(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeInt64(e.ptrToInt64(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldUintIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4366,9 +4527,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeUint(e.ptrToUint(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeUint(e.ptrToUint(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint8Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4377,9 +4539,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeUint8(e.ptrToUint8(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeUint8(e.ptrToUint8(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint16Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4388,9 +4551,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeUint16(e.ptrToUint16(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeUint16(e.ptrToUint16(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint32Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4399,9 +4563,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeUint32(e.ptrToUint32(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeUint32(e.ptrToUint32(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint64Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4410,9 +4575,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeUint64(e.ptrToUint64(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeUint64(e.ptrToUint64(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldFloat32Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4421,9 +4587,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeFloat32(e.ptrToFloat32(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeFloat32(e.ptrToFloat32(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldFloat64Indent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4432,7 +4599,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - v := e.ptrToFloat64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat64(ptr + c.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -4441,7 +4609,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeFloat64(v) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4450,9 +4618,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(e.ptrToString(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeString(e.ptrToString(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldBoolIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4461,9 +4630,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeBool(e.ptrToBool(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + e.encodeBool(e.ptrToBool(ptr + c.offset)) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldBytesIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4472,12 +4642,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(c.ptr + c.offset)) + ptr := load(ctxptr, c.idx) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + c.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldMarshalJSONIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4486,10 +4657,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) b, err := v.(Marshaler).MarshalJSON() if err != nil { @@ -4504,7 +4676,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeBytes(buf.Bytes()) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldArrayIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4513,7 +4685,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { e.encodeNull() @@ -4521,7 +4694,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } else { code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldSliceIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4530,7 +4703,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { e.encodeNull() @@ -4538,7 +4712,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } else { code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldMapIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4547,7 +4721,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { e.encodeNull() code = c.nextField @@ -4562,7 +4737,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldMapLoadIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4571,7 +4746,8 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { e.encodeNull() code = c.nextField @@ -4585,13 +4761,14 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStructIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') @@ -4606,13 +4783,14 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = c.nextField } else { code = code.next - code.ptr = p + store(ctxptr, code.idx, p) } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmpty: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { code = c.nextField } else { @@ -4621,12 +4799,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeBytes(c.key) code = code.next - code.ptr = p + store(ctxptr, code.idx, p) } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyInt: c := code.toStructFieldCode() - v := e.ptrToInt(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4635,10 +4814,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt8: c := code.toStructFieldCode() - v := e.ptrToInt8(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt8(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4647,10 +4827,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt8(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt16: c := code.toStructFieldCode() - v := e.ptrToInt16(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt16(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4659,10 +4840,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt16(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt32: c := code.toStructFieldCode() - v := e.ptrToInt32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4671,10 +4853,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt64: c := code.toStructFieldCode() - v := e.ptrToInt64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt64(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4683,10 +4866,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint: c := code.toStructFieldCode() - v := e.ptrToUint(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4695,10 +4879,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint8: c := code.toStructFieldCode() - v := e.ptrToUint8(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint8(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4707,10 +4892,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint8(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint16: c := code.toStructFieldCode() - v := e.ptrToUint16(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint16(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4719,10 +4905,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint16(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint32: c := code.toStructFieldCode() - v := e.ptrToUint32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4731,10 +4918,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint64: c := code.toStructFieldCode() - v := e.ptrToUint64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint64(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4743,10 +4931,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat32: c := code.toStructFieldCode() - v := e.ptrToFloat32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4755,10 +4944,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat64: c := code.toStructFieldCode() - v := e.ptrToFloat64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat64(ptr + c.offset) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -4773,10 +4963,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyString: c := code.toStructFieldCode() - v := e.ptrToString(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToString(ptr + c.offset) if v != "" { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4785,10 +4976,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBool: c := code.toStructFieldCode() - v := e.ptrToBool(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToBool(ptr + c.offset) if v { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4797,10 +4989,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBool(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBytes: c := code.toStructFieldCode() - v := e.ptrToBytes(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToBytes(ptr + c.offset) if len(v) > 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4812,13 +5005,14 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyMarshalJSON: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) if v != nil { b, err := v.(Marshaler).MarshalJSON() @@ -4835,18 +5029,19 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(buf.Bytes()) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyMarshalText: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) if v != nil { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -4858,10 +5053,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(*(*string)(unsafe.Pointer(&bytes))) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyArray: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { code = c.nextField @@ -4871,10 +5067,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptySlice: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { code = c.nextField @@ -4884,10 +5081,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMap: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { code = c.nextField } else { @@ -4901,10 +5099,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapLoad: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { code = c.nextField } else { @@ -4919,10 +5118,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { code = c.nextField } else { @@ -4933,12 +5133,13 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) e.encodeByte(' ') code = code.next - code.ptr = p + store(ctxptr, code.idx, p) } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyIntIndent: c := code.toStructFieldCode() - v := e.ptrToInt(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4949,10 +5150,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt8Indent: c := code.toStructFieldCode() - v := e.ptrToInt8(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt8(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4963,10 +5165,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt8(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt16Indent: c := code.toStructFieldCode() - v := e.ptrToInt16(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt16(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4977,10 +5180,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt16(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt32Indent: c := code.toStructFieldCode() - v := e.ptrToInt32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4991,10 +5195,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt64Indent: c := code.toStructFieldCode() - v := e.ptrToInt64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToInt64(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5005,10 +5210,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeInt64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUintIndent: c := code.toStructFieldCode() - v := e.ptrToUint(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5019,10 +5225,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint8Indent: c := code.toStructFieldCode() - v := e.ptrToUint8(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint8(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5033,10 +5240,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint8(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint16Indent: c := code.toStructFieldCode() - v := e.ptrToUint16(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint16(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5047,10 +5255,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint16(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint32Indent: c := code.toStructFieldCode() - v := e.ptrToUint32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5061,10 +5270,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint64Indent: c := code.toStructFieldCode() - v := e.ptrToUint64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToUint64(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5075,10 +5285,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeUint64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat32Indent: c := code.toStructFieldCode() - v := e.ptrToFloat32(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat32(ptr + c.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5089,10 +5300,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat32(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat64Indent: c := code.toStructFieldCode() - v := e.ptrToFloat64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat64(ptr + c.offset) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -5109,10 +5321,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeFloat64(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyStringIndent: c := code.toStructFieldCode() - v := e.ptrToString(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToString(ptr + c.offset) if v != "" { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5123,10 +5336,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeString(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBoolIndent: c := code.toStructFieldCode() - v := e.ptrToBool(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToBool(ptr + c.offset) if v { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5137,10 +5351,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBool(v) } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBytesIndent: c := code.toStructFieldCode() - v := e.ptrToBytes(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToBytes(ptr + c.offset) if len(v) > 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -5154,10 +5369,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte('"') } code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyArrayIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { code = c.nextField @@ -5170,10 +5386,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptySliceIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { code = c.nextField @@ -5186,10 +5403,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') code = code.next } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { code = c.nextField } else { @@ -5206,10 +5424,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapLoadIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { code = c.nextField } else { @@ -5227,10 +5446,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = code.next } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyStructIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if p == 0 { code = c.nextField } else { @@ -5247,122 +5467,135 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { code = c.nextField } else { code = code.next - code.ptr = p + store(ctxptr, code.idx, p) } } - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTag: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) code = code.next - code.ptr = p - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, p) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTagInt: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt8: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt8(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt16: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt16(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt32: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt64: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt64(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint8: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint8(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint16: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint16(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint32: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint64: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint64(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat32: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToFloat32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat64: c := code.toStructFieldCode() - v := e.ptrToFloat64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat64(ptr + c.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -5375,28 +5608,31 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) e.encodeString(fmt.Sprint(v)) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagString: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(strconv.Quote(e.ptrToString(c.ptr + c.offset))) + e.encodeString(strconv.Quote(e.ptrToString(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagBool: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToBool(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagBytes: c := code.toStructFieldCode() - v := e.ptrToBytes(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToBytes(ptr + c.offset) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } @@ -5406,13 +5642,14 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalJSON: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) b, err := v.(Marshaler).MarshalJSON() if err != nil { @@ -5427,13 +5664,14 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeString(buf.String()) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalText: c := code.toStructFieldCode() - ptr := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -5444,10 +5682,11 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagIndent: c := code.toStructFieldCode() - p := c.ptr + c.offset + ptr := load(ctxptr, c.idx) + p := ptr + c.offset if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } @@ -5455,132 +5694,144 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) e.encodeByte(' ') code = code.next - code.ptr = p - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, p) + store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTagIntIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt8Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt8(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt16Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt16(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt32Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt64Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt64(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUintIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint8Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint8(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint16Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint16(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint32Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint64Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint64(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat32Indent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToFloat32(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat64Indent: c := code.toStructFieldCode() - v := e.ptrToFloat64(c.ptr + c.offset) + ptr := load(ctxptr, c.idx) + v := e.ptrToFloat64(ptr + c.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -5595,9 +5846,10 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') e.encodeString(fmt.Sprint(v)) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagStringIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } @@ -5606,24 +5858,26 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeByte(' ') var b bytes.Buffer enc := NewEncoder(&b) - enc.encodeString(e.ptrToString(c.ptr + c.offset)) + enc.encodeString(e.ptrToString(ptr + c.offset)) e.encodeString(string(enc.buf)) enc.release() code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagBoolIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToBool(c.ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + c.offset))) code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagBytesIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } @@ -5631,25 +5885,26 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { e.encodeBytes(c.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(c.ptr + c.offset), + e.ptrToBytes(ptr + c.offset), ) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - code.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalJSONIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - ptr := c.ptr + c.offset + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) b, err := v.(Marshaler).MarshalJSON() if err != nil { @@ -5664,19 +5919,20 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeString(buf.String()) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalTextIndent: c := code.toStructFieldCode() + ptr := load(ctxptr, c.idx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } e.encodeIndent(c.indent) e.encodeBytes(c.key) e.encodeByte(' ') - ptr := c.ptr + c.offset + p := ptr + c.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr), + ptr: unsafe.Pointer(p), })) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -5687,7 +5943,7 @@ func (e *Encoder) run(ctx encodeRuntimeContext, code *opcode) error { } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next - c.nextField.ptr = c.ptr + store(ctxptr, c.nextField.idx, ptr) case opStructEnd: e.encodeByte('}') code = code.next From 572d4842a5ceda940d733181034688dfa0ffca4a Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 31 Aug 2020 00:14:32 +0900 Subject: [PATCH 06/18] Reset seenPtr --- encode.go | 2 ++ encode_context.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/encode.go b/encode.go index 1fff880..eb2f1e3 100644 --- a/encode.go +++ b/encode.go @@ -164,6 +164,7 @@ func (e *Encoder) encode(v interface{}) error { } ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) + ctx.reset() ctx.init(p) err := e.run(ctx, code) if e.enabledIndent { @@ -218,6 +219,7 @@ func (e *Encoder) encode(v interface{}) error { cachedOpcode.set(typeptr, codeSet) p := uintptr(header.ptr) ctx := codeSet.ctx.Get().(*encodeRuntimeContext) + ctx.reset() ctx.init(p) if e.enabledIndent { err := e.run(ctx, codeIndent) diff --git a/encode_context.go b/encode_context.go index da3d233..0c7ee1b 100644 --- a/encode_context.go +++ b/encode_context.go @@ -63,6 +63,10 @@ type encodeRuntimeContext struct { seenPtr map[uintptr]struct{} } +func (c *encodeRuntimeContext) reset() { + c.seenPtr = map[uintptr]struct{}{} +} + func (c *encodeRuntimeContext) init(p uintptr) { c.ptrs[0] = p } From a6276c4d8ef0c87ee607392177a1040a86217886 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 31 Aug 2020 03:14:37 +0900 Subject: [PATCH 07/18] Optimize opcode.idx and seenPtr --- encode.go | 22 ++++++----- encode_compile.go | 51 ++++++++++++++----------- encode_context.go | 7 +--- encode_opcode.go | 97 ++++++++++++++++++++++++++--------------------- encode_vm.go | 21 +++++----- 5 files changed, 104 insertions(+), 94 deletions(-) diff --git a/encode.go b/encode.go index eb2f1e3..556bd57 100644 --- a/encode.go +++ b/encode.go @@ -164,9 +164,9 @@ func (e *Encoder) encode(v interface{}) error { } ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) - ctx.reset() ctx.init(p) - err := e.run(ctx, code) + seenPtr := map[uintptr]struct{}{} + err := e.run(ctx, seenPtr, code) if e.enabledIndent { codeSet.codeIndent.Put(code) } else { @@ -210,8 +210,7 @@ func (e *Encoder) encode(v interface{}) error { ctx: sync.Pool{ New: func() interface{} { return &encodeRuntimeContext{ - ptrs: make([]uintptr, codeLength), - seenPtr: map[uintptr]struct{}{}, + ptrs: make([]uintptr, codeLength), } }, }, @@ -219,19 +218,22 @@ func (e *Encoder) encode(v interface{}) error { cachedOpcode.set(typeptr, codeSet) p := uintptr(header.ptr) ctx := codeSet.ctx.Get().(*encodeRuntimeContext) - ctx.reset() ctx.init(p) + + var c *opcode if e.enabledIndent { - err := e.run(ctx, codeIndent) - codeSet.ctx.Put(ctx) - return err + c = codeIndent + } else { + c = code } - if err := e.run(ctx, code); err != nil { + + seenPtr := map[uintptr]struct{}{} + if err := e.run(ctx, seenPtr, c); err != nil { codeSet.ctx.Put(ctx) return err } codeSet.ctx.Put(ctx) - return err + return nil } func (e *Encoder) encodeInt(v int) { diff --git a/encode_compile.go b/encode_compile.go index c2e6ed7..eb98048 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -267,11 +267,12 @@ func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { code := (*opcode)(unsafe.Pointer(&interfaceCode{ opcodeHeader: &opcodeHeader{ - op: opInterface, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, - next: newEndOp(ctx), + op: opInterface, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: newEndOp(ctx), }, root: ctx.root, })) @@ -588,11 +589,12 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { c := (*opcode)(unsafe.Pointer(&recursiveCode{ opcodeHeader: &opcodeHeader{ - op: opStructFieldRecursive, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, - next: newEndOp(ctx), + op: opStructFieldRecursive, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: newEndOp(ctx), }, jmp: code, })) @@ -726,7 +728,7 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { if codeType == codeStructField { if e.isNotExistsField(code.next.toStructFieldCode()) { code.next = code.nextField - diff := code.next.idx - code.idx + diff := code.next.displayIdx - code.displayIdx for i := 0; i < diff; i++ { code.next.decOpcodeIndex() } @@ -763,7 +765,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value } else if f.op == opStructEnd { f.op = opStructAnonymousEnd } else if existsKey { - diff := f.nextField.idx - f.idx + diff := f.nextField.displayIdx - f.displayIdx for i := 0; i < diff; i++ { f.nextField.decOpcodeIndex() } @@ -814,7 +816,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { - diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() } @@ -831,7 +833,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { - diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() } @@ -919,10 +921,11 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, key := fmt.Sprintf(`"%s":`, tag.key) fieldCode := &structFieldCode{ opcodeHeader: &opcodeHeader{ - typ: valueCode.typ, - idx: fieldOpcodeIndex, - next: valueCode, - indent: ctx.indent, + typ: valueCode.typ, + displayIdx: fieldOpcodeIndex, + idx: uintptr(fieldOpcodeIndex) * 8, + next: valueCode, + indent: ctx.indent, }, anonymousKey: field.Anonymous, key: []byte(key), @@ -958,10 +961,11 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, if head == nil { head = &structFieldCode{ opcodeHeader: &opcodeHeader{ - op: opStructFieldHead, - typ: typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opStructFieldHead, + typ: typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, nextField: structEndCode, } @@ -972,7 +976,8 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, code = (*opcode)(unsafe.Pointer(head)) } - structEndCode.idx = ctx.opcodeIndex + structEndCode.displayIdx = ctx.opcodeIndex + structEndCode.idx = uintptr(ctx.opcodeIndex) * 8 ctx.incOpcodeIndex() if ctx.withIndent { diff --git a/encode_context.go b/encode_context.go index 0c7ee1b..ec30d68 100644 --- a/encode_context.go +++ b/encode_context.go @@ -59,12 +59,7 @@ func (c *encodeCompileContext) decOpcodeIndex() { } type encodeRuntimeContext struct { - ptrs []uintptr - seenPtr map[uintptr]struct{} -} - -func (c *encodeRuntimeContext) reset() { - c.seenPtr = map[uintptr]struct{}{} + ptrs []uintptr } func (c *encodeRuntimeContext) init(p uintptr) { diff --git a/encode_opcode.go b/encode_opcode.go index 0b49ed0..7cc4ae9 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -13,20 +13,22 @@ func copyOpcode(code *opcode) *opcode { } type opcodeHeader struct { - op opType - typ *rtype - idx int - indent int - next *opcode + 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, - idx: h.idx, - indent: h.indent, - next: h.next.copy(codeMap), + op: h.op, + typ: h.typ, + displayIdx: h.displayIdx, + idx: h.idx, + indent: h.indent, + next: h.next.copy(codeMap), } } @@ -41,11 +43,12 @@ func newOpCode(ctx *encodeCompileContext, op opType) *opcode { 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, + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: next, }, } } @@ -79,7 +82,7 @@ func (c *opcode) beforeLastCode() *opcode { func (c *opcode) length() int { var idx int for code := c; code.op != opEnd; { - idx = code.idx + idx = code.displayIdx switch code.op.codeType() { case codeArrayElem: code = code.toArrayElemCode().end @@ -96,7 +99,8 @@ func (c *opcode) length() int { func (c *opcode) decOpcodeIndex() { for code := c; code.op != opEnd; { - code.idx-- + code.displayIdx-- + code.idx -= 8 switch code.op.codeType() { case codeArrayElem: code = code.toArrayElemCode().end @@ -153,22 +157,22 @@ func (c *opcode) dump() string { 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))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, 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))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, 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))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, 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))) + codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.displayIdx, 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))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) code = code.next } } @@ -224,9 +228,10 @@ type sliceHeaderCode struct { func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode { return &sliceHeaderCode{ opcodeHeader: &opcodeHeader{ - op: opSliceHead, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opSliceHead, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -234,9 +239,10 @@ func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode { func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *sliceElemCode { return &sliceElemCode{ opcodeHeader: &opcodeHeader{ - op: opSliceElem, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opSliceElem, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, size: size, } @@ -307,9 +313,10 @@ type arrayHeaderCode struct { func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode { return &arrayHeaderCode{ opcodeHeader: &opcodeHeader{ - op: opArrayHead, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opArrayHead, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, len: uintptr(alen), } @@ -318,8 +325,9 @@ func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode { func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *arrayElemCode { return &arrayElemCode{ opcodeHeader: &opcodeHeader{ - op: opArrayElem, - idx: ctx.opcodeIndex, + op: opArrayElem, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, }, len: uintptr(alen), size: size, @@ -536,10 +544,11 @@ func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode { } return &mapHeaderCode{ opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -547,9 +556,10 @@ func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode { func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { return &mapKeyCode{ opcodeHeader: &opcodeHeader{ - op: opMapKey, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opMapKey, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -557,9 +567,10 @@ func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { return &mapValueCode{ opcodeHeader: &opcodeHeader{ - op: opMapValue, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opMapValue, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } diff --git a/encode_vm.go b/encode_vm.go index bc02567..e873ae8 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -11,17 +11,16 @@ import ( "unsafe" ) -func load(base uintptr, idx int) uintptr { - return *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) +func load(base uintptr, idx uintptr) uintptr { + return *(*uintptr)(unsafe.Pointer(base + idx)) } -func store(base uintptr, idx int, p uintptr) { - *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) = p +func store(base uintptr, idx uintptr, p uintptr) { + *(*uintptr)(unsafe.Pointer(base + idx)) = p } -func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { +func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, code *opcode) error { ctxptr := ctx.ptr() - seenPtr := ctx.seenPtr for { switch code.op { case opPtr: @@ -143,11 +142,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { c = code } ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, c.length()), - seenPtr: seenPtr, + ptrs: make([]uintptr, c.length()), } ctx.init(uintptr(header.ptr)) - if err := e.run(ctx, c); err != nil { + if err := e.run(ctx, seenPtr, c); err != nil { return err } code = ifaceCode.next @@ -566,11 +564,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { recursive.seenPtr = ptr recursiveCode := newRecursiveCode(recursive) ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, recursiveCode.length()), - seenPtr: seenPtr, + ptrs: make([]uintptr, recursiveCode.length()), } ctx.init(ptr) - if err := e.run(ctx, recursiveCode); err != nil { + if err := e.run(ctx, seenPtr, recursiveCode); err != nil { return err } code = recursive.next From 72bc598dd4fecc2fa64e5fb71a8875931334f6c0 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 31 Aug 2020 21:59:22 +0900 Subject: [PATCH 08/18] Remove state variables from opcode --- encode.go | 6 +- encode_compile.go | 116 +- encode_context.go | 4 + encode_opcode.go | 671 +++------- encode_vm.go | 3132 +++++++++++++++++++-------------------------- 5 files changed, 1511 insertions(+), 2418 deletions(-) diff --git a/encode.go b/encode.go index 556bd57..e9f2c48 100644 --- a/encode.go +++ b/encode.go @@ -195,16 +195,16 @@ func (e *Encoder) encode(v interface{}) error { if err != nil { return err } - codeLength := code.length() + codeLength := code.totalLength() codeSet := &opcodeSet{ codeIndent: sync.Pool{ New: func() interface{} { - return copyOpcode(codeIndent) + return codeIndent }, }, code: sync.Pool{ New: func() interface{} { - return copyOpcode(code) + return code }, }, ctx: sync.Pool{ diff --git a/encode_compile.go b/encode_compile.go index eb98048..ff1124e 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -265,17 +265,7 @@ func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { } func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { - code := (*opcode)(unsafe.Pointer(&interfaceCode{ - opcodeHeader: &opcodeHeader{ - op: opInterface, - typ: ctx.typ, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - next: newEndOp(ctx), - }, - root: ctx.root, - })) + code := newInterfaceCode(ctx) ctx.incOpcodeIndex() return code, nil } @@ -406,8 +396,8 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, ctx = ctx.decIndent() - header.key = key - header.value = value + header.mapKey = key + header.mapValue = value end := newOpCode(ctx, opMapEnd) ctx.incOpcodeIndex() @@ -586,20 +576,10 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool return fieldType } -func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { - c := (*opcode)(unsafe.Pointer(&recursiveCode{ - opcodeHeader: &opcodeHeader{ - op: opStructFieldRecursive, - typ: ctx.typ, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - next: newEndOp(ctx), - }, - jmp: code, - })) +func (e *Encoder) recursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode { + code := newRecursiveCode(ctx, jmp) ctx.incOpcodeIndex() - return c + return code } func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { @@ -617,7 +597,7 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { 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-- op := e.optimizeStructHeader(valueCode.op, tag, ctx.withIndent) fieldCode.op = op @@ -654,7 +634,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *structField 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)) op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent) fieldCode.op = op @@ -691,7 +671,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *structFieldC return code } -func (e *Encoder) isNotExistsField(head *structFieldCode) bool { +func (e *Encoder) isNotExistsField(head *opcode) bool { if head == nil { return false } @@ -713,12 +693,12 @@ func (e *Encoder) isNotExistsField(head *structFieldCode) bool { if head.next.op.codeType() != codeStructField { 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 - var prev *structFieldCode + var prev *opcode for { if code.op == opStructEnd || code.op == opStructEndIndent { break @@ -726,7 +706,7 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { if code.op == opStructField || code.op == opStructFieldIndent { codeType := code.next.op.codeType() if codeType == codeStructField { - if e.isNotExistsField(code.next.toStructFieldCode()) { + if e.isNotExistsField(code.next) { code.next = code.nextField diff := code.next.displayIdx - code.displayIdx for i := 0; i < diff; i++ { @@ -738,21 +718,21 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { } } prev = code - code = code.nextField.toStructFieldCode() + code = code.nextField } } type structFieldPair struct { - prevField *structFieldCode - curField *structFieldCode + prevField *opcode + curField *opcode isTaggedKey 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{} f := valueCode - var prevAnonymousField *structFieldCode + var prevAnonymousField *opcode for { existsKey := tags.existsKey(f.displayKey) op := f.op.headToAnonymousHead() @@ -777,7 +757,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value break } prevAnonymousField = f - f = f.nextField.toStructFieldCode() + f = f.nextField continue } @@ -787,7 +767,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value isTaggedKey: f.isTaggedKey, }) 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...) } } @@ -795,7 +775,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value break } prevAnonymousField = f - f = f.nextField.toStructFieldCode() + f = f.nextField } return anonymousFields } @@ -869,9 +849,9 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, fieldNum := typ.NumField() fieldIdx := 0 var ( - head *structFieldCode + head *opcode code *opcode - prevField *structFieldCode + prevField *opcode ) ctx = ctx.incIndent() tags := structTags{} @@ -903,7 +883,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } 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...) } } @@ -919,14 +899,12 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } } key := fmt.Sprintf(`"%s":`, tag.key) - fieldCode := &structFieldCode{ - opcodeHeader: &opcodeHeader{ - typ: valueCode.typ, - displayIdx: fieldOpcodeIndex, - idx: uintptr(fieldOpcodeIndex) * 8, - next: valueCode, - indent: ctx.indent, - }, + fieldCode := &opcode{ + typ: valueCode.typ, + displayIdx: fieldOpcodeIndex, + idx: opcodeOffset(fieldOpcodeIndex), + next: valueCode, + indent: ctx.indent, anonymousKey: field.Anonymous, key: []byte(key), isTaggedKey: tag.isTaggedKey, @@ -948,36 +926,32 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } ctx = ctx.decIndent() - structEndCode := (*opcode)(unsafe.Pointer(&structFieldCode{ - opcodeHeader: &opcodeHeader{ - op: opStructEnd, - typ: nil, - indent: ctx.indent, - next: newEndOp(ctx), - }, - })) + structEndCode := &opcode{ + op: opStructEnd, + typ: nil, + indent: ctx.indent, + next: newEndOp(ctx), + } // no struct field if head == nil { - head = &structFieldCode{ - opcodeHeader: &opcodeHeader{ - op: opStructFieldHead, - typ: typ, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - }, - nextField: structEndCode, + head = &opcode{ + op: opStructFieldHead, + typ: typ, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, + nextField: structEndCode, } ctx.incOpcodeIndex() if ctx.withIndent { head.op = opStructFieldHeadIndent } - code = (*opcode)(unsafe.Pointer(head)) + code = head } structEndCode.displayIdx = ctx.opcodeIndex - structEndCode.idx = uintptr(ctx.opcodeIndex) * 8 + structEndCode.idx = opcodeOffset(ctx.opcodeIndex) ctx.incOpcodeIndex() if ctx.withIndent { diff --git a/encode_context.go b/encode_context.go index ec30d68..a36ddec 100644 --- a/encode_context.go +++ b/encode_context.go @@ -10,6 +10,7 @@ type encodeCompileContext struct { withIndent bool root bool opcodeIndex int + ptrIndex int indent int parent *encodeCompileContext @@ -21,6 +22,7 @@ func (c *encodeCompileContext) context() *encodeCompileContext { withIndent: c.withIndent, root: c.root, opcodeIndex: c.opcodeIndex, + ptrIndex: c.ptrIndex, indent: c.indent, parent: c, } @@ -46,6 +48,7 @@ func (c *encodeCompileContext) decIndent() *encodeCompileContext { func (c *encodeCompileContext) incOpcodeIndex() { c.opcodeIndex++ + c.ptrIndex++ if c.parent != nil { c.parent.incOpcodeIndex() } @@ -53,6 +56,7 @@ func (c *encodeCompileContext) incOpcodeIndex() { func (c *encodeCompileContext) decOpcodeIndex() { c.opcodeIndex-- + c.ptrIndex-- if c.parent != nil { c.parent.decOpcodeIndex() } diff --git a/encode_opcode.go b/encode_opcode.go index 7cc4ae9..bc1fe9f 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -2,54 +2,56 @@ 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 - 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), - } -} +var uintptrSize = unsafe.Sizeof(uintptr(0)) 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 { return newOpCodeWithNext(ctx, op, newEndOp(ctx)) } +func opcodeOffset(idx int) uintptr { + return uintptr(idx) * uintptrSize +} + func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { return &opcode{ - opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - next: next, - }, + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + indent: ctx.indent, + idx: opcodeOffset(ctx.opcodeIndex), + next: next, } } @@ -62,12 +64,8 @@ func (c *opcode) beforeLastCode() *opcode { 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 + case codeArrayElem, codeSliceElem, codeMapKey: + nextCode = code.end default: nextCode = code.next } @@ -79,17 +77,13 @@ func (c *opcode) beforeLastCode() *opcode { return nil } -func (c *opcode) length() int { +func (c *opcode) totalLength() int { var idx int for code := c; code.op != opEnd; { idx = code.displayIdx switch code.op.codeType() { - case codeArrayElem: - code = code.toArrayElemCode().end - case codeSliceElem: - code = code.toSliceElemCode().end - case codeMapKey: - code = code.toMapKeyCode().end + case codeArrayElem, codeSliceElem, codeMapKey: + code = code.end default: code = code.next } @@ -102,310 +96,86 @@ func (c *opcode) decOpcodeIndex() { code.displayIdx-- code.idx -= 8 switch code.op.codeType() { - case codeArrayElem: - code = code.toArrayElemCode().end - case codeSliceElem: - code = code.toSliceElemCode().end - case codeMapKey: - code = code.toMapKeyCode().end + case codeArrayElem, codeSliceElem, codeMapKey: + code = code.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 +func (c *opcode) dumpElem(code *opcode) string { + return fmt.Sprintf( + `[%d]%s%s ([headIdx:%d][elemIdx:%d][length:%d][size:%d])`, + code.displayIdx, + strings.Repeat("-", code.indent), + code.op, + code.headIdx, + code.elemIdx, + code.length, + code.size, + ) +} - code.opcodeHeader = c.opcodeHeader.copy(codeMap) - } - return code +func (c *opcode) dumpField(code *opcode) string { + return fmt.Sprintf( + `[%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 { 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.displayIdx, indent, code.op, unsafe.Pointer(code))) - code = code.toArrayElemCode().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 codeArrayElem, codeSliceElem: + codes = append(codes, c.dumpElem(code)) + code = code.end case codeMapKey: - codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) - code = code.toMapKeyCode().end + codes = append(codes, c.dumpKey(code)) + code = code.end case codeStructField: - sf := code.toStructFieldCode() - 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))) + codes = append(codes, c.dumpField(code)) code = code.next 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 } } 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, - 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) { +func linkPrevToNextField(prev, cur *opcode) { prev.nextField = cur.nextField - code := prev.toOpcode() - fcode := cur.toOpcode() + code := prev + fcode := cur 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 + case codeArrayElem, codeSliceElem, codeMapKey: + nextCode = code.end default: nextCode = code.next } @@ -419,213 +189,108 @@ func linkPrevToNextField(prev, cur *structFieldCode) { } } -func (c *structFieldCode) toOpcode() *opcode { - return (*opcode)(unsafe.Pointer(c)) +func newSliceHeaderCode(ctx *encodeCompileContext) *opcode { + return &opcode{ + op: opSliceHead, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, + } } -func (c *structFieldCode) copy(codeMap map[uintptr]*opcode) *opcode { - if c == nil { - return nil +func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *opcode { + return &opcode{ + 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 { - *opcodeHeader - key *mapKeyCode - value *mapValueCode - end *opcode +func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *opcode { + return &opcode{ + op: opArrayHead, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, + length: uintptr(alen), + } } -func (c *mapHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode { - if c == nil { - return nil +func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *opcode { + return &opcode{ + 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 { - *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 { +func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *opcode { var op opType if withLoad { op = opMapHeadLoad } else { op = opMapHead } - return &mapHeaderCode{ - opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - }, + return &opcode{ + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, } } -func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { - return &mapKeyCode{ - opcodeHeader: &opcodeHeader{ - op: opMapKey, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - }, +func newMapKeyCode(ctx *encodeCompileContext) *opcode { + return &opcode{ + op: opMapKey, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, } } -func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { - return &mapValueCode{ - opcodeHeader: &opcodeHeader{ - op: opMapValue, - displayIdx: ctx.opcodeIndex, - idx: uintptr(ctx.opcodeIndex) * 8, - indent: ctx.indent, - }, +func newMapValueCode(ctx *encodeCompileContext) *opcode { + return &opcode{ + op: opMapValue, + displayIdx: ctx.opcodeIndex, + idx: opcodeOffset(ctx.opcodeIndex), + indent: ctx.indent, } } -type interfaceCode struct { - *opcodeHeader - root bool +func newInterfaceCode(ctx *encodeCompileContext) *opcode { + return &opcode{ + 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 { - if c == nil { - return nil +func newRecursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode { + return &opcode{ + 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 { - *opcodeHeader - jmp *compiledCode - seenPtr uintptr -} +//func newRecursiveCode(recursive *recursiveCode) *opcode { +//code := copyOpcode(recursive.jmp.code) +//head := (*structFieldCode)(unsafe.Pointer(code)) +//head.end.next = newEndOp(&encodeCompileContext{}) -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 -} +//code.op = code.op.ptrHeadToHead() +// return code +//} diff --git a/encode_vm.go b/encode_vm.go index e873ae8..409a60c 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -92,10 +92,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } code = code.next case opInterface: - ifaceCode := code.toInterfaceCode() - ptr := load(ctxptr, ifaceCode.idx) + ptr := load(ctxptr, code.idx) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ - typ: ifaceCode.typ, + typ: code.typ, ptr: unsafe.Pointer(ptr), })) if _, exists := seenPtr[ptr]; exists { @@ -108,7 +107,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c rv := reflect.ValueOf(v) if rv.IsNil() { e.encodeNull() - code = ifaceCode.next + code = code.next break } vv := rv.Interface() @@ -121,9 +120,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if typ.Kind() == reflect.Map { code, err := e.compileMap(&encodeCompileContext{ typ: typ, - root: ifaceCode.root, + root: code.root, withIndent: e.enabledIndent, - indent: ifaceCode.indent, + indent: code.indent, }, false) if err != nil { return err @@ -132,9 +131,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { code, err := e.compile(&encodeCompileContext{ typ: typ, - root: ifaceCode.root, + root: code.root, withIndent: e.enabledIndent, - indent: ifaceCode.indent, + indent: code.indent, }) if err != nil { return err @@ -142,13 +141,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c c = code } ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, c.length()), + ptrs: make([]uintptr, c.totalLength()), } ctx.init(uintptr(header.ptr)) if err := e.run(ctx, seenPtr, c); err != nil { return err } - code = ifaceCode.next + code = code.next case opMarshalJSON: ptr := load(ctxptr, code.idx) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ @@ -213,43 +212,48 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c code = code.next case opSliceHead: p := load(ctxptr, code.idx) - headerCode := code.toSliceHeaderCode() header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { e.encodeNull() - code = headerCode.end.next + code = code.end.next } else { e.encodeByte('[') - headerCode.elem.set(header) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(header.Len)) + store(ctxptr, code.idx, header.Data) if header.Len > 0 { code = code.next store(ctxptr, code.idx, header.Data) } else { e.encodeByte(']') - code = headerCode.end.next + code = code.end.next } } case opSliceElem: - c := code.toSliceElemCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeByte(',') + store(ctxptr, code.elemIdx, idx) code = code.next - store(ctxptr, code.idx, c.data+c.idx*c.size) + data := load(ctxptr, code.headIdx) + store(ctxptr, code.idx, data+idx*code.size) } else { e.encodeByte(']') - code = c.end.next + code = code.end.next } case opSliceHeadIndent: p := load(ctxptr, code.idx) - headerCode := code.toSliceHeaderCode() if p == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = headerCode.end.next + code = code.end.next } else { header := (*reflect.SliceHeader)(unsafe.Pointer(p)) - headerCode.elem.set(header) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(header.Len)) + store(ctxptr, code.idx, header.Data) if header.Len > 0 { e.encodeBytes([]byte{'[', '\n'}) e.encodeIndent(code.indent + 1) @@ -258,19 +262,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'[', ']'}) - code = headerCode.end.next + code = code.end.next } } case opRootSliceHeadIndent: p := load(ctxptr, code.idx) - headerCode := code.toSliceHeaderCode() if p == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = headerCode.end.next + code = code.end.next } else { header := (*reflect.SliceHeader)(unsafe.Pointer(p)) - headerCode.elem.set(header) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(header.Len)) + store(ctxptr, code.idx, header.Data) if header.Len > 0 { e.encodeBytes([]byte{'[', '\n'}) e.encodeIndent(code.indent + 1) @@ -279,128 +284,131 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'[', ']'}) - code = headerCode.end.next + code = code.end.next } } case opSliceElemIndent: - c := code.toSliceElemCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) + store(ctxptr, code.elemIdx, idx) code = code.next - store(ctxptr, code.idx, c.data+c.idx*c.size) + data := load(ctxptr, code.headIdx) + store(ctxptr, code.idx, data+idx*code.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) e.encodeByte(']') - code = c.end.next + code = code.end.next } case opRootSliceElemIndent: - c := code.toSliceElemCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) + store(ctxptr, code.elemIdx, idx) code = code.next - store(ctxptr, code.idx, c.data+c.idx*c.size) + data := load(ctxptr, code.headIdx) + store(ctxptr, code.idx, data+idx*code.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) e.encodeByte(']') - code = c.end.next + code = code.end.next } case opArrayHead: p := load(ctxptr, code.idx) - headerCode := code.toArrayHeaderCode() if p == 0 { e.encodeNull() - code = headerCode.end.next + code = code.end.next } else { e.encodeByte('[') - if headerCode.len > 0 { + if code.length > 0 { code = code.next store(ctxptr, code.idx, p) - store(ctxptr, headerCode.elem.opcodeHeader.idx, p) } else { e.encodeByte(']') - code = headerCode.end.next + code = code.end.next } } case opArrayElem: - c := code.toArrayElemCode() - c.idx++ - p := load(ctxptr, c.opcodeHeader.idx) - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + idx++ + if idx < code.length { e.encodeByte(',') + store(ctxptr, code.elemIdx, idx) + p := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, p+c.idx*c.size) + store(ctxptr, code.idx, p+idx*code.size) } else { e.encodeByte(']') - code = c.end.next + code = code.end.next } case opArrayHeadIndent: p := load(ctxptr, code.idx) - headerCode := code.toArrayHeaderCode() if p == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = headerCode.end.next + code = code.end.next } else { e.encodeBytes([]byte{'[', '\n'}) - if headerCode.len > 0 { + if code.length > 0 { e.encodeIndent(code.indent + 1) code = code.next store(ctxptr, code.idx, p) - store(ctxptr, headerCode.elem.opcodeHeader.idx, p) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{']', '\n'}) - code = headerCode.end.next + code = code.end.next } } case opArrayElemIndent: - c := code.toArrayElemCode() - c.idx++ - p := load(ctxptr, c.opcodeHeader.idx) - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + idx++ + if idx < code.length { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) + store(ctxptr, code.elemIdx, idx) + p := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, p+c.idx*c.size) + store(ctxptr, code.idx, p+idx*code.size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) e.encodeBytes([]byte{']', '\n'}) - code = c.end.next + code = code.end.next } case opMapHead: ptr := load(ctxptr, code.idx) - mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeNull() - code = mapHeadCode.end.next + code = code.end.next } else { e.encodeByte('{') mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - mapHeadCode.key.set(mlen, iter) - mapHeadCode.value.set(iter) + store(ctxptr, code.mapKey.length, uintptr(mlen)) + store(ctxptr, code.mapKey.mapIter, uintptr(iter)) + store(ctxptr, code.mapValue.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next } else { e.encodeByte('}') - code = mapHeadCode.end.next + code = code.end.next } } case opMapHeadLoad: ptr := load(ctxptr, code.idx) - mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeNull() - code = mapHeadCode.end.next + code = code.end.next } else { // load pointer ptr = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(ptr))) @@ -408,49 +416,53 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - mapHeadCode.key.set(mlen, iter) - mapHeadCode.value.set(iter) + store(ctxptr, code.mapKey.length, uintptr(mlen)) + store(ctxptr, code.mapKey.mapIter, uintptr(iter)) + store(ctxptr, code.mapValue.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next } else { e.encodeByte('}') - code = mapHeadCode.end.next + code = code.end.next } } case opMapKey: - c := code.toMapKeyCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeByte(',') - key := mapiterkey(c.iter) - store(ctxptr, c.next.idx, uintptr(key)) - code = c.next + iter := unsafe.Pointer(load(ctxptr, code.mapIter)) + store(ctxptr, code.elemIdx, idx) + key := mapiterkey(iter) + store(ctxptr, code.next.idx, uintptr(key)) + code = code.next } else { e.encodeByte('}') - code = c.end.next + code = code.end.next } case opMapValue: e.encodeByte(':') - c := code.toMapValueCode() - value := mapitervalue(c.iter) - store(ctxptr, c.next.idx, uintptr(value)) - mapiternext(c.iter) - code = c.next + iter := unsafe.Pointer(load(ctxptr, code.mapIter)) + value := mapitervalue(iter) + store(ctxptr, code.next.idx, uintptr(value)) + mapiternext(iter) + code = code.next case opMapHeadIndent: ptr := load(ctxptr, code.idx) - mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = mapHeadCode.end.next + code = code.end.next } else { mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - mapHeadCode.key.set(mlen, iter) - mapHeadCode.value.set(iter) + store(ctxptr, code.mapKey.length, uintptr(mlen)) + store(ctxptr, code.mapKey.mapIter, uintptr(iter)) + store(ctxptr, code.mapValue.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -458,16 +470,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) - code = mapHeadCode.end.next + code = code.end.next } } case opMapHeadLoadIndent: ptr := load(ctxptr, code.idx) - mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = mapHeadCode.end.next + code = code.end.next } else { // load pointer ptr = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(ptr))) @@ -475,8 +486,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - mapHeadCode.key.set(mlen, iter) - mapHeadCode.value.set(iter) + store(ctxptr, code.mapKey.length, uintptr(mlen)) + store(ctxptr, code.mapKey.mapIter, uintptr(iter)) + store(ctxptr, code.mapValue.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -484,23 +496,23 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) - code = mapHeadCode.end.next + code = code.end.next } } case opRootMapHeadIndent: ptr := load(ctxptr, code.idx) - mapHeadCode := code.toMapHeadCode() if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = mapHeadCode.end.next + code = code.end.next } else { mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - mapHeadCode.key.set(mlen, iter) - mapHeadCode.value.set(iter) + store(ctxptr, code.mapKey.length, uintptr(mlen)) + store(ctxptr, code.mapKey.mapIter, uintptr(iter)) + store(ctxptr, code.mapValue.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -508,69 +520,77 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) - code = mapHeadCode.end.next + code = code.end.next } } case opMapKeyIndent: - c := code.toMapKeyCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent) - key := mapiterkey(c.iter) - store(ctxptr, c.next.idx, uintptr(key)) - code = c.next + store(ctxptr, code.elemIdx, idx) + iter := unsafe.Pointer(load(ctxptr, code.mapIter)) + key := mapiterkey(iter) + store(ctxptr, code.next.idx, uintptr(key)) + code = code.next } else { e.encodeByte('\n') e.encodeIndent(code.indent - 1) e.encodeByte('}') - code = c.end.next + code = code.end.next } case opRootMapKeyIndent: - c := code.toMapKeyCode() - c.idx++ - if c.idx < c.len { + idx := load(ctxptr, code.elemIdx) + length := load(ctxptr, code.length) + idx++ + if idx < length { e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent) - key := mapiterkey(c.iter) - store(ctxptr, c.next.idx, uintptr(key)) - code = c.next + store(ctxptr, code.elemIdx, idx) + iter := unsafe.Pointer(load(ctxptr, code.mapIter)) + key := mapiterkey(iter) + store(ctxptr, code.next.idx, uintptr(key)) + code = code.next } else { e.encodeByte('\n') e.encodeIndent(code.indent - 1) e.encodeByte('}') - code = c.end.next + code = code.end.next } case opMapValueIndent: e.encodeBytes([]byte{':', ' '}) - c := code.toMapValueCode() - value := mapitervalue(c.iter) - store(ctxptr, c.next.idx, uintptr(value)) - mapiternext(c.iter) - code = c.next + iter := unsafe.Pointer(load(ctxptr, code.mapIter)) + value := mapitervalue(iter) + store(ctxptr, code.next.idx, uintptr(value)) + mapiternext(iter) + code = code.next case opStructFieldRecursive: - recursive := code.toRecursiveCode() ptr := load(ctxptr, code.idx) - if recursive.seenPtr != 0 && recursive.seenPtr == ptr { - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ - typ: code.typ, - ptr: unsafe.Pointer(ptr), - })) - return &UnsupportedValueError{ - Value: reflect.ValueOf(v), - Str: fmt.Sprintf("encountered a cycle via %s", code.typ), + if ptr != 0 { + if _, exists := seenPtr[ptr]; exists { + v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + typ: code.typ, + ptr: unsafe.Pointer(ptr), + })) + return &UnsupportedValueError{ + Value: reflect.ValueOf(v), + Str: fmt.Sprintf("encountered a cycle via %s", code.typ), + } } } - recursive.seenPtr = ptr - recursiveCode := newRecursiveCode(recursive) + c := *(code.jmp.code) ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, recursiveCode.length()), + ptrs: make([]uintptr, c.totalLength()), } ctx.init(ptr) - if err := e.run(ctx, seenPtr, recursiveCode); err != nil { + c.end.next = newEndOp(&encodeCompileContext{}) + c.op = c.op.ptrHeadToHead() + if err := e.run(ctx, seenPtr, &c); err != nil { return err } - code = recursive.next + code = code.next case opStructFieldPtrHead: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -578,7 +598,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHead: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHead { @@ -586,31 +605,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - if !field.anonymousKey { - e.encodeBytes(field.key) + if !code.anonymousKey { + e.encodeBytes(code.key) } - code = field.next - store(ctxptr, code.idx, ptr+field.offset) - store(ctxptr, field.nextField.idx, ptr) + code = code.next + store(ctxptr, code.idx, ptr+code.offset) } case opStructFieldAnonymousHead: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - code = field.next + code = code.next store(ctxptr, code.idx, ptr) - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt { @@ -618,33 +633,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeInt(e.ptrToInt(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt(e.ptrToInt(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeInt(e.ptrToInt(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt(e.ptrToInt(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt8 { @@ -652,33 +663,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeInt8(e.ptrToInt8(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt8(e.ptrToInt8(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeInt8(e.ptrToInt8(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt8(e.ptrToInt8(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadInt16: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt16 { @@ -686,33 +693,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeInt16(e.ptrToInt16(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt16(e.ptrToInt16(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadInt16: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeInt16(e.ptrToInt16(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt16(e.ptrToInt16(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadInt32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt32 { @@ -720,33 +723,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeInt32(e.ptrToInt32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt32(e.ptrToInt32(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadInt32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeInt32(e.ptrToInt32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt32(e.ptrToInt32(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadInt64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadInt64 { @@ -754,33 +753,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeInt64(e.ptrToInt64(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt64(e.ptrToInt64(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadInt64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeInt64(e.ptrToInt64(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeInt64(e.ptrToInt64(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadUint: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint { @@ -788,33 +783,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeUint(e.ptrToUint(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint(e.ptrToUint(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadUint: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeUint(e.ptrToUint(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint(e.ptrToUint(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadUint8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint8 { @@ -822,33 +813,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeUint8(e.ptrToUint8(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint8(e.ptrToUint8(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadUint8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint8: - field := code.toStructFieldCode() - ptr := load(ctxptr, field.idx) + ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeUint8(e.ptrToUint8(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint8(e.ptrToUint8(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadUint16: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint16 { @@ -856,33 +843,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeUint16(e.ptrToUint16(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint16(e.ptrToUint16(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadUint16: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeUint16(e.ptrToUint16(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint16(e.ptrToUint16(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadUint32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint32 { @@ -890,33 +873,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeUint32(e.ptrToUint32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint32(e.ptrToUint32(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadUint32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeUint32(e.ptrToUint32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint32(e.ptrToUint32(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadUint64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadUint64 { @@ -924,33 +903,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeUint64(e.ptrToUint64(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint64(e.ptrToUint64(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadUint64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeUint64(e.ptrToUint64(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeUint64(e.ptrToUint64(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadFloat32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadFloat32 { @@ -958,33 +933,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeFloat32(e.ptrToFloat32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadFloat32: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeFloat32(e.ptrToFloat32(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadFloat64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadFloat64 { @@ -992,9 +963,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -1002,37 +973,33 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } } e.encodeByte('{') - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat64(v) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrAnonymousHeadFloat64: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), Str: strconv.FormatFloat(v, 'g', -1, 64), } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat64(v) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadString: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadString { @@ -1040,33 +1007,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(e.ptrToString(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeString(e.ptrToString(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadString: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeString(e.ptrToString(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeString(e.ptrToString(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadBool: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadBool { @@ -1074,33 +1037,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeBool(e.ptrToBool(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeBool(e.ptrToBool(ptr + code.offset)) + code = code.next } case opStructFieldPtrAnonymousHeadBool: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - e.encodeBool(e.ptrToBool(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeBytes(code.key) + e.encodeBool(e.ptrToBool(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadBytes: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadBytes { @@ -1108,128 +1067,116 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + field.offset)) + e.encodeBytes(code.key) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrAnonymousHeadBytes: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + field.offset)) + e.encodeBytes(code.key) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadArray: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadArray: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + c.offset + ptr := load(ctxptr, code.idx) + code.offset if ptr == 0 { if code.op == opStructFieldPtrHeadArray { e.encodeNull() } else { e.encodeBytes([]byte{'[', ']'}) } - code = c.end + code = code.end } else { e.encodeByte('{') - if !c.anonymousKey { - e.encodeBytes(c.key) + if !code.anonymousKey { + e.encodeBytes(code.key) } - code = c.next + code = code.next store(ctxptr, code.idx, ptr) - store(ctxptr, c.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadArray: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadArray: - c := code.toStructFieldCode() - ptr := load(ctxptr, code.idx) + c.offset + ptr := load(ctxptr, code.idx) + code.offset if ptr == 0 { - code = c.end + code = code.end } else { - e.encodeBytes(c.key) + e.encodeBytes(code.key) store(ctxptr, code.idx, ptr) - store(ctxptr, c.nextField.idx, ptr) - code = c.next + code = code.next } case opStructFieldPtrHeadSlice: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadSlice: - c := code.toStructFieldCode() ptr := load(ctxptr, code.idx) - p := ptr + c.offset + p := ptr + code.offset if p == 0 { if code.op == opStructFieldPtrHeadSlice { e.encodeNull() } else { e.encodeBytes([]byte{'[', ']'}) } - code = c.end + code = code.end } else { e.encodeByte('{') - if !c.anonymousKey { - e.encodeBytes(c.key) + if !code.anonymousKey { + e.encodeBytes(code.key) } - code = c.next + code = code.next store(ctxptr, code.idx, p) - store(ctxptr, c.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadSlice: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadSlice: - c := code.toStructFieldCode() ptr := load(ctxptr, code.idx) - p := ptr + c.offset + p := ptr + code.offset if p == 0 { - code = c.end + code = code.end } else { - e.encodeBytes(c.key) + e.encodeBytes(code.key) store(ctxptr, code.idx, p) - store(ctxptr, c.nextField.idx, ptr) - code = c.next + code = code.next } case opStructFieldPtrHeadMarshalJSON: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) + e.encodeBytes(code.key) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr + field.offset), + ptr: unsafe.Pointer(ptr + code.offset), })) rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = field.end + code = code.end break } b, err := rv.Interface().(Marshaler).MarshalJSON() @@ -1250,27 +1197,25 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c return err } e.encodeBytes(buf.Bytes()) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrAnonymousHeadMarshalJSON: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr + field.offset), + ptr: unsafe.Pointer(ptr + code.offset), })) rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = field.end + code = code.end break } b, err := rv.Interface().(Marshaler).MarshalJSON() @@ -1291,29 +1236,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c return err } e.encodeBytes(buf.Bytes()) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadMarshalText: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end + code = code.end } else { e.encodeByte('{') - e.encodeBytes(field.key) + e.encodeBytes(code.key) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr + field.offset), + ptr: unsafe.Pointer(ptr + code.offset), })) rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = field.end + code = code.end break } bytes, err := rv.Interface().(encoding.TextMarshaler).MarshalText() @@ -1324,27 +1267,25 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrAnonymousHeadMarshalText: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldAnonymousHeadMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end + code = code.end } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, - ptr: unsafe.Pointer(ptr + field.offset), + ptr: unsafe.Pointer(ptr + code.offset), })) rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = field.end + code = code.end break } bytes, err := rv.Interface().(encoding.TextMarshaler).MarshalText() @@ -1355,8 +1296,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadIndent: ptr := load(ctxptr, code.idx) @@ -1365,34 +1305,30 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next - } else if field.next == field.end { + code = code.end.next + } else if code.next == code.end { // not exists fields e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) - code = field.next + code = code.next store(ctxptr, code.idx, ptr) - store(ctxptr, field.nextField.idx, ptr) } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - code = field.next + code = code.next store(ctxptr, code.idx, ptr) - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadIntIndent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadIntIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { if code.op == opStructFieldPtrHeadIntIndent { @@ -1401,225 +1337,203 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeBytes([]byte{'{', '}'}) } - code = field.end + code = code.end } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeInt(e.ptrToInt(ptr + field.offset)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + e.encodeInt(e.ptrToInt(ptr + code.offset)) + code = code.next } case opStructFieldPtrHeadInt8Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt8(e.ptrToInt8(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadInt16Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt16(e.ptrToInt16(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadInt32Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt32(e.ptrToInt32(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadInt64Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadInt64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt64(e.ptrToInt64(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadUintIndent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUintIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint(e.ptrToUint(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadUint8Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint8(e.ptrToUint8(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadUint16Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint16(e.ptrToUint16(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadUint32Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint32(e.ptrToUint32(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadUint64Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadUint64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint64(e.ptrToUint64(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadFloat32Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat32(e.ptrToFloat32(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadFloat64Indent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadFloat64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { v := e.ptrToFloat64(ptr) if math.IsInf(v, 0) || math.IsNaN(v) { @@ -1631,74 +1545,67 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat64(v) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadStringIndent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadStringIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeString(e.ptrToString(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadBoolIndent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBoolIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeBool(e.ptrToBool(ptr)) - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadBytesIndent: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough case opStructFieldHeadBytesIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end + code = code.end } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - store(ctxptr, field.nextField.idx, ptr) - code = field.next + code = code.next } case opStructFieldPtrHeadOmitEmpty: ptr := load(ctxptr, code.idx) @@ -1707,22 +1614,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmpty: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := ptr + field.offset + p := ptr + code.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) - code = field.next + e.encodeBytes(code.key) + code = code.next store(ctxptr, code.idx, p) } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmpty: ptr := load(ctxptr, code.idx) @@ -1731,20 +1636,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmpty: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - p := ptr + field.offset + p := ptr + code.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) - code = field.next + e.encodeBytes(code.key) + code = code.next store(ctxptr, code.idx, p) } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt: ptr := load(ctxptr, code.idx) @@ -1753,22 +1656,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToInt(ptr + field.offset) + v := e.ptrToInt(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt: ptr := load(ctxptr, code.idx) @@ -1777,20 +1678,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToInt(ptr + field.offset) + v := e.ptrToInt(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) @@ -1799,22 +1698,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToInt8(ptr + field.offset) + v := e.ptrToInt8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) @@ -1823,20 +1720,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToInt8(ptr + field.offset) + v := e.ptrToInt8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt16: ptr := load(ctxptr, code.idx) @@ -1845,22 +1740,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToInt16(ptr + field.offset) + v := e.ptrToInt16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt16: ptr := load(ctxptr, code.idx) @@ -1869,20 +1762,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToInt16(ptr + field.offset) + v := e.ptrToInt16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt32: ptr := load(ctxptr, code.idx) @@ -1891,22 +1782,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToInt32(ptr + field.offset) + v := e.ptrToInt32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt32: ptr := load(ctxptr, code.idx) @@ -1915,20 +1804,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToInt32(ptr + field.offset) + v := e.ptrToInt32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt64: ptr := load(ctxptr, code.idx) @@ -1937,22 +1824,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToInt64(ptr + field.offset) + v := e.ptrToInt64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyInt64: ptr := load(ctxptr, code.idx) @@ -1961,20 +1846,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToInt64(ptr + field.offset) + v := e.ptrToInt64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeInt64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint: ptr := load(ctxptr, code.idx) @@ -1983,22 +1866,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToUint(ptr + field.offset) + v := e.ptrToUint(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint: ptr := load(ctxptr, code.idx) @@ -2007,20 +1888,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToUint(ptr + field.offset) + v := e.ptrToUint(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint8: ptr := load(ctxptr, code.idx) @@ -2029,22 +1908,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToUint8(ptr + field.offset) + v := e.ptrToUint8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint8: ptr := load(ctxptr, code.idx) @@ -2053,20 +1930,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToUint8(ptr + field.offset) + v := e.ptrToUint8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint16: ptr := load(ctxptr, code.idx) @@ -2075,22 +1950,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToUint16(ptr + field.offset) + v := e.ptrToUint16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint16: ptr := load(ctxptr, code.idx) @@ -2099,20 +1972,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToUint16(ptr + field.offset) + v := e.ptrToUint16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint32: ptr := load(ctxptr, code.idx) @@ -2121,22 +1992,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToUint32(ptr + field.offset) + v := e.ptrToUint32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint32: ptr := load(ctxptr, code.idx) @@ -2145,20 +2014,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToUint32(ptr + field.offset) + v := e.ptrToUint32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint64: ptr := load(ctxptr, code.idx) @@ -2167,22 +2034,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToUint64(ptr + field.offset) + v := e.ptrToUint64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyUint64: ptr := load(ctxptr, code.idx) @@ -2191,20 +2056,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToUint64(ptr + field.offset) + v := e.ptrToUint64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeUint64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat32: ptr := load(ctxptr, code.idx) @@ -2213,22 +2076,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToFloat32(ptr + field.offset) + v := e.ptrToFloat32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyFloat32: ptr := load(ctxptr, code.idx) @@ -2237,20 +2098,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToFloat32(ptr + field.offset) + v := e.ptrToFloat32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat64: ptr := load(ctxptr, code.idx) @@ -2259,16 +2118,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -2276,11 +2134,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Str: strconv.FormatFloat(v, 'g', -1, 64), } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyFloat64: ptr := load(ctxptr, code.idx) @@ -2289,14 +2146,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -2304,11 +2160,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Str: strconv.FormatFloat(v, 'g', -1, 64), } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeFloat64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyString: ptr := load(ctxptr, code.idx) @@ -2317,22 +2172,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToString(ptr + field.offset) + v := e.ptrToString(ptr + code.offset) if v == "" { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyString: ptr := load(ctxptr, code.idx) @@ -2341,20 +2194,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToString(ptr + field.offset) + v := e.ptrToString(ptr + code.offset) if v == "" { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) @@ -2363,22 +2214,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToBool(ptr + field.offset) + v := e.ptrToBool(ptr + code.offset) if !v { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBool(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) @@ -2387,20 +2236,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToBool(ptr + field.offset) + v := e.ptrToBool(ptr + code.offset) if !v { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBool(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBytes: ptr := load(ctxptr, code.idx) @@ -2409,25 +2256,23 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToBytes(ptr + field.offset) + v := e.ptrToBytes(ptr + code.offset) if len(v) == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyBytes: ptr := load(ctxptr, code.idx) @@ -2436,23 +2281,21 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToBytes(ptr + field.offset) + v := e.ptrToBytes(ptr + code.offset) if len(v) == 0 { - code = field.nextField + code = code.nextField } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyMarshalJSON: ptr := load(ctxptr, code.idx) @@ -2461,17 +2304,16 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) { - code = field.nextField + code = code.nextField } else { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) b, err := v.(Marshaler).MarshalJSON() @@ -2488,18 +2330,17 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c 0, ) } - code = field.nextField + code = code.nextField } else { var buf bytes.Buffer if err := compact(&buf, b, true); err != nil { return err } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBytes(buf.Bytes()) - code = field.next + code = code.next } } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSON: ptr := load(ctxptr, code.idx) @@ -2508,15 +2349,14 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) { - code = field.nextField + code = code.nextField } else { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) b, err := v.(Marshaler).MarshalJSON() @@ -2533,18 +2373,17 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c 0, ) } - code = field.nextField + code = code.nextField } else { var buf bytes.Buffer if err := compact(&buf, b, true); err != nil { return err } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBytes(buf.Bytes()) - code = field.next + code = code.next } } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyMarshalText: ptr := load(ctxptr, code.idx) @@ -2553,17 +2392,16 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) { - code = field.nextField + code = code.nextField } else { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) bytes, err := v.(encoding.TextMarshaler).MarshalText() @@ -2573,11 +2411,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Err: err, } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadOmitEmptyMarshalText: ptr := load(ctxptr, code.idx) @@ -2586,15 +2423,14 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadOmitEmptyMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) { - code = field.nextField + code = code.nextField } else { v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) bytes, err := v.(encoding.TextMarshaler).MarshalText() @@ -2604,11 +2440,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Err: err, } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyIndent: ptr := load(ctxptr, code.idx) @@ -2617,26 +2452,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - p := ptr + field.offset + p := ptr + code.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - code = field.next + code = code.next store(ctxptr, code.idx, p) } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyIntIndent: ptr := load(ctxptr, code.idx) @@ -2645,26 +2478,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyIntIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToInt(ptr + field.offset) + v := e.ptrToInt(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt8Indent: ptr := load(ctxptr, code.idx) @@ -2673,26 +2504,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToInt8(ptr + field.offset) + v := e.ptrToInt8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt16Indent: ptr := load(ctxptr, code.idx) @@ -2701,26 +2530,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToInt16(ptr + field.offset) + v := e.ptrToInt16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt32Indent: ptr := load(ctxptr, code.idx) @@ -2729,26 +2556,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToInt32(ptr + field.offset) + v := e.ptrToInt32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyInt64Indent: ptr := load(ctxptr, code.idx) @@ -2757,26 +2582,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyInt64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToInt64(ptr + field.offset) + v := e.ptrToInt64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUintIndent: ptr := load(ctxptr, code.idx) @@ -2785,26 +2608,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUintIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToUint(ptr + field.offset) + v := e.ptrToUint(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint8Indent: ptr := load(ctxptr, code.idx) @@ -2813,26 +2634,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToUint8(ptr + field.offset) + v := e.ptrToUint8(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint8(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint16Indent: ptr := load(ctxptr, code.idx) @@ -2841,26 +2660,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToUint16(ptr + field.offset) + v := e.ptrToUint16(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint16(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint32Indent: ptr := load(ctxptr, code.idx) @@ -2869,26 +2686,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToUint32(ptr + field.offset) + v := e.ptrToUint32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyUint64Indent: ptr := load(ctxptr, code.idx) @@ -2897,26 +2712,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyUint64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToUint64(ptr + field.offset) + v := e.ptrToUint64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat32Indent: ptr := load(ctxptr, code.idx) @@ -2925,26 +2738,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyFloat32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToFloat32(ptr + field.offset) + v := e.ptrToFloat32(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat32(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyFloat64Indent: ptr := load(ctxptr, code.idx) @@ -2953,18 +2764,17 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyFloat64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if v == 0 { - code = field.nextField + code = code.nextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -2973,12 +2783,11 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } } e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat64(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyStringIndent: ptr := load(ctxptr, code.idx) @@ -2987,26 +2796,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyStringIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToString(ptr + field.offset) + v := e.ptrToString(ptr + code.offset) if v == "" { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeString(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBoolIndent: ptr := load(ctxptr, code.idx) @@ -3015,26 +2822,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyBoolIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToBool(ptr + field.offset) + v := e.ptrToBool(ptr + code.offset) if !v { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeBool(v) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadOmitEmptyBytesIndent: ptr := load(ctxptr, code.idx) @@ -3043,29 +2848,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadOmitEmptyBytesIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToBytes(ptr + field.offset) + v := e.ptrToBytes(ptr + code.offset) if len(v) == 0 { - code = field.nextField + code = code.nextField } else { e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTag: ptr := load(ctxptr, code.idx) @@ -3074,18 +2877,16 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTag: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := ptr + field.offset - e.encodeBytes(field.key) - code = field.next + p := ptr + code.offset + e.encodeBytes(code.key) + code = code.next store(ctxptr, code.idx, p) - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTag: ptr := load(ctxptr, code.idx) @@ -3094,15 +2895,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTag: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - code = field.next - store(ctxptr, code.idx, ptr+field.offset) - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + code = code.next + store(ctxptr, code.idx, ptr+code.offset) } case opStructFieldPtrHeadStringTagInt: ptr := load(ctxptr, code.idx) @@ -3111,17 +2910,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagInt: ptr := load(ctxptr, code.idx) @@ -3130,15 +2927,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagInt: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt8: ptr := load(ctxptr, code.idx) @@ -3147,17 +2942,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagInt8: ptr := load(ctxptr, code.idx) @@ -3166,15 +2959,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagInt8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt16: ptr := load(ctxptr, code.idx) @@ -3183,17 +2974,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagInt16: ptr := load(ctxptr, code.idx) @@ -3202,15 +2991,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagInt16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt32: ptr := load(ctxptr, code.idx) @@ -3219,17 +3006,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagInt32: ptr := load(ctxptr, code.idx) @@ -3238,15 +3023,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagInt32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt64: ptr := load(ctxptr, code.idx) @@ -3255,17 +3038,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagInt64: ptr := load(ctxptr, code.idx) @@ -3274,15 +3055,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagInt64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint: ptr := load(ctxptr, code.idx) @@ -3291,17 +3070,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagUint: ptr := load(ctxptr, code.idx) @@ -3310,15 +3087,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagUint: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint8: ptr := load(ctxptr, code.idx) @@ -3327,17 +3102,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagUint8: ptr := load(ctxptr, code.idx) @@ -3346,15 +3119,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagUint8: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint16: ptr := load(ctxptr, code.idx) @@ -3363,17 +3134,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagUint16: ptr := load(ctxptr, code.idx) @@ -3382,15 +3151,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagUint16: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint32: ptr := load(ctxptr, code.idx) @@ -3399,17 +3166,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagUint32: ptr := load(ctxptr, code.idx) @@ -3418,15 +3183,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagUint32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint64: ptr := load(ctxptr, code.idx) @@ -3435,17 +3198,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagUint64: ptr := load(ctxptr, code.idx) @@ -3454,15 +3215,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagUint64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagFloat32: ptr := load(ctxptr, code.idx) @@ -3471,17 +3230,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagFloat32: ptr := load(ctxptr, code.idx) @@ -3490,15 +3247,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagFloat32: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagFloat64: ptr := load(ctxptr, code.idx) @@ -3507,24 +3262,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), Str: strconv.FormatFloat(v, 'g', -1, 64), } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(fmt.Sprint(v)) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagFloat64: ptr := load(ctxptr, code.idx) @@ -3533,22 +3286,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagFloat64: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), Str: strconv.FormatFloat(v, 'g', -1, 64), } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(fmt.Sprint(v)) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrHeadStringTagString: ptr := load(ctxptr, code.idx) @@ -3557,17 +3308,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(strconv.Quote(e.ptrToString(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagString: ptr := load(ctxptr, code.idx) @@ -3576,15 +3325,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagString: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(strconv.Quote(e.ptrToString(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagBool: ptr := load(ctxptr, code.idx) @@ -3593,17 +3340,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + code.offset))) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagBool: ptr := load(ctxptr, code.idx) @@ -3612,15 +3357,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagBool: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) - e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagBytes: ptr := load(ctxptr, code.idx) @@ -3629,22 +3372,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - e.encodeBytes(field.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + field.offset), + e.ptrToBytes(ptr + code.offset), ) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagBytes: ptr := load(ctxptr, code.idx) @@ -3653,20 +3394,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagBytes: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - e.encodeBytes(field.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + field.offset), + e.ptrToBytes(ptr + code.offset), ) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrHeadStringTagMarshalJSON: ptr := load(ctxptr, code.idx) @@ -3675,14 +3414,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) b, err := v.(Marshaler).MarshalJSON() @@ -3699,18 +3437,17 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c 0, ) } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBytes([]byte{'"', '"'}) - code = field.nextField + code = code.nextField } else { var buf bytes.Buffer if err := compact(&buf, b, true); err != nil { return err } e.encodeString(buf.String()) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrAnonymousHeadStringTagMarshalJSON: ptr := load(ctxptr, code.idx) @@ -3719,12 +3456,11 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagMarshalJSON: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) isPtr := code.typ.Kind() == reflect.Ptr v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) b, err := v.(Marshaler).MarshalJSON() @@ -3741,19 +3477,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c 0, ) } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeBytes([]byte{'"', '"'}) - code = field.nextField + code = code.nextField } else { var buf bytes.Buffer if err := compact(&buf, b, true); err != nil { return err } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(buf.String()) - code = field.next + code = code.next } - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagMarshalText: ptr := load(ctxptr, code.idx) @@ -3762,14 +3497,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeByte('{') - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -3778,10 +3512,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Err: err, } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrAnonymousHeadStringTagMarshalText: ptr := load(ctxptr, code.idx) @@ -3790,12 +3523,11 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldAnonymousHeadStringTagMarshalText: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { - code = field.end.next + code = code.end.next } else { - p := unsafe.Pointer(ptr + field.offset) + p := unsafe.Pointer(ptr + code.offset) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) bytes, err := v.(encoding.TextMarshaler).MarshalText() if err != nil { @@ -3804,10 +3536,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c Err: err, } } - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeString(*(*string)(unsafe.Pointer(&bytes))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrHeadStringTagIndent: ptr := load(ctxptr, code.idx) @@ -3816,21 +3547,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) - p := ptr + field.offset + p := ptr + code.offset e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - code = field.next + code = code.next store(ctxptr, code.idx, p) - store(ctxptr, field.nextField.idx, ptr) } case opStructFieldPtrHeadStringTagIntIndent: ptr := load(ctxptr, code.idx) @@ -3839,20 +3568,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagIntIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt8Indent: ptr := load(ctxptr, code.idx) @@ -3861,20 +3588,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt16Indent: ptr := load(ctxptr, code.idx) @@ -3883,20 +3608,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt32Indent: ptr := load(ctxptr, code.idx) @@ -3905,20 +3628,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagInt64Indent: ptr := load(ctxptr, code.idx) @@ -3927,20 +3648,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagInt64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUintIndent: ptr := load(ctxptr, code.idx) @@ -3949,20 +3668,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUintIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint8Indent: ptr := load(ctxptr, code.idx) @@ -3971,20 +3688,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint8Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint16Indent: ptr := load(ctxptr, code.idx) @@ -3993,20 +3708,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint16Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint32Indent: ptr := load(ctxptr, code.idx) @@ -4015,20 +3728,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagUint64Indent: ptr := load(ctxptr, code.idx) @@ -4037,20 +3748,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagUint64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagFloat32Indent: ptr := load(ctxptr, code.idx) @@ -4059,20 +3768,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagFloat32Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagFloat64Indent: ptr := load(ctxptr, code.idx) @@ -4081,15 +3788,14 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagFloat64Indent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) - v := e.ptrToFloat64(ptr + field.offset) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -4097,11 +3803,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } } e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeString(fmt.Sprint(v)) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructFieldPtrHeadStringTagStringIndent: ptr := load(ctxptr, code.idx) @@ -4110,20 +3815,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagStringIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(strconv.Quote(e.ptrToString(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(strconv.Quote(e.ptrToString(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagBoolIndent: ptr := load(ctxptr, code.idx) @@ -4132,20 +3835,18 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagBoolIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToBool(ptr + field.offset))) - code = field.next - store(ctxptr, field.nextField.idx, ptr) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + code.offset))) + code = code.next } case opStructFieldPtrHeadStringTagBytesIndent: ptr := load(ctxptr, code.idx) @@ -4154,157 +3855,129 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } fallthrough case opStructFieldHeadStringTagBytesIndent: - field := code.toStructFieldCode() ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = field.end.next + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) - e.encodeBytes(field.key) + e.encodeBytes(code.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + field.offset), + e.ptrToBytes(ptr + code.offset), ) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') - code = field.next - store(ctxptr, field.nextField.idx, ptr) + code = code.next } case opStructField: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - if !c.anonymousKey { - e.encodeBytes(c.key) + if !code.anonymousKey { + e.encodeBytes(code.key) } + ptr := load(ctxptr, code.headIdx) + code.offset code = code.next - ptr := load(ctxptr, c.idx) - store(ctxptr, code.idx, ptr+c.offset) - store(ctxptr, c.nextField.idx, ptr) + store(ctxptr, code.idx, ptr) case opStructFieldInt: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeInt(e.ptrToInt(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeInt(e.ptrToInt(ptr + code.offset)) code = code.next case opStructFieldInt8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeInt8(e.ptrToInt8(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeInt8(e.ptrToInt8(ptr + code.offset)) code = code.next case opStructFieldInt16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeInt16(e.ptrToInt16(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeInt16(e.ptrToInt16(ptr + code.offset)) code = code.next case opStructFieldInt32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeInt32(e.ptrToInt32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeInt32(e.ptrToInt32(ptr + code.offset)) code = code.next case opStructFieldInt64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeInt64(e.ptrToInt64(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeInt64(e.ptrToInt64(ptr + code.offset)) code = code.next case opStructFieldUint: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeUint(e.ptrToUint(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeUint(e.ptrToUint(ptr + code.offset)) code = code.next case opStructFieldUint8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeUint8(e.ptrToUint8(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeUint8(e.ptrToUint8(ptr + code.offset)) code = code.next case opStructFieldUint16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeUint16(e.ptrToUint16(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeUint16(e.ptrToUint16(ptr + code.offset)) code = code.next case opStructFieldUint32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeUint32(e.ptrToUint32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeUint32(e.ptrToUint32(ptr + code.offset)) code = code.next case opStructFieldUint64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeUint64(e.ptrToUint64(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeUint64(e.ptrToUint64(ptr + code.offset)) code = code.next case opStructFieldFloat32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeFloat32(e.ptrToFloat32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) code = code.next case opStructFieldFloat64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -4317,31 +3990,25 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeString(e.ptrToString(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeString(e.ptrToString(ptr + code.offset)) code = code.next case opStructFieldBool: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - e.encodeBool(e.ptrToBool(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + e.encodeBool(e.ptrToBool(ptr + code.offset)) code = code.next case opStructFieldBytes: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') @@ -4350,11 +4017,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -4376,11 +4041,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) - e.encodeBytes(c.key) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + e.encodeBytes(code.key) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -4398,206 +4061,171 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) + e.encodeBytes(code.key) + ptr := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, ptr+c.offset) - e.encodeBytes(c.key) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldSlice: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - store(ctxptr, c.nextField.idx, ptr) + e.encodeBytes(code.key) + ptr := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, ptr+c.offset) - e.encodeBytes(c.key) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldMap: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - e.encodeBytes(c.key) + e.encodeBytes(code.key) + ptr := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, ptr+c.offset) - store(ctxptr, c.nextField.idx, ptr) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldMapLoad: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - e.encodeBytes(c.key) + e.encodeBytes(code.key) + ptr := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, ptr+c.offset) - store(ctxptr, c.nextField.idx, ptr) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldStruct: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - e.encodeBytes(c.key) + e.encodeBytes(code.key) + ptr := load(ctxptr, code.headIdx) code = code.next - store(ctxptr, code.idx, ptr+c.offset) - store(ctxptr, c.nextField.idx, ptr) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') + ptr := load(ctxptr, code.headIdx) code = code.next - ptr := load(ctxptr, c.idx) - store(ctxptr, code.idx, ptr+c.offset) - store(ctxptr, c.nextField.idx, ptr) + store(ctxptr, code.idx, ptr+code.offset) case opStructFieldIntIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeInt(e.ptrToInt(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeInt(e.ptrToInt(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt8Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeInt8(e.ptrToInt8(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeInt8(e.ptrToInt8(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt16Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeInt16(e.ptrToInt16(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeInt16(e.ptrToInt16(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt32Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeInt32(e.ptrToInt32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeInt32(e.ptrToInt32(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldInt64Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeInt64(e.ptrToInt64(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeInt64(e.ptrToInt64(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldUintIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeUint(e.ptrToUint(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeUint(e.ptrToUint(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint8Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeUint8(e.ptrToUint8(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeUint8(e.ptrToUint8(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint16Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeUint16(e.ptrToUint16(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeUint16(e.ptrToUint16(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint32Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeUint32(e.ptrToUint32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeUint32(e.ptrToUint32(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldUint64Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeUint64(e.ptrToUint64(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeUint64(e.ptrToUint64(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldFloat32Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeFloat32(e.ptrToFloat32(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldFloat64Indent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -4606,56 +4234,48 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeFloat64(v) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeString(e.ptrToString(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeString(e.ptrToString(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldBoolIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - e.encodeBool(e.ptrToBool(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + e.encodeBool(e.ptrToBool(ptr + code.offset)) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldBytesIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + c.offset)) + ptr := load(ctxptr, code.headIdx) + s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldMarshalJSONIndent: - c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeByte(',') } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -4673,279 +4293,242 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeBytes(buf.Bytes()) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructFieldArrayIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - c := code.toStructFieldCode() - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { e.encodeNull() - code = c.nextField + code = code.nextField } else { code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldSliceIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - c := code.toStructFieldCode() - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { e.encodeNull() - code = c.nextField + code = code.nextField } else { code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldMapIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - c := code.toStructFieldCode() - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { e.encodeNull() - code = c.nextField + code = code.nextField } else { mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { e.encodeBytes([]byte{'{', '}'}) mapCode := code.next - mapHeadCode := mapCode.toMapHeadCode() - code = mapHeadCode.end.next + code = mapCode.end.next } else { code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldMapLoadIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - c := code.toStructFieldCode() - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { e.encodeNull() - code = c.nextField + code = code.nextField } else { p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { e.encodeBytes([]byte{'{', '}'}) - code = c.nextField + code = code.nextField } else { code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldStructIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') if p == 0 { e.encodeBytes([]byte{'{', '}'}) - code = c.nextField + code = code.nextField } else { - headCode := c.next.toStructFieldCode() + headCode := code.next if headCode.next == headCode.end { // not exists fields e.encodeBytes([]byte{'{', '}'}) - code = c.nextField + code = code.nextField } else { code = code.next store(ctxptr, code.idx, p) } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmpty: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) code = code.next store(ctxptr, code.idx, p) } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyInt: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeInt(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt8: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt8(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt8(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeInt8(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt16: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt16(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt16(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeInt16(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeInt32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt64(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeInt64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeUint(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint8: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint8(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint8(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeUint8(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint16: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint16(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint16(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeUint16(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeUint32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint64(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeUint64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeFloat32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat64(ptr + code.offset) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -4956,57 +4539,49 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeFloat64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyString: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToString(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToString(ptr + code.offset) if v != "" { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeString(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBool: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToBool(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToBool(ptr + code.offset) if v { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeBool(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBytes: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToBytes(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToBytes(ptr + code.offset) if len(v) > 0 { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyMarshalJSON: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5026,11 +4601,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeBytes(buf.Bytes()) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyMarshalText: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5050,45 +4623,39 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeString(*(*string)(unsafe.Pointer(&bytes))) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyArray: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptySlice: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMap: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { - code = c.nextField + code = code.nextField } else { mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -5096,18 +4663,16 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapLoad: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { - code = c.nextField + code = code.nextField } else { p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -5115,193 +4680,167 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next store(ctxptr, code.idx, p) } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyIntIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt8Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt8(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt8(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt8(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt16Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt16(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt16(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt16(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyInt64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToInt64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt64(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeInt64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUintIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint8Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint8(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint8(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint8(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint16Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint16(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint16(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint16(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyUint64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToUint64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToUint64(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeUint64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat32(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat32(ptr + code.offset) if v != 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat32(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyFloat64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat64(ptr + code.offset) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ @@ -5312,53 +4851,47 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeFloat64(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyStringIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToString(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToString(ptr + code.offset) if v != "" { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeString(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBoolIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToBool(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToBool(ptr + code.offset) if v { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeBool(v) } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyBytesIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToBytes(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToBytes(ptr + code.offset) if len(v) > 0 { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') @@ -5366,233 +4899,197 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeByte('"') } code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldOmitEmptyArrayIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptySliceIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset header := (*reflect.SliceHeader)(unsafe.Pointer(p)) if p == 0 || header.Data == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { - code = c.nextField + code = code.nextField } else { mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyMapLoadIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { - code = c.nextField + code = code.nextField } else { p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) mlen := maplen(unsafe.Pointer(p)) if mlen == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldOmitEmptyStructIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if p == 0 { - code = c.nextField + code = code.nextField } else { if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - headCode := c.next.toStructFieldCode() + headCode := code.next if headCode.next == headCode.end { // not exists fields e.encodeBytes([]byte{'{', '}'}) - code = c.nextField + code = code.nextField } else { code = code.next store(ctxptr, code.idx, p) } } - store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTag: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) code = code.next store(ctxptr, code.idx, p) - store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTagInt: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt8: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt16: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint8: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint16: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat32: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat64: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -5602,48 +5099,40 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) e.encodeString(fmt.Sprint(v)) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagString: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(strconv.Quote(e.ptrToString(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(strconv.Quote(e.ptrToString(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagBool: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) - e.encodeString(fmt.Sprint(e.ptrToBool(ptr + c.offset))) + e.encodeBytes(code.key) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagBytes: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToBytes(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToBytes(ptr + code.offset) if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } - e.encodeBytes(c.key) + e.encodeBytes(code.key) s := base64.StdEncoding.EncodeToString(v) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalJSON: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5661,11 +5150,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeString(buf.String()) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalText: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5679,156 +5166,130 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - p := ptr + c.offset + ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') code = code.next store(ctxptr, code.idx, p) - store(ctxptr, c.nextField.idx, ptr) case opStructFieldStringTagIntIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt8Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt8(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt16Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt16(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagInt64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToInt64(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUintIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint8Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint8(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint16Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint16(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagUint64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToUint64(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat32Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToFloat32(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagFloat64Indent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) - v := e.ptrToFloat64(ptr + c.offset) + ptr := load(ctxptr, code.headIdx) + v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { return &UnsupportedValueError{ Value: reflect.ValueOf(v), @@ -5838,67 +5299,59 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') e.encodeString(fmt.Sprint(v)) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagStringIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') var b bytes.Buffer enc := NewEncoder(&b) - enc.encodeString(e.ptrToString(ptr + c.offset)) + enc.encodeString(e.ptrToString(ptr + code.offset)) e.encodeString(string(enc.buf)) enc.release() code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagBoolIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - e.encodeString(fmt.Sprint(e.ptrToBool(ptr + c.offset))) + e.encodeString(fmt.Sprint(e.ptrToBool(ptr + code.offset))) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagBytesIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + c.offset), + e.ptrToBytes(ptr + code.offset), ) e.encodeByte('"') e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) e.encodeByte('"') code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalJSONIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - p := ptr + c.offset + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5916,17 +5369,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeString(buf.String()) code = code.next - store(ctxptr, code.idx, ptr) case opStructFieldStringTagMarshalTextIndent: - c := code.toStructFieldCode() - ptr := load(ctxptr, c.idx) + ptr := load(ctxptr, code.headIdx) if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) } - e.encodeIndent(c.indent) - e.encodeBytes(c.key) + e.encodeIndent(code.indent) + e.encodeBytes(code.key) e.encodeByte(' ') - p := ptr + c.offset + p := ptr + code.offset v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(p), @@ -5940,7 +5391,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next - store(ctxptr, c.nextField.idx, ptr) case opStructEnd: e.encodeByte('}') code = code.next From 3aa921e884337420ac422fafb9ad387083e6f00a Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Tue, 1 Sep 2020 22:26:26 +0900 Subject: [PATCH 09/18] Fix encoding engine --- encode.go | 4 +- encode_compile.go | 95 ++++++++++++++-------------- encode_context.go | 26 +++++++- encode_opcode.go | 153 +++++++++++++++++++++++++++++++++++++--------- encode_vm.go | 96 +++++++++++++++++------------ json_test.go | 10 +-- 6 files changed, 263 insertions(+), 121 deletions(-) diff --git a/encode.go b/encode.go index e9f2c48..4ca7216 100644 --- a/encode.go +++ b/encode.go @@ -166,7 +166,7 @@ func (e *Encoder) encode(v interface{}) error { p := uintptr(header.ptr) ctx.init(p) seenPtr := map[uintptr]struct{}{} - err := e.run(ctx, seenPtr, code) + err := e.run(ctx, 0, seenPtr, code) if e.enabledIndent { codeSet.codeIndent.Put(code) } else { @@ -228,7 +228,7 @@ func (e *Encoder) encode(v interface{}) error { } seenPtr := map[uintptr]struct{}{} - if err := e.run(ctx, seenPtr, c); err != nil { + if err := e.run(ctx, 0, seenPtr, c); err != nil { codeSet.ctx.Put(ctx) return err } diff --git a/encode_compile.go b/encode_compile.go index ff1124e..54819df 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -133,7 +133,7 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { ptrOpcodeIndex := ctx.opcodeIndex - ctx.incOpcodeIndex() + ctx.incIndex() code, err := e.compile(ctx.withType(ctx.typ.Elem())) if err != nil { return nil, err @@ -142,7 +142,7 @@ func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { if code.op != ptrHeadOp { code.op = ptrHeadOp code.decOpcodeIndex() - ctx.decOpcodeIndex() + ctx.decIndex() return code, nil } c := ctx.context() @@ -152,121 +152,121 @@ func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileMarshalJSON(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opMarshalJSON) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileMarshalJSONPtr(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalJSON) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileMarshalText(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opMarshalText) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileMarshalTextPtr(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalText) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInt(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opInt) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInt8(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opInt8) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInt16(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opInt16) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInt32(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opInt32) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInt64(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opInt64) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileUint(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opUint) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileUint8(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opUint8) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileUint16(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opUint16) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileUint32(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opUint32) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opUint64) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opFloat32) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileFloat64(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opFloat64) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileString(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opString) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileBool(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opBool) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { code := newOpCode(ctx, opBytes) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { code := newInterfaceCode(ctx) - ctx.incOpcodeIndex() + ctx.incIndex() return code, nil } @@ -276,7 +276,7 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { size := elem.Size() header := newSliceHeaderCode(ctx) - ctx.incOpcodeIndex() + ctx.incIndex() code, err := e.compile(ctx.withType(ctx.typ.Elem()).incIndent()) if err != nil { @@ -287,11 +287,11 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - elemCode := newSliceElemCode(ctx, size) - ctx.incOpcodeIndex() + elemCode := newSliceElemCode(ctx, header, size) + ctx.incIndex() end := newOpCode(ctx, opSliceEnd) - ctx.incOpcodeIndex() + ctx.incIndex() if ctx.withIndent { if ctx.root { header.op = opRootSliceHeadIndent @@ -320,7 +320,7 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { size := elem.Size() header := newArrayHeaderCode(ctx, alen) - ctx.incOpcodeIndex() + ctx.incIndex() code, err := e.compile(ctx.withType(elem).incIndent()) if err != nil { @@ -330,11 +330,11 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { // ^ | // |________| - elemCode := newArrayElemCode(ctx, alen, size) - ctx.incOpcodeIndex() + elemCode := newArrayElemCode(ctx, header, alen, size) + ctx.incIndex() end := newOpCode(ctx, opArrayEnd) - ctx.incOpcodeIndex() + ctx.incIndex() if ctx.withIndent { header.op = opArrayHeadIndent @@ -373,7 +373,7 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, // |_______________________| ctx = ctx.incIndent() header := newMapHeaderCode(ctx, withLoad) - ctx.incOpcodeIndex() + ctx.incIndex() typ := ctx.typ keyType := ctx.typ.Key() @@ -382,8 +382,8 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, return nil, err } - value := newMapValueCode(ctx) - ctx.incOpcodeIndex() + value := newMapValueCode(ctx, header) + ctx.incIndex() valueType := typ.Elem() valueCode, err := e.compile(ctx.withType(valueType)) @@ -391,15 +391,15 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, return nil, err } - key := newMapKeyCode(ctx) - ctx.incOpcodeIndex() + key := newMapKeyCode(ctx, header) + ctx.incIndex() ctx = ctx.decIndent() header.mapKey = key header.mapValue = value end := newOpCode(ctx, opMapEnd) - ctx.incOpcodeIndex() + ctx.incIndex() if ctx.withIndent { if header.op == opMapHead { @@ -578,7 +578,7 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool func (e *Encoder) recursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode { code := newRecursiveCode(ctx, jmp) - ctx.incOpcodeIndex() + ctx.incIndex() return code } @@ -667,7 +667,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu opStructFieldStringTagIndent: return valueCode.beforeLastCode() } - ctx.decOpcodeIndex() + ctx.decIndex() return code } @@ -876,7 +876,8 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } } fieldOpcodeIndex := ctx.opcodeIndex - ctx.incOpcodeIndex() + fieldPtrIndex := ctx.ptrIndex + ctx.incIndex() valueCode, err := e.compile(ctx.withType(fieldType)) if err != nil { return nil, err @@ -902,7 +903,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, fieldCode := &opcode{ typ: valueCode.typ, displayIdx: fieldOpcodeIndex, - idx: opcodeOffset(fieldOpcodeIndex), + idx: opcodeOffset(fieldPtrIndex), next: valueCode, indent: ctx.indent, anonymousKey: field.Anonymous, @@ -912,14 +913,15 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, offset: field.Offset, } if fieldIdx == 0 { + fieldCode.headIdx = fieldCode.idx code = e.structHeader(ctx, fieldCode, valueCode, tag) head = fieldCode prevField = fieldCode } else { - fcode := (*opcode)(unsafe.Pointer(fieldCode)) - code.next = fcode + fieldCode.headIdx = head.headIdx + code.next = fieldCode code = e.structField(ctx, fieldCode, valueCode, tag) - prevField.nextField = fcode + prevField.nextField = fieldCode prevField = fieldCode } fieldIdx++ @@ -939,11 +941,12 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, op: opStructFieldHead, typ: typ, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), + headIdx: opcodeOffset(ctx.ptrIndex), indent: ctx.indent, nextField: structEndCode, } - ctx.incOpcodeIndex() + ctx.incIndex() if ctx.withIndent { head.op = opStructFieldHeadIndent } @@ -952,7 +955,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, structEndCode.displayIdx = ctx.opcodeIndex structEndCode.idx = opcodeOffset(ctx.opcodeIndex) - ctx.incOpcodeIndex() + ctx.incIndex() if ctx.withIndent { structEndCode.op = opStructEndIndent diff --git a/encode_context.go b/encode_context.go index a36ddec..0b30e45 100644 --- a/encode_context.go +++ b/encode_context.go @@ -46,9 +46,18 @@ func (c *encodeCompileContext) decIndent() *encodeCompileContext { return ctx } +func (c *encodeCompileContext) incIndex() { + c.incOpcodeIndex() + c.incPtrIndex() +} + +func (c *encodeCompileContext) decIndex() { + c.decOpcodeIndex() + c.decPtrIndex() +} + func (c *encodeCompileContext) incOpcodeIndex() { c.opcodeIndex++ - c.ptrIndex++ if c.parent != nil { c.parent.incOpcodeIndex() } @@ -56,12 +65,25 @@ func (c *encodeCompileContext) incOpcodeIndex() { func (c *encodeCompileContext) decOpcodeIndex() { c.opcodeIndex-- - c.ptrIndex-- if c.parent != nil { c.parent.decOpcodeIndex() } } +func (c *encodeCompileContext) incPtrIndex() { + c.ptrIndex++ + if c.parent != nil { + c.parent.incPtrIndex() + } +} + +func (c *encodeCompileContext) decPtrIndex() { + c.ptrIndex-- + if c.parent != nil { + c.parent.decPtrIndex() + } +} + type encodeRuntimeContext struct { ptrs []uintptr } diff --git a/encode_opcode.go b/encode_opcode.go index bc1fe9f..9ff35ba 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -50,7 +50,7 @@ func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opco typ: ctx.typ, displayIdx: ctx.opcodeIndex, indent: ctx.indent, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), next: next, } } @@ -94,7 +94,7 @@ func (c *opcode) totalLength() int { func (c *opcode) decOpcodeIndex() { for code := c; code.op != opEnd; { code.displayIdx-- - code.idx -= 8 + code.idx -= uintptrSize switch code.op.codeType() { case codeArrayElem, codeSliceElem, codeMapKey: code = code.end @@ -104,40 +104,93 @@ func (c *opcode) decOpcodeIndex() { } } -func (c *opcode) dumpElem(code *opcode) string { +func (c *opcode) dumpHead(code *opcode) string { + var length uintptr + if code.op.codeType() == codeArrayElem { + length = code.length + } else { + length = code.length / uintptrSize + } return fmt.Sprintf( - `[%d]%s%s ([headIdx:%d][elemIdx:%d][length:%d][size:%d])`, + `[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d])`, code.displayIdx, strings.Repeat("-", code.indent), code.op, - code.headIdx, - code.elemIdx, - code.length, + code.idx/uintptrSize, + code.headIdx/uintptrSize, + code.elemIdx/uintptrSize, + length, + ) +} + +func (c *opcode) dumpMapHead(code *opcode) string { + return fmt.Sprintf( + `[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][mapIter:%d])`, + code.displayIdx, + strings.Repeat("-", code.indent), + code.op, + code.idx/uintptrSize, + code.headIdx/uintptrSize, + code.elemIdx/uintptrSize, + code.length/uintptrSize, + code.mapIter/uintptrSize, + ) +} + +func (c *opcode) dumpElem(code *opcode) string { + var length uintptr + if code.op.codeType() == codeArrayElem { + length = code.length + } else { + length = code.length / uintptrSize + } + return fmt.Sprintf( + `[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][size:%d])`, + code.displayIdx, + strings.Repeat("-", code.indent), + code.op, + code.idx/uintptrSize, + code.headIdx/uintptrSize, + code.elemIdx/uintptrSize, + length, code.size, ) } func (c *opcode) dumpField(code *opcode) string { return fmt.Sprintf( - `[%d]%s%s ([key:%s][offset:%d][headIdx:%d])`, + `[%d]%s%s ([idx:%d][key:%s][offset:%d][headIdx:%d])`, code.displayIdx, strings.Repeat("-", code.indent), code.op, + code.idx/uintptrSize, code.displayKey, code.offset, - code.headIdx, + code.headIdx/uintptrSize, ) } func (c *opcode) dumpKey(code *opcode) string { return fmt.Sprintf( - `[%d]%s%s ([elemIdx:%d][length:%d][mapIter:%d])`, + `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, code.displayIdx, strings.Repeat("-", code.indent), code.op, - code.elemIdx, - code.length, - code.mapIter, + code.idx/uintptrSize, + code.elemIdx/uintptrSize, + code.length/uintptrSize, + code.mapIter/uintptrSize, + ) +} + +func (c *opcode) dumpValue(code *opcode) string { + return fmt.Sprintf( + `[%d]%s%s ([idx:%d][mapIter:%d])`, + code.displayIdx, + strings.Repeat("-", code.indent), + code.op, + code.idx/uintptrSize, + code.mapIter/uintptrSize, ) } @@ -145,21 +198,31 @@ func (c *opcode) dump() string { codes := []string{} for code := c; code.op != opEnd; { switch code.op.codeType() { + case codeSliceHead: + codes = append(codes, c.dumpHead(code)) + code = code.next + case codeMapHead: + codes = append(codes, c.dumpMapHead(code)) + code = code.next case codeArrayElem, codeSliceElem: codes = append(codes, c.dumpElem(code)) code = code.end case codeMapKey: codes = append(codes, c.dumpKey(code)) code = code.end + case codeMapValue: + codes = append(codes, c.dumpValue(code)) + code = code.next case codeStructField: codes = append(codes, c.dumpField(code)) code = code.next default: codes = append(codes, fmt.Sprintf( - "[%d]%s%s", + "[%d]%s%s ([idx:%d])", code.displayIdx, strings.Repeat("-", code.indent), code.op, + code.idx/uintptrSize, )) code = code.next } @@ -190,40 +253,58 @@ func linkPrevToNextField(prev, cur *opcode) { } func newSliceHeaderCode(ctx *encodeCompileContext) *opcode { + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + elemIdx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + length := opcodeOffset(ctx.ptrIndex) return &opcode{ op: opSliceHead, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: idx, + headIdx: idx, + elemIdx: elemIdx, + length: length, indent: ctx.indent, } } -func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *opcode { +func newSliceElemCode(ctx *encodeCompileContext, head *opcode, size uintptr) *opcode { return &opcode{ op: opSliceElem, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), + headIdx: head.idx, + elemIdx: head.elemIdx, + length: head.length, indent: ctx.indent, size: size, } } func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *opcode { + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + elemIdx := opcodeOffset(ctx.ptrIndex) return &opcode{ op: opArrayHead, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: idx, + headIdx: idx, + elemIdx: elemIdx, indent: ctx.indent, length: uintptr(alen), } } -func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *opcode { +func newArrayElemCode(ctx *encodeCompileContext, head *opcode, length int, size uintptr) *opcode { return &opcode{ op: opArrayElem, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), - length: uintptr(alen), + idx: opcodeOffset(ctx.ptrIndex), + elemIdx: head.elemIdx, + headIdx: head.headIdx, + length: uintptr(length), size: size, } } @@ -235,29 +316,45 @@ func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *opcode { } else { op = opMapHead } + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + elemIdx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + length := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + mapIter := opcodeOffset(ctx.ptrIndex) return &opcode{ op: op, typ: ctx.typ, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: idx, + elemIdx: elemIdx, + length: length, + mapIter: mapIter, indent: ctx.indent, } } -func newMapKeyCode(ctx *encodeCompileContext) *opcode { +func newMapKeyCode(ctx *encodeCompileContext, head *opcode) *opcode { return &opcode{ op: opMapKey, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), + elemIdx: head.elemIdx, + length: head.length, + mapIter: head.mapIter, indent: ctx.indent, } } -func newMapValueCode(ctx *encodeCompileContext) *opcode { +func newMapValueCode(ctx *encodeCompileContext, head *opcode) *opcode { return &opcode{ op: opMapValue, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), + elemIdx: head.elemIdx, + length: head.length, + mapIter: head.mapIter, indent: ctx.indent, } } @@ -267,7 +364,7 @@ func newInterfaceCode(ctx *encodeCompileContext) *opcode { op: opInterface, typ: ctx.typ, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), indent: ctx.indent, next: newEndOp(ctx), root: ctx.root, @@ -279,7 +376,7 @@ func newRecursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode { op: opStructFieldRecursive, typ: ctx.typ, displayIdx: ctx.opcodeIndex, - idx: opcodeOffset(ctx.opcodeIndex), + idx: opcodeOffset(ctx.ptrIndex), indent: ctx.indent, next: newEndOp(ctx), jmp: jmp, diff --git a/encode_vm.go b/encode_vm.go index 409a60c..81b9750 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -11,6 +11,8 @@ import ( "unsafe" ) +const startDetectingCyclesAfter = 1000 + func load(base uintptr, idx uintptr) uintptr { return *(*uintptr)(unsafe.Pointer(base + idx)) } @@ -19,7 +21,7 @@ func store(base uintptr, idx uintptr, p uintptr) { *(*uintptr)(unsafe.Pointer(base + idx)) = p } -func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, code *opcode) error { +func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map[uintptr]struct{}, code *opcode) error { ctxptr := ctx.ptr() for { switch code.op { @@ -144,7 +146,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c ptrs: make([]uintptr, c.totalLength()), } ctx.init(uintptr(header.ptr)) - if err := e.run(ctx, seenPtr, c); err != nil { + if err := e.run(ctx, recursiveLevel+1, seenPtr, c); err != nil { return err } code = code.next @@ -236,9 +238,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if idx < length { e.encodeByte(',') store(ctxptr, code.elemIdx, idx) - code = code.next data := load(ctxptr, code.headIdx) - store(ctxptr, code.idx, data+idx*code.size) + size := code.size + code = code.next + store(ctxptr, code.idx, data+idx*size) } else { e.encodeByte(']') code = code.end.next @@ -295,9 +298,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeBytes([]byte{',', '\n'}) e.encodeIndent(code.indent + 1) store(ctxptr, code.elemIdx, idx) - code = code.next data := load(ctxptr, code.headIdx) - store(ctxptr, code.idx, data+idx*code.size) + size := code.size + code = code.next + store(ctxptr, code.idx, data+idx*size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) @@ -329,6 +333,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } else { e.encodeByte('[') if code.length > 0 { + store(ctxptr, code.elemIdx, 0) code = code.next store(ctxptr, code.idx, p) } else { @@ -343,8 +348,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeByte(',') store(ctxptr, code.elemIdx, idx) p := load(ctxptr, code.headIdx) + size := code.size code = code.next - store(ctxptr, code.idx, p+idx*code.size) + store(ctxptr, code.idx, p+idx*size) } else { e.encodeByte(']') code = code.end.next @@ -359,6 +365,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeBytes([]byte{'[', '\n'}) if code.length > 0 { e.encodeIndent(code.indent + 1) + store(ctxptr, code.elemIdx, 0) code = code.next store(ctxptr, code.idx, p) } else { @@ -375,8 +382,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeIndent(code.indent + 1) store(ctxptr, code.elemIdx, idx) p := load(ctxptr, code.headIdx) + size := code.size code = code.next - store(ctxptr, code.idx, p+idx*code.size) + store(ctxptr, code.idx, p+idx*size) } else { e.encodeByte('\n') e.encodeIndent(code.indent) @@ -393,9 +401,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - store(ctxptr, code.mapKey.length, uintptr(mlen)) - store(ctxptr, code.mapKey.mapIter, uintptr(iter)) - store(ctxptr, code.mapValue.mapIter, uintptr(iter)) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(mlen)) + store(ctxptr, code.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -416,9 +424,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - store(ctxptr, code.mapKey.length, uintptr(mlen)) - store(ctxptr, code.mapKey.mapIter, uintptr(iter)) - store(ctxptr, code.mapValue.mapIter, uintptr(iter)) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(mlen)) + store(ctxptr, code.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -460,9 +468,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - store(ctxptr, code.mapKey.length, uintptr(mlen)) - store(ctxptr, code.mapKey.mapIter, uintptr(iter)) - store(ctxptr, code.mapValue.mapIter, uintptr(iter)) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(mlen)) + store(ctxptr, code.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -486,9 +494,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - store(ctxptr, code.mapKey.length, uintptr(mlen)) - store(ctxptr, code.mapKey.mapIter, uintptr(iter)) - store(ctxptr, code.mapValue.mapIter, uintptr(iter)) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(mlen)) + store(ctxptr, code.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -510,9 +518,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - store(ctxptr, code.mapKey.length, uintptr(mlen)) - store(ctxptr, code.mapKey.mapIter, uintptr(iter)) - store(ctxptr, code.mapValue.mapIter, uintptr(iter)) + store(ctxptr, code.elemIdx, 0) + store(ctxptr, code.length, uintptr(mlen)) + store(ctxptr, code.mapIter, uintptr(iter)) key := mapiterkey(iter) store(ctxptr, code.next.idx, uintptr(key)) code = code.next @@ -569,17 +577,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c case opStructFieldRecursive: ptr := load(ctxptr, code.idx) if ptr != 0 { - if _, exists := seenPtr[ptr]; exists { - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ - typ: code.typ, - ptr: unsafe.Pointer(ptr), - })) - return &UnsupportedValueError{ - Value: reflect.ValueOf(v), - Str: fmt.Sprintf("encountered a cycle via %s", code.typ), + if recursiveLevel > startDetectingCyclesAfter { + if _, exists := seenPtr[ptr]; exists { + v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + typ: code.typ, + ptr: unsafe.Pointer(ptr), + })) + return &UnsupportedValueError{ + Value: reflect.ValueOf(v), + Str: fmt.Sprintf("encountered a cycle via %s", code.typ), + } } } } + seenPtr[ptr] = struct{}{} c := *(code.jmp.code) ctx := &encodeRuntimeContext{ ptrs: make([]uintptr, c.totalLength()), @@ -587,7 +598,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c ctx.init(ptr) c.end.next = newEndOp(&encodeCompileContext{}) c.op = c.op.ptrHeadToHead() - if err := e.run(ctx, seenPtr, &c); err != nil { + if err := e.run(ctx, recursiveLevel+1, seenPtr, &c); err != nil { return err } code = code.next @@ -611,8 +622,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c if !code.anonymousKey { e.encodeBytes(code.key) } + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) } case opStructFieldAnonymousHead: ptr := load(ctxptr, code.idx) @@ -4063,40 +4075,45 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c } e.encodeBytes(code.key) ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldSlice: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(code.key) ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldMap: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(code.key) ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldMapLoad: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(code.key) ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldStruct: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') } e.encodeBytes(code.key) ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) @@ -4105,8 +4122,9 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, c e.encodeBytes(code.key) e.encodeByte(' ') ptr := load(ctxptr, code.headIdx) + p := ptr + code.offset code = code.next - store(ctxptr, code.idx, ptr+code.offset) + store(ctxptr, code.idx, p) case opStructFieldIntIndent: if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { e.encodeBytes([]byte{',', '\n'}) diff --git a/json_test.go b/json_test.go index 3831777..bb25fce 100644 --- a/json_test.go +++ b/json_test.go @@ -121,7 +121,6 @@ func TestIndent(t *testing.T) { } // Tests of a large random structure. - func TestCompactBig(t *testing.T) { initBig() var buf bytes.Buffer @@ -221,7 +220,10 @@ func trim(b []byte) []byte { // Generate a random JSON object. -var jsonBig []byte +var ( + jsonBig []byte + jsonVal interface{} +) func initBig() { if len(jsonBig) > 0 { @@ -231,8 +233,8 @@ func initBig() { if testing.Short() { n = 100 } - v := genValue(n) - b, err := json.Marshal(v) + jsonVal = genValue(n) + b, err := json.Marshal(jsonVal) if err != nil { panic(err) } From 18a6e4cffe09fc4ef9c5b2c8fda8a430159fb641 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Tue, 1 Sep 2020 22:39:20 +0900 Subject: [PATCH 10/18] Remove codePool --- encode.go | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/encode.go b/encode.go index 4ca7216..6297a1a 100644 --- a/encode.go +++ b/encode.go @@ -36,8 +36,8 @@ type opcodeMap struct { } type opcodeSet struct { - codeIndent sync.Pool - code sync.Pool + codeIndent *opcode + code *opcode ctx sync.Pool } @@ -158,20 +158,15 @@ func (e *Encoder) encode(v interface{}) error { if codeSet := cachedOpcode.get(typeptr); codeSet != nil { var code *opcode if e.enabledIndent { - code = codeSet.codeIndent.Get().(*opcode) + code = codeSet.codeIndent } else { - code = codeSet.code.Get().(*opcode) + code = codeSet.code } ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) ctx.init(p) seenPtr := map[uintptr]struct{}{} err := e.run(ctx, 0, seenPtr, code) - if e.enabledIndent { - codeSet.codeIndent.Put(code) - } else { - codeSet.code.Put(code) - } codeSet.ctx.Put(ctx) return err } @@ -197,16 +192,8 @@ func (e *Encoder) encode(v interface{}) error { } codeLength := code.totalLength() codeSet := &opcodeSet{ - codeIndent: sync.Pool{ - New: func() interface{} { - return codeIndent - }, - }, - code: sync.Pool{ - New: func() interface{} { - return code - }, - }, + codeIndent: codeIndent, + code: code, ctx: sync.Pool{ New: func() interface{} { return &encodeRuntimeContext{ From 4f4060f8081e81d14ddd5453734c9ae1de3343c6 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Tue, 1 Sep 2020 23:23:07 +0900 Subject: [PATCH 11/18] Fix index number --- encode_compile.go | 2 +- encode_opcode.go | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/encode_compile.go b/encode_compile.go index 54819df..fcbb05d 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -954,7 +954,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } structEndCode.displayIdx = ctx.opcodeIndex - structEndCode.idx = opcodeOffset(ctx.opcodeIndex) + structEndCode.idx = opcodeOffset(ctx.ptrIndex) ctx.incIndex() if ctx.withIndent { diff --git a/encode_opcode.go b/encode_opcode.go index 9ff35ba..a3d9e1a 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -95,6 +95,18 @@ func (c *opcode) decOpcodeIndex() { for code := c; code.op != opEnd; { code.displayIdx-- code.idx -= uintptrSize + if code.headIdx > 0 { + code.headIdx -= uintptrSize + } + if code.elemIdx > 0 { + code.elemIdx -= uintptrSize + } + if code.mapIter > 0 { + code.mapIter -= uintptrSize + } + if code.length > 0 && code.op.codeType() != codeArrayHead && code.op.codeType() != codeArrayElem { + code.length -= uintptrSize + } switch code.op.codeType() { case codeArrayElem, codeSliceElem, codeMapKey: code = code.end @@ -106,7 +118,7 @@ func (c *opcode) decOpcodeIndex() { func (c *opcode) dumpHead(code *opcode) string { var length uintptr - if code.op.codeType() == codeArrayElem { + if code.op.codeType() == codeArrayHead { length = code.length } else { length = code.length / uintptrSize @@ -382,12 +394,3 @@ func newRecursiveCode(ctx *encodeCompileContext, jmp *compiledCode) *opcode { jmp: jmp, } } - -//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 -//} From 34b662b98e6b2f9f679cc0e224c4258d60c63a4a Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 3 Sep 2020 15:36:11 +0900 Subject: [PATCH 12/18] Add InterfaceEnd operation --- cmd/generator/main.go | 2 + encode_opcode.go | 9 +- encode_optype.go | 1576 +++++++++++++++++++++-------------------- encode_vm.go | 41 +- 4 files changed, 846 insertions(+), 782 deletions(-) diff --git a/cmd/generator/main.go b/cmd/generator/main.go index 971dc5b..c6a3c9e 100644 --- a/cmd/generator/main.go +++ b/cmd/generator/main.go @@ -220,6 +220,7 @@ func (t opType) fieldToStringTagField() opType { opTypes := []opType{ {"End", "EndIndent", "Op"}, {"Interface", "InterfaceIndent", "Op"}, + {"InterfaceEnd", "InterfaceEndIndent", "Op"}, {"Ptr", "PtrIndent", "Op"}, {"SliceHead", "SliceHeadIndent", "SliceHead"}, {"RootSliceHead", "RootSliceHeadIndent", "SliceHead"}, @@ -252,6 +253,7 @@ func (t opType) fieldToStringTagField() opType { {"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"}, {"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"}, {"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"}, + {"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"}, {"StructEnd", "StructEndIndent", "StructField"}, {"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"}, } diff --git a/encode_opcode.go b/encode_opcode.go index a3d9e1a..9b0cc81 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -80,7 +80,10 @@ func (c *opcode) beforeLastCode() *opcode { func (c *opcode) totalLength() int { var idx int for code := c; code.op != opEnd; { - idx = code.displayIdx + idx = int(code.idx / uintptrSize) + if code.op == opInterfaceEnd { + break + } switch code.op.codeType() { case codeArrayElem, codeSliceElem, codeMapKey: code = code.end @@ -88,7 +91,7 @@ func (c *opcode) totalLength() int { code = code.next } } - return idx + 1 + return idx + 2 // opEnd + 1 } func (c *opcode) decOpcodeIndex() { @@ -378,8 +381,8 @@ func newInterfaceCode(ctx *encodeCompileContext) *opcode { displayIdx: ctx.opcodeIndex, idx: opcodeOffset(ctx.ptrIndex), indent: ctx.indent, - next: newEndOp(ctx), root: ctx.root, + next: newEndOp(ctx), } } diff --git a/encode_optype.go b/encode_optype.go index 21c2835..dccc3d5 100644 --- a/encode_optype.go +++ b/encode_optype.go @@ -21,780 +21,784 @@ type opType int const ( opEnd opType = 0 opInterface opType = 1 - opPtr opType = 2 - opSliceHead opType = 3 - opRootSliceHead opType = 4 - opSliceElem opType = 5 - opRootSliceElem opType = 6 - opSliceEnd opType = 7 - opArrayHead opType = 8 - opArrayElem opType = 9 - opArrayEnd opType = 10 - opMapHead opType = 11 - opMapHeadLoad opType = 12 - opRootMapHead opType = 13 - opMapKey opType = 14 - opRootMapKey opType = 15 - opMapValue opType = 16 - opMapEnd opType = 17 - opStructFieldHead opType = 18 - opStructFieldHeadOmitEmpty opType = 19 - opStructFieldHeadStringTag opType = 20 - opStructFieldAnonymousHead opType = 21 - opStructFieldAnonymousHeadOmitEmpty opType = 22 - opStructFieldPtrAnonymousHeadOmitEmpty opType = 23 - opStructFieldAnonymousHeadStringTag opType = 24 - opStructFieldPtrAnonymousHeadStringTag opType = 25 - opStructFieldPtrHead opType = 26 - opStructFieldPtrHeadOmitEmpty opType = 27 - opStructFieldPtrHeadStringTag opType = 28 - opStructFieldPtrAnonymousHead opType = 29 - opStructField opType = 30 - opStructFieldOmitEmpty opType = 31 - opStructFieldStringTag opType = 32 - opStructFieldRecursive opType = 33 - opStructEnd opType = 34 - opStructAnonymousEnd opType = 35 - opInt opType = 36 - opInt8 opType = 37 - opInt16 opType = 38 - opInt32 opType = 39 - opInt64 opType = 40 - opUint opType = 41 - opUint8 opType = 42 - opUint16 opType = 43 - opUint32 opType = 44 - opUint64 opType = 45 - opFloat32 opType = 46 - opFloat64 opType = 47 - opBool opType = 48 - opString opType = 49 - opBytes opType = 50 - opArray opType = 51 - opMap opType = 52 - opMapLoad opType = 53 - opSlice opType = 54 - opStruct opType = 55 - opMarshalJSON opType = 56 - opMarshalText opType = 57 - opStructFieldHeadInt opType = 58 - opStructFieldHeadInt8 opType = 59 - opStructFieldHeadInt16 opType = 60 - opStructFieldHeadInt32 opType = 61 - opStructFieldHeadInt64 opType = 62 - opStructFieldHeadUint opType = 63 - opStructFieldHeadUint8 opType = 64 - opStructFieldHeadUint16 opType = 65 - opStructFieldHeadUint32 opType = 66 - opStructFieldHeadUint64 opType = 67 - opStructFieldHeadFloat32 opType = 68 - opStructFieldHeadFloat64 opType = 69 - opStructFieldHeadBool opType = 70 - opStructFieldHeadString opType = 71 - opStructFieldHeadBytes opType = 72 - opStructFieldHeadArray opType = 73 - opStructFieldHeadMap opType = 74 - opStructFieldHeadMapLoad opType = 75 - opStructFieldHeadSlice opType = 76 - opStructFieldHeadStruct opType = 77 - opStructFieldHeadMarshalJSON opType = 78 - opStructFieldHeadMarshalText opType = 79 - opStructFieldHeadOmitEmptyInt opType = 80 - opStructFieldHeadOmitEmptyInt8 opType = 81 - opStructFieldHeadOmitEmptyInt16 opType = 82 - opStructFieldHeadOmitEmptyInt32 opType = 83 - opStructFieldHeadOmitEmptyInt64 opType = 84 - opStructFieldHeadOmitEmptyUint opType = 85 - opStructFieldHeadOmitEmptyUint8 opType = 86 - opStructFieldHeadOmitEmptyUint16 opType = 87 - opStructFieldHeadOmitEmptyUint32 opType = 88 - opStructFieldHeadOmitEmptyUint64 opType = 89 - opStructFieldHeadOmitEmptyFloat32 opType = 90 - opStructFieldHeadOmitEmptyFloat64 opType = 91 - opStructFieldHeadOmitEmptyBool opType = 92 - opStructFieldHeadOmitEmptyString opType = 93 - opStructFieldHeadOmitEmptyBytes opType = 94 - opStructFieldHeadOmitEmptyArray opType = 95 - opStructFieldHeadOmitEmptyMap opType = 96 - opStructFieldHeadOmitEmptyMapLoad opType = 97 - opStructFieldHeadOmitEmptySlice opType = 98 - opStructFieldHeadOmitEmptyStruct opType = 99 - opStructFieldHeadOmitEmptyMarshalJSON opType = 100 - opStructFieldHeadOmitEmptyMarshalText opType = 101 - opStructFieldHeadStringTagInt opType = 102 - opStructFieldHeadStringTagInt8 opType = 103 - opStructFieldHeadStringTagInt16 opType = 104 - opStructFieldHeadStringTagInt32 opType = 105 - opStructFieldHeadStringTagInt64 opType = 106 - opStructFieldHeadStringTagUint opType = 107 - opStructFieldHeadStringTagUint8 opType = 108 - opStructFieldHeadStringTagUint16 opType = 109 - opStructFieldHeadStringTagUint32 opType = 110 - opStructFieldHeadStringTagUint64 opType = 111 - opStructFieldHeadStringTagFloat32 opType = 112 - opStructFieldHeadStringTagFloat64 opType = 113 - opStructFieldHeadStringTagBool opType = 114 - opStructFieldHeadStringTagString opType = 115 - opStructFieldHeadStringTagBytes opType = 116 - opStructFieldHeadStringTagArray opType = 117 - opStructFieldHeadStringTagMap opType = 118 - opStructFieldHeadStringTagMapLoad opType = 119 - opStructFieldHeadStringTagSlice opType = 120 - opStructFieldHeadStringTagStruct opType = 121 - opStructFieldHeadStringTagMarshalJSON opType = 122 - opStructFieldHeadStringTagMarshalText opType = 123 - opStructFieldAnonymousHeadInt opType = 124 - opStructFieldAnonymousHeadInt8 opType = 125 - opStructFieldAnonymousHeadInt16 opType = 126 - opStructFieldAnonymousHeadInt32 opType = 127 - opStructFieldAnonymousHeadInt64 opType = 128 - opStructFieldAnonymousHeadUint opType = 129 - opStructFieldAnonymousHeadUint8 opType = 130 - opStructFieldAnonymousHeadUint16 opType = 131 - opStructFieldAnonymousHeadUint32 opType = 132 - opStructFieldAnonymousHeadUint64 opType = 133 - opStructFieldAnonymousHeadFloat32 opType = 134 - opStructFieldAnonymousHeadFloat64 opType = 135 - opStructFieldAnonymousHeadBool opType = 136 - opStructFieldAnonymousHeadString opType = 137 - opStructFieldAnonymousHeadBytes opType = 138 - opStructFieldAnonymousHeadArray opType = 139 - opStructFieldAnonymousHeadMap opType = 140 - opStructFieldAnonymousHeadMapLoad opType = 141 - opStructFieldAnonymousHeadSlice opType = 142 - opStructFieldAnonymousHeadStruct opType = 143 - opStructFieldAnonymousHeadMarshalJSON opType = 144 - opStructFieldAnonymousHeadMarshalText opType = 145 - opStructFieldAnonymousHeadOmitEmptyInt opType = 146 - opStructFieldAnonymousHeadOmitEmptyInt8 opType = 147 - opStructFieldAnonymousHeadOmitEmptyInt16 opType = 148 - opStructFieldAnonymousHeadOmitEmptyInt32 opType = 149 - opStructFieldAnonymousHeadOmitEmptyInt64 opType = 150 - opStructFieldAnonymousHeadOmitEmptyUint opType = 151 - opStructFieldAnonymousHeadOmitEmptyUint8 opType = 152 - opStructFieldAnonymousHeadOmitEmptyUint16 opType = 153 - opStructFieldAnonymousHeadOmitEmptyUint32 opType = 154 - opStructFieldAnonymousHeadOmitEmptyUint64 opType = 155 - opStructFieldAnonymousHeadOmitEmptyFloat32 opType = 156 - opStructFieldAnonymousHeadOmitEmptyFloat64 opType = 157 - opStructFieldAnonymousHeadOmitEmptyBool opType = 158 - opStructFieldAnonymousHeadOmitEmptyString opType = 159 - opStructFieldAnonymousHeadOmitEmptyBytes opType = 160 - opStructFieldAnonymousHeadOmitEmptyArray opType = 161 - opStructFieldAnonymousHeadOmitEmptyMap opType = 162 - opStructFieldAnonymousHeadOmitEmptyMapLoad opType = 163 - opStructFieldAnonymousHeadOmitEmptySlice opType = 164 - opStructFieldAnonymousHeadOmitEmptyStruct opType = 165 - opStructFieldAnonymousHeadOmitEmptyMarshalJSON opType = 166 - opStructFieldAnonymousHeadOmitEmptyMarshalText opType = 167 - opStructFieldAnonymousHeadStringTagInt opType = 168 - opStructFieldAnonymousHeadStringTagInt8 opType = 169 - opStructFieldAnonymousHeadStringTagInt16 opType = 170 - opStructFieldAnonymousHeadStringTagInt32 opType = 171 - opStructFieldAnonymousHeadStringTagInt64 opType = 172 - opStructFieldAnonymousHeadStringTagUint opType = 173 - opStructFieldAnonymousHeadStringTagUint8 opType = 174 - opStructFieldAnonymousHeadStringTagUint16 opType = 175 - opStructFieldAnonymousHeadStringTagUint32 opType = 176 - opStructFieldAnonymousHeadStringTagUint64 opType = 177 - opStructFieldAnonymousHeadStringTagFloat32 opType = 178 - opStructFieldAnonymousHeadStringTagFloat64 opType = 179 - opStructFieldAnonymousHeadStringTagBool opType = 180 - opStructFieldAnonymousHeadStringTagString opType = 181 - opStructFieldAnonymousHeadStringTagBytes opType = 182 - opStructFieldAnonymousHeadStringTagArray opType = 183 - opStructFieldAnonymousHeadStringTagMap opType = 184 - opStructFieldAnonymousHeadStringTagMapLoad opType = 185 - opStructFieldAnonymousHeadStringTagSlice opType = 186 - opStructFieldAnonymousHeadStringTagStruct opType = 187 - opStructFieldAnonymousHeadStringTagMarshalJSON opType = 188 - opStructFieldAnonymousHeadStringTagMarshalText opType = 189 - opStructFieldPtrHeadInt opType = 190 - opStructFieldPtrHeadInt8 opType = 191 - opStructFieldPtrHeadInt16 opType = 192 - opStructFieldPtrHeadInt32 opType = 193 - opStructFieldPtrHeadInt64 opType = 194 - opStructFieldPtrHeadUint opType = 195 - opStructFieldPtrHeadUint8 opType = 196 - opStructFieldPtrHeadUint16 opType = 197 - opStructFieldPtrHeadUint32 opType = 198 - opStructFieldPtrHeadUint64 opType = 199 - opStructFieldPtrHeadFloat32 opType = 200 - opStructFieldPtrHeadFloat64 opType = 201 - opStructFieldPtrHeadBool opType = 202 - opStructFieldPtrHeadString opType = 203 - opStructFieldPtrHeadBytes opType = 204 - opStructFieldPtrHeadArray opType = 205 - opStructFieldPtrHeadMap opType = 206 - opStructFieldPtrHeadMapLoad opType = 207 - opStructFieldPtrHeadSlice opType = 208 - opStructFieldPtrHeadStruct opType = 209 - opStructFieldPtrHeadMarshalJSON opType = 210 - opStructFieldPtrHeadMarshalText opType = 211 - opStructFieldPtrHeadOmitEmptyInt opType = 212 - opStructFieldPtrHeadOmitEmptyInt8 opType = 213 - opStructFieldPtrHeadOmitEmptyInt16 opType = 214 - opStructFieldPtrHeadOmitEmptyInt32 opType = 215 - opStructFieldPtrHeadOmitEmptyInt64 opType = 216 - opStructFieldPtrHeadOmitEmptyUint opType = 217 - opStructFieldPtrHeadOmitEmptyUint8 opType = 218 - opStructFieldPtrHeadOmitEmptyUint16 opType = 219 - opStructFieldPtrHeadOmitEmptyUint32 opType = 220 - opStructFieldPtrHeadOmitEmptyUint64 opType = 221 - opStructFieldPtrHeadOmitEmptyFloat32 opType = 222 - opStructFieldPtrHeadOmitEmptyFloat64 opType = 223 - opStructFieldPtrHeadOmitEmptyBool opType = 224 - opStructFieldPtrHeadOmitEmptyString opType = 225 - opStructFieldPtrHeadOmitEmptyBytes opType = 226 - opStructFieldPtrHeadOmitEmptyArray opType = 227 - opStructFieldPtrHeadOmitEmptyMap opType = 228 - opStructFieldPtrHeadOmitEmptyMapLoad opType = 229 - opStructFieldPtrHeadOmitEmptySlice opType = 230 - opStructFieldPtrHeadOmitEmptyStruct opType = 231 - opStructFieldPtrHeadOmitEmptyMarshalJSON opType = 232 - opStructFieldPtrHeadOmitEmptyMarshalText opType = 233 - opStructFieldPtrHeadStringTagInt opType = 234 - opStructFieldPtrHeadStringTagInt8 opType = 235 - opStructFieldPtrHeadStringTagInt16 opType = 236 - opStructFieldPtrHeadStringTagInt32 opType = 237 - opStructFieldPtrHeadStringTagInt64 opType = 238 - opStructFieldPtrHeadStringTagUint opType = 239 - opStructFieldPtrHeadStringTagUint8 opType = 240 - opStructFieldPtrHeadStringTagUint16 opType = 241 - opStructFieldPtrHeadStringTagUint32 opType = 242 - opStructFieldPtrHeadStringTagUint64 opType = 243 - opStructFieldPtrHeadStringTagFloat32 opType = 244 - opStructFieldPtrHeadStringTagFloat64 opType = 245 - opStructFieldPtrHeadStringTagBool opType = 246 - opStructFieldPtrHeadStringTagString opType = 247 - opStructFieldPtrHeadStringTagBytes opType = 248 - opStructFieldPtrHeadStringTagArray opType = 249 - opStructFieldPtrHeadStringTagMap opType = 250 - opStructFieldPtrHeadStringTagMapLoad opType = 251 - opStructFieldPtrHeadStringTagSlice opType = 252 - opStructFieldPtrHeadStringTagStruct opType = 253 - opStructFieldPtrHeadStringTagMarshalJSON opType = 254 - opStructFieldPtrHeadStringTagMarshalText opType = 255 - opStructFieldPtrAnonymousHeadInt opType = 256 - opStructFieldPtrAnonymousHeadInt8 opType = 257 - opStructFieldPtrAnonymousHeadInt16 opType = 258 - opStructFieldPtrAnonymousHeadInt32 opType = 259 - opStructFieldPtrAnonymousHeadInt64 opType = 260 - opStructFieldPtrAnonymousHeadUint opType = 261 - opStructFieldPtrAnonymousHeadUint8 opType = 262 - opStructFieldPtrAnonymousHeadUint16 opType = 263 - opStructFieldPtrAnonymousHeadUint32 opType = 264 - opStructFieldPtrAnonymousHeadUint64 opType = 265 - opStructFieldPtrAnonymousHeadFloat32 opType = 266 - opStructFieldPtrAnonymousHeadFloat64 opType = 267 - opStructFieldPtrAnonymousHeadBool opType = 268 - opStructFieldPtrAnonymousHeadString opType = 269 - opStructFieldPtrAnonymousHeadBytes opType = 270 - opStructFieldPtrAnonymousHeadArray opType = 271 - opStructFieldPtrAnonymousHeadMap opType = 272 - opStructFieldPtrAnonymousHeadMapLoad opType = 273 - opStructFieldPtrAnonymousHeadSlice opType = 274 - opStructFieldPtrAnonymousHeadStruct opType = 275 - opStructFieldPtrAnonymousHeadMarshalJSON opType = 276 - opStructFieldPtrAnonymousHeadMarshalText opType = 277 - opStructFieldPtrAnonymousHeadOmitEmptyInt opType = 278 - opStructFieldPtrAnonymousHeadOmitEmptyInt8 opType = 279 - opStructFieldPtrAnonymousHeadOmitEmptyInt16 opType = 280 - opStructFieldPtrAnonymousHeadOmitEmptyInt32 opType = 281 - opStructFieldPtrAnonymousHeadOmitEmptyInt64 opType = 282 - opStructFieldPtrAnonymousHeadOmitEmptyUint opType = 283 - opStructFieldPtrAnonymousHeadOmitEmptyUint8 opType = 284 - opStructFieldPtrAnonymousHeadOmitEmptyUint16 opType = 285 - opStructFieldPtrAnonymousHeadOmitEmptyUint32 opType = 286 - opStructFieldPtrAnonymousHeadOmitEmptyUint64 opType = 287 - opStructFieldPtrAnonymousHeadOmitEmptyFloat32 opType = 288 - opStructFieldPtrAnonymousHeadOmitEmptyFloat64 opType = 289 - opStructFieldPtrAnonymousHeadOmitEmptyBool opType = 290 - opStructFieldPtrAnonymousHeadOmitEmptyString opType = 291 - opStructFieldPtrAnonymousHeadOmitEmptyBytes opType = 292 - opStructFieldPtrAnonymousHeadOmitEmptyArray opType = 293 - opStructFieldPtrAnonymousHeadOmitEmptyMap opType = 294 - opStructFieldPtrAnonymousHeadOmitEmptyMapLoad opType = 295 - opStructFieldPtrAnonymousHeadOmitEmptySlice opType = 296 - opStructFieldPtrAnonymousHeadOmitEmptyStruct opType = 297 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSON opType = 298 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalText opType = 299 - opStructFieldPtrAnonymousHeadStringTagInt opType = 300 - opStructFieldPtrAnonymousHeadStringTagInt8 opType = 301 - opStructFieldPtrAnonymousHeadStringTagInt16 opType = 302 - opStructFieldPtrAnonymousHeadStringTagInt32 opType = 303 - opStructFieldPtrAnonymousHeadStringTagInt64 opType = 304 - opStructFieldPtrAnonymousHeadStringTagUint opType = 305 - opStructFieldPtrAnonymousHeadStringTagUint8 opType = 306 - opStructFieldPtrAnonymousHeadStringTagUint16 opType = 307 - opStructFieldPtrAnonymousHeadStringTagUint32 opType = 308 - opStructFieldPtrAnonymousHeadStringTagUint64 opType = 309 - opStructFieldPtrAnonymousHeadStringTagFloat32 opType = 310 - opStructFieldPtrAnonymousHeadStringTagFloat64 opType = 311 - opStructFieldPtrAnonymousHeadStringTagBool opType = 312 - opStructFieldPtrAnonymousHeadStringTagString opType = 313 - opStructFieldPtrAnonymousHeadStringTagBytes opType = 314 - opStructFieldPtrAnonymousHeadStringTagArray opType = 315 - opStructFieldPtrAnonymousHeadStringTagMap opType = 316 - opStructFieldPtrAnonymousHeadStringTagMapLoad opType = 317 - opStructFieldPtrAnonymousHeadStringTagSlice opType = 318 - opStructFieldPtrAnonymousHeadStringTagStruct opType = 319 - opStructFieldPtrAnonymousHeadStringTagMarshalJSON opType = 320 - opStructFieldPtrAnonymousHeadStringTagMarshalText opType = 321 - opStructFieldInt opType = 322 - opStructFieldInt8 opType = 323 - opStructFieldInt16 opType = 324 - opStructFieldInt32 opType = 325 - opStructFieldInt64 opType = 326 - opStructFieldUint opType = 327 - opStructFieldUint8 opType = 328 - opStructFieldUint16 opType = 329 - opStructFieldUint32 opType = 330 - opStructFieldUint64 opType = 331 - opStructFieldFloat32 opType = 332 - opStructFieldFloat64 opType = 333 - opStructFieldBool opType = 334 - opStructFieldString opType = 335 - opStructFieldBytes opType = 336 - opStructFieldArray opType = 337 - opStructFieldMap opType = 338 - opStructFieldMapLoad opType = 339 - opStructFieldSlice opType = 340 - opStructFieldStruct opType = 341 - opStructFieldMarshalJSON opType = 342 - opStructFieldMarshalText opType = 343 - opStructFieldOmitEmptyInt opType = 344 - opStructFieldOmitEmptyInt8 opType = 345 - opStructFieldOmitEmptyInt16 opType = 346 - opStructFieldOmitEmptyInt32 opType = 347 - opStructFieldOmitEmptyInt64 opType = 348 - opStructFieldOmitEmptyUint opType = 349 - opStructFieldOmitEmptyUint8 opType = 350 - opStructFieldOmitEmptyUint16 opType = 351 - opStructFieldOmitEmptyUint32 opType = 352 - opStructFieldOmitEmptyUint64 opType = 353 - opStructFieldOmitEmptyFloat32 opType = 354 - opStructFieldOmitEmptyFloat64 opType = 355 - opStructFieldOmitEmptyBool opType = 356 - opStructFieldOmitEmptyString opType = 357 - opStructFieldOmitEmptyBytes opType = 358 - opStructFieldOmitEmptyArray opType = 359 - opStructFieldOmitEmptyMap opType = 360 - opStructFieldOmitEmptyMapLoad opType = 361 - opStructFieldOmitEmptySlice opType = 362 - opStructFieldOmitEmptyStruct opType = 363 - opStructFieldOmitEmptyMarshalJSON opType = 364 - opStructFieldOmitEmptyMarshalText opType = 365 - opStructFieldStringTagInt opType = 366 - opStructFieldStringTagInt8 opType = 367 - opStructFieldStringTagInt16 opType = 368 - opStructFieldStringTagInt32 opType = 369 - opStructFieldStringTagInt64 opType = 370 - opStructFieldStringTagUint opType = 371 - opStructFieldStringTagUint8 opType = 372 - opStructFieldStringTagUint16 opType = 373 - opStructFieldStringTagUint32 opType = 374 - opStructFieldStringTagUint64 opType = 375 - opStructFieldStringTagFloat32 opType = 376 - opStructFieldStringTagFloat64 opType = 377 - opStructFieldStringTagBool opType = 378 - opStructFieldStringTagString opType = 379 - opStructFieldStringTagBytes opType = 380 - opStructFieldStringTagArray opType = 381 - opStructFieldStringTagMap opType = 382 - opStructFieldStringTagMapLoad opType = 383 - opStructFieldStringTagSlice opType = 384 - opStructFieldStringTagStruct opType = 385 - opStructFieldStringTagMarshalJSON opType = 386 - opStructFieldStringTagMarshalText opType = 387 - opEndIndent opType = 388 - opInterfaceIndent opType = 389 - opPtrIndent opType = 390 - opSliceHeadIndent opType = 391 - opRootSliceHeadIndent opType = 392 - opSliceElemIndent opType = 393 - opRootSliceElemIndent opType = 394 - opSliceEndIndent opType = 395 - opArrayHeadIndent opType = 396 - opArrayElemIndent opType = 397 - opArrayEndIndent opType = 398 - opMapHeadIndent opType = 399 - opMapHeadLoadIndent opType = 400 - opRootMapHeadIndent opType = 401 - opMapKeyIndent opType = 402 - opRootMapKeyIndent opType = 403 - opMapValueIndent opType = 404 - opMapEndIndent opType = 405 - opStructFieldHeadIndent opType = 406 - opStructFieldHeadOmitEmptyIndent opType = 407 - opStructFieldHeadStringTagIndent opType = 408 - opStructFieldAnonymousHeadIndent opType = 409 - opStructFieldAnonymousHeadOmitEmptyIndent opType = 410 - opStructFieldPtrAnonymousHeadOmitEmptyIndent opType = 411 - opStructFieldAnonymousHeadStringTagIndent opType = 412 - opStructFieldPtrAnonymousHeadStringTagIndent opType = 413 - opStructFieldPtrHeadIndent opType = 414 - opStructFieldPtrHeadOmitEmptyIndent opType = 415 - opStructFieldPtrHeadStringTagIndent opType = 416 - opStructFieldPtrAnonymousHeadIndent opType = 417 - opStructFieldIndent opType = 418 - opStructFieldOmitEmptyIndent opType = 419 - opStructFieldStringTagIndent opType = 420 - opStructFieldRecursiveIndent opType = 421 - opStructEndIndent opType = 422 - opStructAnonymousEndIndent opType = 423 - opIntIndent opType = 424 - opInt8Indent opType = 425 - opInt16Indent opType = 426 - opInt32Indent opType = 427 - opInt64Indent opType = 428 - opUintIndent opType = 429 - opUint8Indent opType = 430 - opUint16Indent opType = 431 - opUint32Indent opType = 432 - opUint64Indent opType = 433 - opFloat32Indent opType = 434 - opFloat64Indent opType = 435 - opBoolIndent opType = 436 - opStringIndent opType = 437 - opBytesIndent opType = 438 - opArrayIndent opType = 439 - opMapIndent opType = 440 - opMapLoadIndent opType = 441 - opSliceIndent opType = 442 - opStructIndent opType = 443 - opMarshalJSONIndent opType = 444 - opMarshalTextIndent opType = 445 - opStructFieldHeadIntIndent opType = 446 - opStructFieldHeadInt8Indent opType = 447 - opStructFieldHeadInt16Indent opType = 448 - opStructFieldHeadInt32Indent opType = 449 - opStructFieldHeadInt64Indent opType = 450 - opStructFieldHeadUintIndent opType = 451 - opStructFieldHeadUint8Indent opType = 452 - opStructFieldHeadUint16Indent opType = 453 - opStructFieldHeadUint32Indent opType = 454 - opStructFieldHeadUint64Indent opType = 455 - opStructFieldHeadFloat32Indent opType = 456 - opStructFieldHeadFloat64Indent opType = 457 - opStructFieldHeadBoolIndent opType = 458 - opStructFieldHeadStringIndent opType = 459 - opStructFieldHeadBytesIndent opType = 460 - opStructFieldHeadArrayIndent opType = 461 - opStructFieldHeadMapIndent opType = 462 - opStructFieldHeadMapLoadIndent opType = 463 - opStructFieldHeadSliceIndent opType = 464 - opStructFieldHeadStructIndent opType = 465 - opStructFieldHeadMarshalJSONIndent opType = 466 - opStructFieldHeadMarshalTextIndent opType = 467 - opStructFieldHeadOmitEmptyIntIndent opType = 468 - opStructFieldHeadOmitEmptyInt8Indent opType = 469 - opStructFieldHeadOmitEmptyInt16Indent opType = 470 - opStructFieldHeadOmitEmptyInt32Indent opType = 471 - opStructFieldHeadOmitEmptyInt64Indent opType = 472 - opStructFieldHeadOmitEmptyUintIndent opType = 473 - opStructFieldHeadOmitEmptyUint8Indent opType = 474 - opStructFieldHeadOmitEmptyUint16Indent opType = 475 - opStructFieldHeadOmitEmptyUint32Indent opType = 476 - opStructFieldHeadOmitEmptyUint64Indent opType = 477 - opStructFieldHeadOmitEmptyFloat32Indent opType = 478 - opStructFieldHeadOmitEmptyFloat64Indent opType = 479 - opStructFieldHeadOmitEmptyBoolIndent opType = 480 - opStructFieldHeadOmitEmptyStringIndent opType = 481 - opStructFieldHeadOmitEmptyBytesIndent opType = 482 - opStructFieldHeadOmitEmptyArrayIndent opType = 483 - opStructFieldHeadOmitEmptyMapIndent opType = 484 - opStructFieldHeadOmitEmptyMapLoadIndent opType = 485 - opStructFieldHeadOmitEmptySliceIndent opType = 486 - opStructFieldHeadOmitEmptyStructIndent opType = 487 - opStructFieldHeadOmitEmptyMarshalJSONIndent opType = 488 - opStructFieldHeadOmitEmptyMarshalTextIndent opType = 489 - opStructFieldHeadStringTagIntIndent opType = 490 - opStructFieldHeadStringTagInt8Indent opType = 491 - opStructFieldHeadStringTagInt16Indent opType = 492 - opStructFieldHeadStringTagInt32Indent opType = 493 - opStructFieldHeadStringTagInt64Indent opType = 494 - opStructFieldHeadStringTagUintIndent opType = 495 - opStructFieldHeadStringTagUint8Indent opType = 496 - opStructFieldHeadStringTagUint16Indent opType = 497 - opStructFieldHeadStringTagUint32Indent opType = 498 - opStructFieldHeadStringTagUint64Indent opType = 499 - opStructFieldHeadStringTagFloat32Indent opType = 500 - opStructFieldHeadStringTagFloat64Indent opType = 501 - opStructFieldHeadStringTagBoolIndent opType = 502 - opStructFieldHeadStringTagStringIndent opType = 503 - opStructFieldHeadStringTagBytesIndent opType = 504 - opStructFieldHeadStringTagArrayIndent opType = 505 - opStructFieldHeadStringTagMapIndent opType = 506 - opStructFieldHeadStringTagMapLoadIndent opType = 507 - opStructFieldHeadStringTagSliceIndent opType = 508 - opStructFieldHeadStringTagStructIndent opType = 509 - opStructFieldHeadStringTagMarshalJSONIndent opType = 510 - opStructFieldHeadStringTagMarshalTextIndent opType = 511 - opStructFieldAnonymousHeadIntIndent opType = 512 - opStructFieldAnonymousHeadInt8Indent opType = 513 - opStructFieldAnonymousHeadInt16Indent opType = 514 - opStructFieldAnonymousHeadInt32Indent opType = 515 - opStructFieldAnonymousHeadInt64Indent opType = 516 - opStructFieldAnonymousHeadUintIndent opType = 517 - opStructFieldAnonymousHeadUint8Indent opType = 518 - opStructFieldAnonymousHeadUint16Indent opType = 519 - opStructFieldAnonymousHeadUint32Indent opType = 520 - opStructFieldAnonymousHeadUint64Indent opType = 521 - opStructFieldAnonymousHeadFloat32Indent opType = 522 - opStructFieldAnonymousHeadFloat64Indent opType = 523 - opStructFieldAnonymousHeadBoolIndent opType = 524 - opStructFieldAnonymousHeadStringIndent opType = 525 - opStructFieldAnonymousHeadBytesIndent opType = 526 - opStructFieldAnonymousHeadArrayIndent opType = 527 - opStructFieldAnonymousHeadMapIndent opType = 528 - opStructFieldAnonymousHeadMapLoadIndent opType = 529 - opStructFieldAnonymousHeadSliceIndent opType = 530 - opStructFieldAnonymousHeadStructIndent opType = 531 - opStructFieldAnonymousHeadMarshalJSONIndent opType = 532 - opStructFieldAnonymousHeadMarshalTextIndent opType = 533 - opStructFieldAnonymousHeadOmitEmptyIntIndent opType = 534 - opStructFieldAnonymousHeadOmitEmptyInt8Indent opType = 535 - opStructFieldAnonymousHeadOmitEmptyInt16Indent opType = 536 - opStructFieldAnonymousHeadOmitEmptyInt32Indent opType = 537 - opStructFieldAnonymousHeadOmitEmptyInt64Indent opType = 538 - opStructFieldAnonymousHeadOmitEmptyUintIndent opType = 539 - opStructFieldAnonymousHeadOmitEmptyUint8Indent opType = 540 - opStructFieldAnonymousHeadOmitEmptyUint16Indent opType = 541 - opStructFieldAnonymousHeadOmitEmptyUint32Indent opType = 542 - opStructFieldAnonymousHeadOmitEmptyUint64Indent opType = 543 - opStructFieldAnonymousHeadOmitEmptyFloat32Indent opType = 544 - opStructFieldAnonymousHeadOmitEmptyFloat64Indent opType = 545 - opStructFieldAnonymousHeadOmitEmptyBoolIndent opType = 546 - opStructFieldAnonymousHeadOmitEmptyStringIndent opType = 547 - opStructFieldAnonymousHeadOmitEmptyBytesIndent opType = 548 - opStructFieldAnonymousHeadOmitEmptyArrayIndent opType = 549 - opStructFieldAnonymousHeadOmitEmptyMapIndent opType = 550 - opStructFieldAnonymousHeadOmitEmptyMapLoadIndent opType = 551 - opStructFieldAnonymousHeadOmitEmptySliceIndent opType = 552 - opStructFieldAnonymousHeadOmitEmptyStructIndent opType = 553 - opStructFieldAnonymousHeadOmitEmptyMarshalJSONIndent opType = 554 - opStructFieldAnonymousHeadOmitEmptyMarshalTextIndent opType = 555 - opStructFieldAnonymousHeadStringTagIntIndent opType = 556 - opStructFieldAnonymousHeadStringTagInt8Indent opType = 557 - opStructFieldAnonymousHeadStringTagInt16Indent opType = 558 - opStructFieldAnonymousHeadStringTagInt32Indent opType = 559 - opStructFieldAnonymousHeadStringTagInt64Indent opType = 560 - opStructFieldAnonymousHeadStringTagUintIndent opType = 561 - opStructFieldAnonymousHeadStringTagUint8Indent opType = 562 - opStructFieldAnonymousHeadStringTagUint16Indent opType = 563 - opStructFieldAnonymousHeadStringTagUint32Indent opType = 564 - opStructFieldAnonymousHeadStringTagUint64Indent opType = 565 - opStructFieldAnonymousHeadStringTagFloat32Indent opType = 566 - opStructFieldAnonymousHeadStringTagFloat64Indent opType = 567 - opStructFieldAnonymousHeadStringTagBoolIndent opType = 568 - opStructFieldAnonymousHeadStringTagStringIndent opType = 569 - opStructFieldAnonymousHeadStringTagBytesIndent opType = 570 - opStructFieldAnonymousHeadStringTagArrayIndent opType = 571 - opStructFieldAnonymousHeadStringTagMapIndent opType = 572 - opStructFieldAnonymousHeadStringTagMapLoadIndent opType = 573 - opStructFieldAnonymousHeadStringTagSliceIndent opType = 574 - opStructFieldAnonymousHeadStringTagStructIndent opType = 575 - opStructFieldAnonymousHeadStringTagMarshalJSONIndent opType = 576 - opStructFieldAnonymousHeadStringTagMarshalTextIndent opType = 577 - opStructFieldPtrHeadIntIndent opType = 578 - opStructFieldPtrHeadInt8Indent opType = 579 - opStructFieldPtrHeadInt16Indent opType = 580 - opStructFieldPtrHeadInt32Indent opType = 581 - opStructFieldPtrHeadInt64Indent opType = 582 - opStructFieldPtrHeadUintIndent opType = 583 - opStructFieldPtrHeadUint8Indent opType = 584 - opStructFieldPtrHeadUint16Indent opType = 585 - opStructFieldPtrHeadUint32Indent opType = 586 - opStructFieldPtrHeadUint64Indent opType = 587 - opStructFieldPtrHeadFloat32Indent opType = 588 - opStructFieldPtrHeadFloat64Indent opType = 589 - opStructFieldPtrHeadBoolIndent opType = 590 - opStructFieldPtrHeadStringIndent opType = 591 - opStructFieldPtrHeadBytesIndent opType = 592 - opStructFieldPtrHeadArrayIndent opType = 593 - opStructFieldPtrHeadMapIndent opType = 594 - opStructFieldPtrHeadMapLoadIndent opType = 595 - opStructFieldPtrHeadSliceIndent opType = 596 - opStructFieldPtrHeadStructIndent opType = 597 - opStructFieldPtrHeadMarshalJSONIndent opType = 598 - opStructFieldPtrHeadMarshalTextIndent opType = 599 - opStructFieldPtrHeadOmitEmptyIntIndent opType = 600 - opStructFieldPtrHeadOmitEmptyInt8Indent opType = 601 - opStructFieldPtrHeadOmitEmptyInt16Indent opType = 602 - opStructFieldPtrHeadOmitEmptyInt32Indent opType = 603 - opStructFieldPtrHeadOmitEmptyInt64Indent opType = 604 - opStructFieldPtrHeadOmitEmptyUintIndent opType = 605 - opStructFieldPtrHeadOmitEmptyUint8Indent opType = 606 - opStructFieldPtrHeadOmitEmptyUint16Indent opType = 607 - opStructFieldPtrHeadOmitEmptyUint32Indent opType = 608 - opStructFieldPtrHeadOmitEmptyUint64Indent opType = 609 - opStructFieldPtrHeadOmitEmptyFloat32Indent opType = 610 - opStructFieldPtrHeadOmitEmptyFloat64Indent opType = 611 - opStructFieldPtrHeadOmitEmptyBoolIndent opType = 612 - opStructFieldPtrHeadOmitEmptyStringIndent opType = 613 - opStructFieldPtrHeadOmitEmptyBytesIndent opType = 614 - opStructFieldPtrHeadOmitEmptyArrayIndent opType = 615 - opStructFieldPtrHeadOmitEmptyMapIndent opType = 616 - opStructFieldPtrHeadOmitEmptyMapLoadIndent opType = 617 - opStructFieldPtrHeadOmitEmptySliceIndent opType = 618 - opStructFieldPtrHeadOmitEmptyStructIndent opType = 619 - opStructFieldPtrHeadOmitEmptyMarshalJSONIndent opType = 620 - opStructFieldPtrHeadOmitEmptyMarshalTextIndent opType = 621 - opStructFieldPtrHeadStringTagIntIndent opType = 622 - opStructFieldPtrHeadStringTagInt8Indent opType = 623 - opStructFieldPtrHeadStringTagInt16Indent opType = 624 - opStructFieldPtrHeadStringTagInt32Indent opType = 625 - opStructFieldPtrHeadStringTagInt64Indent opType = 626 - opStructFieldPtrHeadStringTagUintIndent opType = 627 - opStructFieldPtrHeadStringTagUint8Indent opType = 628 - opStructFieldPtrHeadStringTagUint16Indent opType = 629 - opStructFieldPtrHeadStringTagUint32Indent opType = 630 - opStructFieldPtrHeadStringTagUint64Indent opType = 631 - opStructFieldPtrHeadStringTagFloat32Indent opType = 632 - opStructFieldPtrHeadStringTagFloat64Indent opType = 633 - opStructFieldPtrHeadStringTagBoolIndent opType = 634 - opStructFieldPtrHeadStringTagStringIndent opType = 635 - opStructFieldPtrHeadStringTagBytesIndent opType = 636 - opStructFieldPtrHeadStringTagArrayIndent opType = 637 - opStructFieldPtrHeadStringTagMapIndent opType = 638 - opStructFieldPtrHeadStringTagMapLoadIndent opType = 639 - opStructFieldPtrHeadStringTagSliceIndent opType = 640 - opStructFieldPtrHeadStringTagStructIndent opType = 641 - opStructFieldPtrHeadStringTagMarshalJSONIndent opType = 642 - opStructFieldPtrHeadStringTagMarshalTextIndent opType = 643 - opStructFieldPtrAnonymousHeadIntIndent opType = 644 - opStructFieldPtrAnonymousHeadInt8Indent opType = 645 - opStructFieldPtrAnonymousHeadInt16Indent opType = 646 - opStructFieldPtrAnonymousHeadInt32Indent opType = 647 - opStructFieldPtrAnonymousHeadInt64Indent opType = 648 - opStructFieldPtrAnonymousHeadUintIndent opType = 649 - opStructFieldPtrAnonymousHeadUint8Indent opType = 650 - opStructFieldPtrAnonymousHeadUint16Indent opType = 651 - opStructFieldPtrAnonymousHeadUint32Indent opType = 652 - opStructFieldPtrAnonymousHeadUint64Indent opType = 653 - opStructFieldPtrAnonymousHeadFloat32Indent opType = 654 - opStructFieldPtrAnonymousHeadFloat64Indent opType = 655 - opStructFieldPtrAnonymousHeadBoolIndent opType = 656 - opStructFieldPtrAnonymousHeadStringIndent opType = 657 - opStructFieldPtrAnonymousHeadBytesIndent opType = 658 - opStructFieldPtrAnonymousHeadArrayIndent opType = 659 - opStructFieldPtrAnonymousHeadMapIndent opType = 660 - opStructFieldPtrAnonymousHeadMapLoadIndent opType = 661 - opStructFieldPtrAnonymousHeadSliceIndent opType = 662 - opStructFieldPtrAnonymousHeadStructIndent opType = 663 - opStructFieldPtrAnonymousHeadMarshalJSONIndent opType = 664 - opStructFieldPtrAnonymousHeadMarshalTextIndent opType = 665 - opStructFieldPtrAnonymousHeadOmitEmptyIntIndent opType = 666 - opStructFieldPtrAnonymousHeadOmitEmptyInt8Indent opType = 667 - opStructFieldPtrAnonymousHeadOmitEmptyInt16Indent opType = 668 - opStructFieldPtrAnonymousHeadOmitEmptyInt32Indent opType = 669 - opStructFieldPtrAnonymousHeadOmitEmptyInt64Indent opType = 670 - opStructFieldPtrAnonymousHeadOmitEmptyUintIndent opType = 671 - opStructFieldPtrAnonymousHeadOmitEmptyUint8Indent opType = 672 - opStructFieldPtrAnonymousHeadOmitEmptyUint16Indent opType = 673 - opStructFieldPtrAnonymousHeadOmitEmptyUint32Indent opType = 674 - opStructFieldPtrAnonymousHeadOmitEmptyUint64Indent opType = 675 - opStructFieldPtrAnonymousHeadOmitEmptyFloat32Indent opType = 676 - opStructFieldPtrAnonymousHeadOmitEmptyFloat64Indent opType = 677 - opStructFieldPtrAnonymousHeadOmitEmptyBoolIndent opType = 678 - opStructFieldPtrAnonymousHeadOmitEmptyStringIndent opType = 679 - opStructFieldPtrAnonymousHeadOmitEmptyBytesIndent opType = 680 - opStructFieldPtrAnonymousHeadOmitEmptyArrayIndent opType = 681 - opStructFieldPtrAnonymousHeadOmitEmptyMapIndent opType = 682 - opStructFieldPtrAnonymousHeadOmitEmptyMapLoadIndent opType = 683 - opStructFieldPtrAnonymousHeadOmitEmptySliceIndent opType = 684 - opStructFieldPtrAnonymousHeadOmitEmptyStructIndent opType = 685 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSONIndent opType = 686 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalTextIndent opType = 687 - opStructFieldPtrAnonymousHeadStringTagIntIndent opType = 688 - opStructFieldPtrAnonymousHeadStringTagInt8Indent opType = 689 - opStructFieldPtrAnonymousHeadStringTagInt16Indent opType = 690 - opStructFieldPtrAnonymousHeadStringTagInt32Indent opType = 691 - opStructFieldPtrAnonymousHeadStringTagInt64Indent opType = 692 - opStructFieldPtrAnonymousHeadStringTagUintIndent opType = 693 - opStructFieldPtrAnonymousHeadStringTagUint8Indent opType = 694 - opStructFieldPtrAnonymousHeadStringTagUint16Indent opType = 695 - opStructFieldPtrAnonymousHeadStringTagUint32Indent opType = 696 - opStructFieldPtrAnonymousHeadStringTagUint64Indent opType = 697 - opStructFieldPtrAnonymousHeadStringTagFloat32Indent opType = 698 - opStructFieldPtrAnonymousHeadStringTagFloat64Indent opType = 699 - opStructFieldPtrAnonymousHeadStringTagBoolIndent opType = 700 - opStructFieldPtrAnonymousHeadStringTagStringIndent opType = 701 - opStructFieldPtrAnonymousHeadStringTagBytesIndent opType = 702 - opStructFieldPtrAnonymousHeadStringTagArrayIndent opType = 703 - opStructFieldPtrAnonymousHeadStringTagMapIndent opType = 704 - opStructFieldPtrAnonymousHeadStringTagMapLoadIndent opType = 705 - opStructFieldPtrAnonymousHeadStringTagSliceIndent opType = 706 - opStructFieldPtrAnonymousHeadStringTagStructIndent opType = 707 - opStructFieldPtrAnonymousHeadStringTagMarshalJSONIndent opType = 708 - opStructFieldPtrAnonymousHeadStringTagMarshalTextIndent opType = 709 - opStructFieldIntIndent opType = 710 - opStructFieldInt8Indent opType = 711 - opStructFieldInt16Indent opType = 712 - opStructFieldInt32Indent opType = 713 - opStructFieldInt64Indent opType = 714 - opStructFieldUintIndent opType = 715 - opStructFieldUint8Indent opType = 716 - opStructFieldUint16Indent opType = 717 - opStructFieldUint32Indent opType = 718 - opStructFieldUint64Indent opType = 719 - opStructFieldFloat32Indent opType = 720 - opStructFieldFloat64Indent opType = 721 - opStructFieldBoolIndent opType = 722 - opStructFieldStringIndent opType = 723 - opStructFieldBytesIndent opType = 724 - opStructFieldArrayIndent opType = 725 - opStructFieldMapIndent opType = 726 - opStructFieldMapLoadIndent opType = 727 - opStructFieldSliceIndent opType = 728 - opStructFieldStructIndent opType = 729 - opStructFieldMarshalJSONIndent opType = 730 - opStructFieldMarshalTextIndent opType = 731 - opStructFieldOmitEmptyIntIndent opType = 732 - opStructFieldOmitEmptyInt8Indent opType = 733 - opStructFieldOmitEmptyInt16Indent opType = 734 - opStructFieldOmitEmptyInt32Indent opType = 735 - opStructFieldOmitEmptyInt64Indent opType = 736 - opStructFieldOmitEmptyUintIndent opType = 737 - opStructFieldOmitEmptyUint8Indent opType = 738 - opStructFieldOmitEmptyUint16Indent opType = 739 - opStructFieldOmitEmptyUint32Indent opType = 740 - opStructFieldOmitEmptyUint64Indent opType = 741 - opStructFieldOmitEmptyFloat32Indent opType = 742 - opStructFieldOmitEmptyFloat64Indent opType = 743 - opStructFieldOmitEmptyBoolIndent opType = 744 - opStructFieldOmitEmptyStringIndent opType = 745 - opStructFieldOmitEmptyBytesIndent opType = 746 - opStructFieldOmitEmptyArrayIndent opType = 747 - opStructFieldOmitEmptyMapIndent opType = 748 - opStructFieldOmitEmptyMapLoadIndent opType = 749 - opStructFieldOmitEmptySliceIndent opType = 750 - opStructFieldOmitEmptyStructIndent opType = 751 - opStructFieldOmitEmptyMarshalJSONIndent opType = 752 - opStructFieldOmitEmptyMarshalTextIndent opType = 753 - opStructFieldStringTagIntIndent opType = 754 - opStructFieldStringTagInt8Indent opType = 755 - opStructFieldStringTagInt16Indent opType = 756 - opStructFieldStringTagInt32Indent opType = 757 - opStructFieldStringTagInt64Indent opType = 758 - opStructFieldStringTagUintIndent opType = 759 - opStructFieldStringTagUint8Indent opType = 760 - opStructFieldStringTagUint16Indent opType = 761 - opStructFieldStringTagUint32Indent opType = 762 - opStructFieldStringTagUint64Indent opType = 763 - opStructFieldStringTagFloat32Indent opType = 764 - opStructFieldStringTagFloat64Indent opType = 765 - opStructFieldStringTagBoolIndent opType = 766 - opStructFieldStringTagStringIndent opType = 767 - opStructFieldStringTagBytesIndent opType = 768 - opStructFieldStringTagArrayIndent opType = 769 - opStructFieldStringTagMapIndent opType = 770 - opStructFieldStringTagMapLoadIndent opType = 771 - opStructFieldStringTagSliceIndent opType = 772 - opStructFieldStringTagStructIndent opType = 773 - opStructFieldStringTagMarshalJSONIndent opType = 774 - opStructFieldStringTagMarshalTextIndent opType = 775 + opInterfaceEnd opType = 2 + opPtr opType = 3 + opSliceHead opType = 4 + opRootSliceHead opType = 5 + opSliceElem opType = 6 + opRootSliceElem opType = 7 + opSliceEnd opType = 8 + opArrayHead opType = 9 + opArrayElem opType = 10 + opArrayEnd opType = 11 + opMapHead opType = 12 + opMapHeadLoad opType = 13 + opRootMapHead opType = 14 + opMapKey opType = 15 + opRootMapKey opType = 16 + opMapValue opType = 17 + opMapEnd opType = 18 + opStructFieldHead opType = 19 + opStructFieldHeadOmitEmpty opType = 20 + opStructFieldHeadStringTag opType = 21 + opStructFieldAnonymousHead opType = 22 + opStructFieldAnonymousHeadOmitEmpty opType = 23 + opStructFieldPtrAnonymousHeadOmitEmpty opType = 24 + opStructFieldAnonymousHeadStringTag opType = 25 + opStructFieldPtrAnonymousHeadStringTag opType = 26 + opStructFieldPtrHead opType = 27 + opStructFieldPtrHeadOmitEmpty opType = 28 + opStructFieldPtrHeadStringTag opType = 29 + opStructFieldPtrAnonymousHead opType = 30 + opStructField opType = 31 + opStructFieldOmitEmpty opType = 32 + opStructFieldStringTag opType = 33 + opStructFieldRecursive opType = 34 + opStructFieldRecursiveEnd opType = 35 + opStructEnd opType = 36 + opStructAnonymousEnd opType = 37 + opInt opType = 38 + opInt8 opType = 39 + opInt16 opType = 40 + opInt32 opType = 41 + opInt64 opType = 42 + opUint opType = 43 + opUint8 opType = 44 + opUint16 opType = 45 + opUint32 opType = 46 + opUint64 opType = 47 + opFloat32 opType = 48 + opFloat64 opType = 49 + opBool opType = 50 + opString opType = 51 + opBytes opType = 52 + opArray opType = 53 + opMap opType = 54 + opMapLoad opType = 55 + opSlice opType = 56 + opStruct opType = 57 + opMarshalJSON opType = 58 + opMarshalText opType = 59 + opStructFieldHeadInt opType = 60 + opStructFieldHeadInt8 opType = 61 + opStructFieldHeadInt16 opType = 62 + opStructFieldHeadInt32 opType = 63 + opStructFieldHeadInt64 opType = 64 + opStructFieldHeadUint opType = 65 + opStructFieldHeadUint8 opType = 66 + opStructFieldHeadUint16 opType = 67 + opStructFieldHeadUint32 opType = 68 + opStructFieldHeadUint64 opType = 69 + opStructFieldHeadFloat32 opType = 70 + opStructFieldHeadFloat64 opType = 71 + opStructFieldHeadBool opType = 72 + opStructFieldHeadString opType = 73 + opStructFieldHeadBytes opType = 74 + opStructFieldHeadArray opType = 75 + opStructFieldHeadMap opType = 76 + opStructFieldHeadMapLoad opType = 77 + opStructFieldHeadSlice opType = 78 + opStructFieldHeadStruct opType = 79 + opStructFieldHeadMarshalJSON opType = 80 + opStructFieldHeadMarshalText opType = 81 + opStructFieldHeadOmitEmptyInt opType = 82 + opStructFieldHeadOmitEmptyInt8 opType = 83 + opStructFieldHeadOmitEmptyInt16 opType = 84 + opStructFieldHeadOmitEmptyInt32 opType = 85 + opStructFieldHeadOmitEmptyInt64 opType = 86 + opStructFieldHeadOmitEmptyUint opType = 87 + opStructFieldHeadOmitEmptyUint8 opType = 88 + opStructFieldHeadOmitEmptyUint16 opType = 89 + opStructFieldHeadOmitEmptyUint32 opType = 90 + opStructFieldHeadOmitEmptyUint64 opType = 91 + opStructFieldHeadOmitEmptyFloat32 opType = 92 + opStructFieldHeadOmitEmptyFloat64 opType = 93 + opStructFieldHeadOmitEmptyBool opType = 94 + opStructFieldHeadOmitEmptyString opType = 95 + opStructFieldHeadOmitEmptyBytes opType = 96 + opStructFieldHeadOmitEmptyArray opType = 97 + opStructFieldHeadOmitEmptyMap opType = 98 + opStructFieldHeadOmitEmptyMapLoad opType = 99 + opStructFieldHeadOmitEmptySlice opType = 100 + opStructFieldHeadOmitEmptyStruct opType = 101 + opStructFieldHeadOmitEmptyMarshalJSON opType = 102 + opStructFieldHeadOmitEmptyMarshalText opType = 103 + opStructFieldHeadStringTagInt opType = 104 + opStructFieldHeadStringTagInt8 opType = 105 + opStructFieldHeadStringTagInt16 opType = 106 + opStructFieldHeadStringTagInt32 opType = 107 + opStructFieldHeadStringTagInt64 opType = 108 + opStructFieldHeadStringTagUint opType = 109 + opStructFieldHeadStringTagUint8 opType = 110 + opStructFieldHeadStringTagUint16 opType = 111 + opStructFieldHeadStringTagUint32 opType = 112 + opStructFieldHeadStringTagUint64 opType = 113 + opStructFieldHeadStringTagFloat32 opType = 114 + opStructFieldHeadStringTagFloat64 opType = 115 + opStructFieldHeadStringTagBool opType = 116 + opStructFieldHeadStringTagString opType = 117 + opStructFieldHeadStringTagBytes opType = 118 + opStructFieldHeadStringTagArray opType = 119 + opStructFieldHeadStringTagMap opType = 120 + opStructFieldHeadStringTagMapLoad opType = 121 + opStructFieldHeadStringTagSlice opType = 122 + opStructFieldHeadStringTagStruct opType = 123 + opStructFieldHeadStringTagMarshalJSON opType = 124 + opStructFieldHeadStringTagMarshalText opType = 125 + opStructFieldAnonymousHeadInt opType = 126 + opStructFieldAnonymousHeadInt8 opType = 127 + opStructFieldAnonymousHeadInt16 opType = 128 + opStructFieldAnonymousHeadInt32 opType = 129 + opStructFieldAnonymousHeadInt64 opType = 130 + opStructFieldAnonymousHeadUint opType = 131 + opStructFieldAnonymousHeadUint8 opType = 132 + opStructFieldAnonymousHeadUint16 opType = 133 + opStructFieldAnonymousHeadUint32 opType = 134 + opStructFieldAnonymousHeadUint64 opType = 135 + opStructFieldAnonymousHeadFloat32 opType = 136 + opStructFieldAnonymousHeadFloat64 opType = 137 + opStructFieldAnonymousHeadBool opType = 138 + opStructFieldAnonymousHeadString opType = 139 + opStructFieldAnonymousHeadBytes opType = 140 + opStructFieldAnonymousHeadArray opType = 141 + opStructFieldAnonymousHeadMap opType = 142 + opStructFieldAnonymousHeadMapLoad opType = 143 + opStructFieldAnonymousHeadSlice opType = 144 + opStructFieldAnonymousHeadStruct opType = 145 + opStructFieldAnonymousHeadMarshalJSON opType = 146 + opStructFieldAnonymousHeadMarshalText opType = 147 + opStructFieldAnonymousHeadOmitEmptyInt opType = 148 + opStructFieldAnonymousHeadOmitEmptyInt8 opType = 149 + opStructFieldAnonymousHeadOmitEmptyInt16 opType = 150 + opStructFieldAnonymousHeadOmitEmptyInt32 opType = 151 + opStructFieldAnonymousHeadOmitEmptyInt64 opType = 152 + opStructFieldAnonymousHeadOmitEmptyUint opType = 153 + opStructFieldAnonymousHeadOmitEmptyUint8 opType = 154 + opStructFieldAnonymousHeadOmitEmptyUint16 opType = 155 + opStructFieldAnonymousHeadOmitEmptyUint32 opType = 156 + opStructFieldAnonymousHeadOmitEmptyUint64 opType = 157 + opStructFieldAnonymousHeadOmitEmptyFloat32 opType = 158 + opStructFieldAnonymousHeadOmitEmptyFloat64 opType = 159 + opStructFieldAnonymousHeadOmitEmptyBool opType = 160 + opStructFieldAnonymousHeadOmitEmptyString opType = 161 + opStructFieldAnonymousHeadOmitEmptyBytes opType = 162 + opStructFieldAnonymousHeadOmitEmptyArray opType = 163 + opStructFieldAnonymousHeadOmitEmptyMap opType = 164 + opStructFieldAnonymousHeadOmitEmptyMapLoad opType = 165 + opStructFieldAnonymousHeadOmitEmptySlice opType = 166 + opStructFieldAnonymousHeadOmitEmptyStruct opType = 167 + opStructFieldAnonymousHeadOmitEmptyMarshalJSON opType = 168 + opStructFieldAnonymousHeadOmitEmptyMarshalText opType = 169 + opStructFieldAnonymousHeadStringTagInt opType = 170 + opStructFieldAnonymousHeadStringTagInt8 opType = 171 + opStructFieldAnonymousHeadStringTagInt16 opType = 172 + opStructFieldAnonymousHeadStringTagInt32 opType = 173 + opStructFieldAnonymousHeadStringTagInt64 opType = 174 + opStructFieldAnonymousHeadStringTagUint opType = 175 + opStructFieldAnonymousHeadStringTagUint8 opType = 176 + opStructFieldAnonymousHeadStringTagUint16 opType = 177 + opStructFieldAnonymousHeadStringTagUint32 opType = 178 + opStructFieldAnonymousHeadStringTagUint64 opType = 179 + opStructFieldAnonymousHeadStringTagFloat32 opType = 180 + opStructFieldAnonymousHeadStringTagFloat64 opType = 181 + opStructFieldAnonymousHeadStringTagBool opType = 182 + opStructFieldAnonymousHeadStringTagString opType = 183 + opStructFieldAnonymousHeadStringTagBytes opType = 184 + opStructFieldAnonymousHeadStringTagArray opType = 185 + opStructFieldAnonymousHeadStringTagMap opType = 186 + opStructFieldAnonymousHeadStringTagMapLoad opType = 187 + opStructFieldAnonymousHeadStringTagSlice opType = 188 + opStructFieldAnonymousHeadStringTagStruct opType = 189 + opStructFieldAnonymousHeadStringTagMarshalJSON opType = 190 + opStructFieldAnonymousHeadStringTagMarshalText opType = 191 + opStructFieldPtrHeadInt opType = 192 + opStructFieldPtrHeadInt8 opType = 193 + opStructFieldPtrHeadInt16 opType = 194 + opStructFieldPtrHeadInt32 opType = 195 + opStructFieldPtrHeadInt64 opType = 196 + opStructFieldPtrHeadUint opType = 197 + opStructFieldPtrHeadUint8 opType = 198 + opStructFieldPtrHeadUint16 opType = 199 + opStructFieldPtrHeadUint32 opType = 200 + opStructFieldPtrHeadUint64 opType = 201 + opStructFieldPtrHeadFloat32 opType = 202 + opStructFieldPtrHeadFloat64 opType = 203 + opStructFieldPtrHeadBool opType = 204 + opStructFieldPtrHeadString opType = 205 + opStructFieldPtrHeadBytes opType = 206 + opStructFieldPtrHeadArray opType = 207 + opStructFieldPtrHeadMap opType = 208 + opStructFieldPtrHeadMapLoad opType = 209 + opStructFieldPtrHeadSlice opType = 210 + opStructFieldPtrHeadStruct opType = 211 + opStructFieldPtrHeadMarshalJSON opType = 212 + opStructFieldPtrHeadMarshalText opType = 213 + opStructFieldPtrHeadOmitEmptyInt opType = 214 + opStructFieldPtrHeadOmitEmptyInt8 opType = 215 + opStructFieldPtrHeadOmitEmptyInt16 opType = 216 + opStructFieldPtrHeadOmitEmptyInt32 opType = 217 + opStructFieldPtrHeadOmitEmptyInt64 opType = 218 + opStructFieldPtrHeadOmitEmptyUint opType = 219 + opStructFieldPtrHeadOmitEmptyUint8 opType = 220 + opStructFieldPtrHeadOmitEmptyUint16 opType = 221 + opStructFieldPtrHeadOmitEmptyUint32 opType = 222 + opStructFieldPtrHeadOmitEmptyUint64 opType = 223 + opStructFieldPtrHeadOmitEmptyFloat32 opType = 224 + opStructFieldPtrHeadOmitEmptyFloat64 opType = 225 + opStructFieldPtrHeadOmitEmptyBool opType = 226 + opStructFieldPtrHeadOmitEmptyString opType = 227 + opStructFieldPtrHeadOmitEmptyBytes opType = 228 + opStructFieldPtrHeadOmitEmptyArray opType = 229 + opStructFieldPtrHeadOmitEmptyMap opType = 230 + opStructFieldPtrHeadOmitEmptyMapLoad opType = 231 + opStructFieldPtrHeadOmitEmptySlice opType = 232 + opStructFieldPtrHeadOmitEmptyStruct opType = 233 + opStructFieldPtrHeadOmitEmptyMarshalJSON opType = 234 + opStructFieldPtrHeadOmitEmptyMarshalText opType = 235 + opStructFieldPtrHeadStringTagInt opType = 236 + opStructFieldPtrHeadStringTagInt8 opType = 237 + opStructFieldPtrHeadStringTagInt16 opType = 238 + opStructFieldPtrHeadStringTagInt32 opType = 239 + opStructFieldPtrHeadStringTagInt64 opType = 240 + opStructFieldPtrHeadStringTagUint opType = 241 + opStructFieldPtrHeadStringTagUint8 opType = 242 + opStructFieldPtrHeadStringTagUint16 opType = 243 + opStructFieldPtrHeadStringTagUint32 opType = 244 + opStructFieldPtrHeadStringTagUint64 opType = 245 + opStructFieldPtrHeadStringTagFloat32 opType = 246 + opStructFieldPtrHeadStringTagFloat64 opType = 247 + opStructFieldPtrHeadStringTagBool opType = 248 + opStructFieldPtrHeadStringTagString opType = 249 + opStructFieldPtrHeadStringTagBytes opType = 250 + opStructFieldPtrHeadStringTagArray opType = 251 + opStructFieldPtrHeadStringTagMap opType = 252 + opStructFieldPtrHeadStringTagMapLoad opType = 253 + opStructFieldPtrHeadStringTagSlice opType = 254 + opStructFieldPtrHeadStringTagStruct opType = 255 + opStructFieldPtrHeadStringTagMarshalJSON opType = 256 + opStructFieldPtrHeadStringTagMarshalText opType = 257 + opStructFieldPtrAnonymousHeadInt opType = 258 + opStructFieldPtrAnonymousHeadInt8 opType = 259 + opStructFieldPtrAnonymousHeadInt16 opType = 260 + opStructFieldPtrAnonymousHeadInt32 opType = 261 + opStructFieldPtrAnonymousHeadInt64 opType = 262 + opStructFieldPtrAnonymousHeadUint opType = 263 + opStructFieldPtrAnonymousHeadUint8 opType = 264 + opStructFieldPtrAnonymousHeadUint16 opType = 265 + opStructFieldPtrAnonymousHeadUint32 opType = 266 + opStructFieldPtrAnonymousHeadUint64 opType = 267 + opStructFieldPtrAnonymousHeadFloat32 opType = 268 + opStructFieldPtrAnonymousHeadFloat64 opType = 269 + opStructFieldPtrAnonymousHeadBool opType = 270 + opStructFieldPtrAnonymousHeadString opType = 271 + opStructFieldPtrAnonymousHeadBytes opType = 272 + opStructFieldPtrAnonymousHeadArray opType = 273 + opStructFieldPtrAnonymousHeadMap opType = 274 + opStructFieldPtrAnonymousHeadMapLoad opType = 275 + opStructFieldPtrAnonymousHeadSlice opType = 276 + opStructFieldPtrAnonymousHeadStruct opType = 277 + opStructFieldPtrAnonymousHeadMarshalJSON opType = 278 + opStructFieldPtrAnonymousHeadMarshalText opType = 279 + opStructFieldPtrAnonymousHeadOmitEmptyInt opType = 280 + opStructFieldPtrAnonymousHeadOmitEmptyInt8 opType = 281 + opStructFieldPtrAnonymousHeadOmitEmptyInt16 opType = 282 + opStructFieldPtrAnonymousHeadOmitEmptyInt32 opType = 283 + opStructFieldPtrAnonymousHeadOmitEmptyInt64 opType = 284 + opStructFieldPtrAnonymousHeadOmitEmptyUint opType = 285 + opStructFieldPtrAnonymousHeadOmitEmptyUint8 opType = 286 + opStructFieldPtrAnonymousHeadOmitEmptyUint16 opType = 287 + opStructFieldPtrAnonymousHeadOmitEmptyUint32 opType = 288 + opStructFieldPtrAnonymousHeadOmitEmptyUint64 opType = 289 + opStructFieldPtrAnonymousHeadOmitEmptyFloat32 opType = 290 + opStructFieldPtrAnonymousHeadOmitEmptyFloat64 opType = 291 + opStructFieldPtrAnonymousHeadOmitEmptyBool opType = 292 + opStructFieldPtrAnonymousHeadOmitEmptyString opType = 293 + opStructFieldPtrAnonymousHeadOmitEmptyBytes opType = 294 + opStructFieldPtrAnonymousHeadOmitEmptyArray opType = 295 + opStructFieldPtrAnonymousHeadOmitEmptyMap opType = 296 + opStructFieldPtrAnonymousHeadOmitEmptyMapLoad opType = 297 + opStructFieldPtrAnonymousHeadOmitEmptySlice opType = 298 + opStructFieldPtrAnonymousHeadOmitEmptyStruct opType = 299 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSON opType = 300 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalText opType = 301 + opStructFieldPtrAnonymousHeadStringTagInt opType = 302 + opStructFieldPtrAnonymousHeadStringTagInt8 opType = 303 + opStructFieldPtrAnonymousHeadStringTagInt16 opType = 304 + opStructFieldPtrAnonymousHeadStringTagInt32 opType = 305 + opStructFieldPtrAnonymousHeadStringTagInt64 opType = 306 + opStructFieldPtrAnonymousHeadStringTagUint opType = 307 + opStructFieldPtrAnonymousHeadStringTagUint8 opType = 308 + opStructFieldPtrAnonymousHeadStringTagUint16 opType = 309 + opStructFieldPtrAnonymousHeadStringTagUint32 opType = 310 + opStructFieldPtrAnonymousHeadStringTagUint64 opType = 311 + opStructFieldPtrAnonymousHeadStringTagFloat32 opType = 312 + opStructFieldPtrAnonymousHeadStringTagFloat64 opType = 313 + opStructFieldPtrAnonymousHeadStringTagBool opType = 314 + opStructFieldPtrAnonymousHeadStringTagString opType = 315 + opStructFieldPtrAnonymousHeadStringTagBytes opType = 316 + opStructFieldPtrAnonymousHeadStringTagArray opType = 317 + opStructFieldPtrAnonymousHeadStringTagMap opType = 318 + opStructFieldPtrAnonymousHeadStringTagMapLoad opType = 319 + opStructFieldPtrAnonymousHeadStringTagSlice opType = 320 + opStructFieldPtrAnonymousHeadStringTagStruct opType = 321 + opStructFieldPtrAnonymousHeadStringTagMarshalJSON opType = 322 + opStructFieldPtrAnonymousHeadStringTagMarshalText opType = 323 + opStructFieldInt opType = 324 + opStructFieldInt8 opType = 325 + opStructFieldInt16 opType = 326 + opStructFieldInt32 opType = 327 + opStructFieldInt64 opType = 328 + opStructFieldUint opType = 329 + opStructFieldUint8 opType = 330 + opStructFieldUint16 opType = 331 + opStructFieldUint32 opType = 332 + opStructFieldUint64 opType = 333 + opStructFieldFloat32 opType = 334 + opStructFieldFloat64 opType = 335 + opStructFieldBool opType = 336 + opStructFieldString opType = 337 + opStructFieldBytes opType = 338 + opStructFieldArray opType = 339 + opStructFieldMap opType = 340 + opStructFieldMapLoad opType = 341 + opStructFieldSlice opType = 342 + opStructFieldStruct opType = 343 + opStructFieldMarshalJSON opType = 344 + opStructFieldMarshalText opType = 345 + opStructFieldOmitEmptyInt opType = 346 + opStructFieldOmitEmptyInt8 opType = 347 + opStructFieldOmitEmptyInt16 opType = 348 + opStructFieldOmitEmptyInt32 opType = 349 + opStructFieldOmitEmptyInt64 opType = 350 + opStructFieldOmitEmptyUint opType = 351 + opStructFieldOmitEmptyUint8 opType = 352 + opStructFieldOmitEmptyUint16 opType = 353 + opStructFieldOmitEmptyUint32 opType = 354 + opStructFieldOmitEmptyUint64 opType = 355 + opStructFieldOmitEmptyFloat32 opType = 356 + opStructFieldOmitEmptyFloat64 opType = 357 + opStructFieldOmitEmptyBool opType = 358 + opStructFieldOmitEmptyString opType = 359 + opStructFieldOmitEmptyBytes opType = 360 + opStructFieldOmitEmptyArray opType = 361 + opStructFieldOmitEmptyMap opType = 362 + opStructFieldOmitEmptyMapLoad opType = 363 + opStructFieldOmitEmptySlice opType = 364 + opStructFieldOmitEmptyStruct opType = 365 + opStructFieldOmitEmptyMarshalJSON opType = 366 + opStructFieldOmitEmptyMarshalText opType = 367 + opStructFieldStringTagInt opType = 368 + opStructFieldStringTagInt8 opType = 369 + opStructFieldStringTagInt16 opType = 370 + opStructFieldStringTagInt32 opType = 371 + opStructFieldStringTagInt64 opType = 372 + opStructFieldStringTagUint opType = 373 + opStructFieldStringTagUint8 opType = 374 + opStructFieldStringTagUint16 opType = 375 + opStructFieldStringTagUint32 opType = 376 + opStructFieldStringTagUint64 opType = 377 + opStructFieldStringTagFloat32 opType = 378 + opStructFieldStringTagFloat64 opType = 379 + opStructFieldStringTagBool opType = 380 + opStructFieldStringTagString opType = 381 + opStructFieldStringTagBytes opType = 382 + opStructFieldStringTagArray opType = 383 + opStructFieldStringTagMap opType = 384 + opStructFieldStringTagMapLoad opType = 385 + opStructFieldStringTagSlice opType = 386 + opStructFieldStringTagStruct opType = 387 + opStructFieldStringTagMarshalJSON opType = 388 + opStructFieldStringTagMarshalText opType = 389 + opEndIndent opType = 390 + opInterfaceIndent opType = 391 + opInterfaceEndIndent opType = 392 + opPtrIndent opType = 393 + opSliceHeadIndent opType = 394 + opRootSliceHeadIndent opType = 395 + opSliceElemIndent opType = 396 + opRootSliceElemIndent opType = 397 + opSliceEndIndent opType = 398 + opArrayHeadIndent opType = 399 + opArrayElemIndent opType = 400 + opArrayEndIndent opType = 401 + opMapHeadIndent opType = 402 + opMapHeadLoadIndent opType = 403 + opRootMapHeadIndent opType = 404 + opMapKeyIndent opType = 405 + opRootMapKeyIndent opType = 406 + opMapValueIndent opType = 407 + opMapEndIndent opType = 408 + opStructFieldHeadIndent opType = 409 + opStructFieldHeadOmitEmptyIndent opType = 410 + opStructFieldHeadStringTagIndent opType = 411 + opStructFieldAnonymousHeadIndent opType = 412 + opStructFieldAnonymousHeadOmitEmptyIndent opType = 413 + opStructFieldPtrAnonymousHeadOmitEmptyIndent opType = 414 + opStructFieldAnonymousHeadStringTagIndent opType = 415 + opStructFieldPtrAnonymousHeadStringTagIndent opType = 416 + opStructFieldPtrHeadIndent opType = 417 + opStructFieldPtrHeadOmitEmptyIndent opType = 418 + opStructFieldPtrHeadStringTagIndent opType = 419 + opStructFieldPtrAnonymousHeadIndent opType = 420 + opStructFieldIndent opType = 421 + opStructFieldOmitEmptyIndent opType = 422 + opStructFieldStringTagIndent opType = 423 + opStructFieldRecursiveIndent opType = 424 + opStructFieldRecursiveEndIndent opType = 425 + opStructEndIndent opType = 426 + opStructAnonymousEndIndent opType = 427 + opIntIndent opType = 428 + opInt8Indent opType = 429 + opInt16Indent opType = 430 + opInt32Indent opType = 431 + opInt64Indent opType = 432 + opUintIndent opType = 433 + opUint8Indent opType = 434 + opUint16Indent opType = 435 + opUint32Indent opType = 436 + opUint64Indent opType = 437 + opFloat32Indent opType = 438 + opFloat64Indent opType = 439 + opBoolIndent opType = 440 + opStringIndent opType = 441 + opBytesIndent opType = 442 + opArrayIndent opType = 443 + opMapIndent opType = 444 + opMapLoadIndent opType = 445 + opSliceIndent opType = 446 + opStructIndent opType = 447 + opMarshalJSONIndent opType = 448 + opMarshalTextIndent opType = 449 + opStructFieldHeadIntIndent opType = 450 + opStructFieldHeadInt8Indent opType = 451 + opStructFieldHeadInt16Indent opType = 452 + opStructFieldHeadInt32Indent opType = 453 + opStructFieldHeadInt64Indent opType = 454 + opStructFieldHeadUintIndent opType = 455 + opStructFieldHeadUint8Indent opType = 456 + opStructFieldHeadUint16Indent opType = 457 + opStructFieldHeadUint32Indent opType = 458 + opStructFieldHeadUint64Indent opType = 459 + opStructFieldHeadFloat32Indent opType = 460 + opStructFieldHeadFloat64Indent opType = 461 + opStructFieldHeadBoolIndent opType = 462 + opStructFieldHeadStringIndent opType = 463 + opStructFieldHeadBytesIndent opType = 464 + opStructFieldHeadArrayIndent opType = 465 + opStructFieldHeadMapIndent opType = 466 + opStructFieldHeadMapLoadIndent opType = 467 + opStructFieldHeadSliceIndent opType = 468 + opStructFieldHeadStructIndent opType = 469 + opStructFieldHeadMarshalJSONIndent opType = 470 + opStructFieldHeadMarshalTextIndent opType = 471 + opStructFieldHeadOmitEmptyIntIndent opType = 472 + opStructFieldHeadOmitEmptyInt8Indent opType = 473 + opStructFieldHeadOmitEmptyInt16Indent opType = 474 + opStructFieldHeadOmitEmptyInt32Indent opType = 475 + opStructFieldHeadOmitEmptyInt64Indent opType = 476 + opStructFieldHeadOmitEmptyUintIndent opType = 477 + opStructFieldHeadOmitEmptyUint8Indent opType = 478 + opStructFieldHeadOmitEmptyUint16Indent opType = 479 + opStructFieldHeadOmitEmptyUint32Indent opType = 480 + opStructFieldHeadOmitEmptyUint64Indent opType = 481 + opStructFieldHeadOmitEmptyFloat32Indent opType = 482 + opStructFieldHeadOmitEmptyFloat64Indent opType = 483 + opStructFieldHeadOmitEmptyBoolIndent opType = 484 + opStructFieldHeadOmitEmptyStringIndent opType = 485 + opStructFieldHeadOmitEmptyBytesIndent opType = 486 + opStructFieldHeadOmitEmptyArrayIndent opType = 487 + opStructFieldHeadOmitEmptyMapIndent opType = 488 + opStructFieldHeadOmitEmptyMapLoadIndent opType = 489 + opStructFieldHeadOmitEmptySliceIndent opType = 490 + opStructFieldHeadOmitEmptyStructIndent opType = 491 + opStructFieldHeadOmitEmptyMarshalJSONIndent opType = 492 + opStructFieldHeadOmitEmptyMarshalTextIndent opType = 493 + opStructFieldHeadStringTagIntIndent opType = 494 + opStructFieldHeadStringTagInt8Indent opType = 495 + opStructFieldHeadStringTagInt16Indent opType = 496 + opStructFieldHeadStringTagInt32Indent opType = 497 + opStructFieldHeadStringTagInt64Indent opType = 498 + opStructFieldHeadStringTagUintIndent opType = 499 + opStructFieldHeadStringTagUint8Indent opType = 500 + opStructFieldHeadStringTagUint16Indent opType = 501 + opStructFieldHeadStringTagUint32Indent opType = 502 + opStructFieldHeadStringTagUint64Indent opType = 503 + opStructFieldHeadStringTagFloat32Indent opType = 504 + opStructFieldHeadStringTagFloat64Indent opType = 505 + opStructFieldHeadStringTagBoolIndent opType = 506 + opStructFieldHeadStringTagStringIndent opType = 507 + opStructFieldHeadStringTagBytesIndent opType = 508 + opStructFieldHeadStringTagArrayIndent opType = 509 + opStructFieldHeadStringTagMapIndent opType = 510 + opStructFieldHeadStringTagMapLoadIndent opType = 511 + opStructFieldHeadStringTagSliceIndent opType = 512 + opStructFieldHeadStringTagStructIndent opType = 513 + opStructFieldHeadStringTagMarshalJSONIndent opType = 514 + opStructFieldHeadStringTagMarshalTextIndent opType = 515 + opStructFieldAnonymousHeadIntIndent opType = 516 + opStructFieldAnonymousHeadInt8Indent opType = 517 + opStructFieldAnonymousHeadInt16Indent opType = 518 + opStructFieldAnonymousHeadInt32Indent opType = 519 + opStructFieldAnonymousHeadInt64Indent opType = 520 + opStructFieldAnonymousHeadUintIndent opType = 521 + opStructFieldAnonymousHeadUint8Indent opType = 522 + opStructFieldAnonymousHeadUint16Indent opType = 523 + opStructFieldAnonymousHeadUint32Indent opType = 524 + opStructFieldAnonymousHeadUint64Indent opType = 525 + opStructFieldAnonymousHeadFloat32Indent opType = 526 + opStructFieldAnonymousHeadFloat64Indent opType = 527 + opStructFieldAnonymousHeadBoolIndent opType = 528 + opStructFieldAnonymousHeadStringIndent opType = 529 + opStructFieldAnonymousHeadBytesIndent opType = 530 + opStructFieldAnonymousHeadArrayIndent opType = 531 + opStructFieldAnonymousHeadMapIndent opType = 532 + opStructFieldAnonymousHeadMapLoadIndent opType = 533 + opStructFieldAnonymousHeadSliceIndent opType = 534 + opStructFieldAnonymousHeadStructIndent opType = 535 + opStructFieldAnonymousHeadMarshalJSONIndent opType = 536 + opStructFieldAnonymousHeadMarshalTextIndent opType = 537 + opStructFieldAnonymousHeadOmitEmptyIntIndent opType = 538 + opStructFieldAnonymousHeadOmitEmptyInt8Indent opType = 539 + opStructFieldAnonymousHeadOmitEmptyInt16Indent opType = 540 + opStructFieldAnonymousHeadOmitEmptyInt32Indent opType = 541 + opStructFieldAnonymousHeadOmitEmptyInt64Indent opType = 542 + opStructFieldAnonymousHeadOmitEmptyUintIndent opType = 543 + opStructFieldAnonymousHeadOmitEmptyUint8Indent opType = 544 + opStructFieldAnonymousHeadOmitEmptyUint16Indent opType = 545 + opStructFieldAnonymousHeadOmitEmptyUint32Indent opType = 546 + opStructFieldAnonymousHeadOmitEmptyUint64Indent opType = 547 + opStructFieldAnonymousHeadOmitEmptyFloat32Indent opType = 548 + opStructFieldAnonymousHeadOmitEmptyFloat64Indent opType = 549 + opStructFieldAnonymousHeadOmitEmptyBoolIndent opType = 550 + opStructFieldAnonymousHeadOmitEmptyStringIndent opType = 551 + opStructFieldAnonymousHeadOmitEmptyBytesIndent opType = 552 + opStructFieldAnonymousHeadOmitEmptyArrayIndent opType = 553 + opStructFieldAnonymousHeadOmitEmptyMapIndent opType = 554 + opStructFieldAnonymousHeadOmitEmptyMapLoadIndent opType = 555 + opStructFieldAnonymousHeadOmitEmptySliceIndent opType = 556 + opStructFieldAnonymousHeadOmitEmptyStructIndent opType = 557 + opStructFieldAnonymousHeadOmitEmptyMarshalJSONIndent opType = 558 + opStructFieldAnonymousHeadOmitEmptyMarshalTextIndent opType = 559 + opStructFieldAnonymousHeadStringTagIntIndent opType = 560 + opStructFieldAnonymousHeadStringTagInt8Indent opType = 561 + opStructFieldAnonymousHeadStringTagInt16Indent opType = 562 + opStructFieldAnonymousHeadStringTagInt32Indent opType = 563 + opStructFieldAnonymousHeadStringTagInt64Indent opType = 564 + opStructFieldAnonymousHeadStringTagUintIndent opType = 565 + opStructFieldAnonymousHeadStringTagUint8Indent opType = 566 + opStructFieldAnonymousHeadStringTagUint16Indent opType = 567 + opStructFieldAnonymousHeadStringTagUint32Indent opType = 568 + opStructFieldAnonymousHeadStringTagUint64Indent opType = 569 + opStructFieldAnonymousHeadStringTagFloat32Indent opType = 570 + opStructFieldAnonymousHeadStringTagFloat64Indent opType = 571 + opStructFieldAnonymousHeadStringTagBoolIndent opType = 572 + opStructFieldAnonymousHeadStringTagStringIndent opType = 573 + opStructFieldAnonymousHeadStringTagBytesIndent opType = 574 + opStructFieldAnonymousHeadStringTagArrayIndent opType = 575 + opStructFieldAnonymousHeadStringTagMapIndent opType = 576 + opStructFieldAnonymousHeadStringTagMapLoadIndent opType = 577 + opStructFieldAnonymousHeadStringTagSliceIndent opType = 578 + opStructFieldAnonymousHeadStringTagStructIndent opType = 579 + opStructFieldAnonymousHeadStringTagMarshalJSONIndent opType = 580 + opStructFieldAnonymousHeadStringTagMarshalTextIndent opType = 581 + opStructFieldPtrHeadIntIndent opType = 582 + opStructFieldPtrHeadInt8Indent opType = 583 + opStructFieldPtrHeadInt16Indent opType = 584 + opStructFieldPtrHeadInt32Indent opType = 585 + opStructFieldPtrHeadInt64Indent opType = 586 + opStructFieldPtrHeadUintIndent opType = 587 + opStructFieldPtrHeadUint8Indent opType = 588 + opStructFieldPtrHeadUint16Indent opType = 589 + opStructFieldPtrHeadUint32Indent opType = 590 + opStructFieldPtrHeadUint64Indent opType = 591 + opStructFieldPtrHeadFloat32Indent opType = 592 + opStructFieldPtrHeadFloat64Indent opType = 593 + opStructFieldPtrHeadBoolIndent opType = 594 + opStructFieldPtrHeadStringIndent opType = 595 + opStructFieldPtrHeadBytesIndent opType = 596 + opStructFieldPtrHeadArrayIndent opType = 597 + opStructFieldPtrHeadMapIndent opType = 598 + opStructFieldPtrHeadMapLoadIndent opType = 599 + opStructFieldPtrHeadSliceIndent opType = 600 + opStructFieldPtrHeadStructIndent opType = 601 + opStructFieldPtrHeadMarshalJSONIndent opType = 602 + opStructFieldPtrHeadMarshalTextIndent opType = 603 + opStructFieldPtrHeadOmitEmptyIntIndent opType = 604 + opStructFieldPtrHeadOmitEmptyInt8Indent opType = 605 + opStructFieldPtrHeadOmitEmptyInt16Indent opType = 606 + opStructFieldPtrHeadOmitEmptyInt32Indent opType = 607 + opStructFieldPtrHeadOmitEmptyInt64Indent opType = 608 + opStructFieldPtrHeadOmitEmptyUintIndent opType = 609 + opStructFieldPtrHeadOmitEmptyUint8Indent opType = 610 + opStructFieldPtrHeadOmitEmptyUint16Indent opType = 611 + opStructFieldPtrHeadOmitEmptyUint32Indent opType = 612 + opStructFieldPtrHeadOmitEmptyUint64Indent opType = 613 + opStructFieldPtrHeadOmitEmptyFloat32Indent opType = 614 + opStructFieldPtrHeadOmitEmptyFloat64Indent opType = 615 + opStructFieldPtrHeadOmitEmptyBoolIndent opType = 616 + opStructFieldPtrHeadOmitEmptyStringIndent opType = 617 + opStructFieldPtrHeadOmitEmptyBytesIndent opType = 618 + opStructFieldPtrHeadOmitEmptyArrayIndent opType = 619 + opStructFieldPtrHeadOmitEmptyMapIndent opType = 620 + opStructFieldPtrHeadOmitEmptyMapLoadIndent opType = 621 + opStructFieldPtrHeadOmitEmptySliceIndent opType = 622 + opStructFieldPtrHeadOmitEmptyStructIndent opType = 623 + opStructFieldPtrHeadOmitEmptyMarshalJSONIndent opType = 624 + opStructFieldPtrHeadOmitEmptyMarshalTextIndent opType = 625 + opStructFieldPtrHeadStringTagIntIndent opType = 626 + opStructFieldPtrHeadStringTagInt8Indent opType = 627 + opStructFieldPtrHeadStringTagInt16Indent opType = 628 + opStructFieldPtrHeadStringTagInt32Indent opType = 629 + opStructFieldPtrHeadStringTagInt64Indent opType = 630 + opStructFieldPtrHeadStringTagUintIndent opType = 631 + opStructFieldPtrHeadStringTagUint8Indent opType = 632 + opStructFieldPtrHeadStringTagUint16Indent opType = 633 + opStructFieldPtrHeadStringTagUint32Indent opType = 634 + opStructFieldPtrHeadStringTagUint64Indent opType = 635 + opStructFieldPtrHeadStringTagFloat32Indent opType = 636 + opStructFieldPtrHeadStringTagFloat64Indent opType = 637 + opStructFieldPtrHeadStringTagBoolIndent opType = 638 + opStructFieldPtrHeadStringTagStringIndent opType = 639 + opStructFieldPtrHeadStringTagBytesIndent opType = 640 + opStructFieldPtrHeadStringTagArrayIndent opType = 641 + opStructFieldPtrHeadStringTagMapIndent opType = 642 + opStructFieldPtrHeadStringTagMapLoadIndent opType = 643 + opStructFieldPtrHeadStringTagSliceIndent opType = 644 + opStructFieldPtrHeadStringTagStructIndent opType = 645 + opStructFieldPtrHeadStringTagMarshalJSONIndent opType = 646 + opStructFieldPtrHeadStringTagMarshalTextIndent opType = 647 + opStructFieldPtrAnonymousHeadIntIndent opType = 648 + opStructFieldPtrAnonymousHeadInt8Indent opType = 649 + opStructFieldPtrAnonymousHeadInt16Indent opType = 650 + opStructFieldPtrAnonymousHeadInt32Indent opType = 651 + opStructFieldPtrAnonymousHeadInt64Indent opType = 652 + opStructFieldPtrAnonymousHeadUintIndent opType = 653 + opStructFieldPtrAnonymousHeadUint8Indent opType = 654 + opStructFieldPtrAnonymousHeadUint16Indent opType = 655 + opStructFieldPtrAnonymousHeadUint32Indent opType = 656 + opStructFieldPtrAnonymousHeadUint64Indent opType = 657 + opStructFieldPtrAnonymousHeadFloat32Indent opType = 658 + opStructFieldPtrAnonymousHeadFloat64Indent opType = 659 + opStructFieldPtrAnonymousHeadBoolIndent opType = 660 + opStructFieldPtrAnonymousHeadStringIndent opType = 661 + opStructFieldPtrAnonymousHeadBytesIndent opType = 662 + opStructFieldPtrAnonymousHeadArrayIndent opType = 663 + opStructFieldPtrAnonymousHeadMapIndent opType = 664 + opStructFieldPtrAnonymousHeadMapLoadIndent opType = 665 + opStructFieldPtrAnonymousHeadSliceIndent opType = 666 + opStructFieldPtrAnonymousHeadStructIndent opType = 667 + opStructFieldPtrAnonymousHeadMarshalJSONIndent opType = 668 + opStructFieldPtrAnonymousHeadMarshalTextIndent opType = 669 + opStructFieldPtrAnonymousHeadOmitEmptyIntIndent opType = 670 + opStructFieldPtrAnonymousHeadOmitEmptyInt8Indent opType = 671 + opStructFieldPtrAnonymousHeadOmitEmptyInt16Indent opType = 672 + opStructFieldPtrAnonymousHeadOmitEmptyInt32Indent opType = 673 + opStructFieldPtrAnonymousHeadOmitEmptyInt64Indent opType = 674 + opStructFieldPtrAnonymousHeadOmitEmptyUintIndent opType = 675 + opStructFieldPtrAnonymousHeadOmitEmptyUint8Indent opType = 676 + opStructFieldPtrAnonymousHeadOmitEmptyUint16Indent opType = 677 + opStructFieldPtrAnonymousHeadOmitEmptyUint32Indent opType = 678 + opStructFieldPtrAnonymousHeadOmitEmptyUint64Indent opType = 679 + opStructFieldPtrAnonymousHeadOmitEmptyFloat32Indent opType = 680 + opStructFieldPtrAnonymousHeadOmitEmptyFloat64Indent opType = 681 + opStructFieldPtrAnonymousHeadOmitEmptyBoolIndent opType = 682 + opStructFieldPtrAnonymousHeadOmitEmptyStringIndent opType = 683 + opStructFieldPtrAnonymousHeadOmitEmptyBytesIndent opType = 684 + opStructFieldPtrAnonymousHeadOmitEmptyArrayIndent opType = 685 + opStructFieldPtrAnonymousHeadOmitEmptyMapIndent opType = 686 + opStructFieldPtrAnonymousHeadOmitEmptyMapLoadIndent opType = 687 + opStructFieldPtrAnonymousHeadOmitEmptySliceIndent opType = 688 + opStructFieldPtrAnonymousHeadOmitEmptyStructIndent opType = 689 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSONIndent opType = 690 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalTextIndent opType = 691 + opStructFieldPtrAnonymousHeadStringTagIntIndent opType = 692 + opStructFieldPtrAnonymousHeadStringTagInt8Indent opType = 693 + opStructFieldPtrAnonymousHeadStringTagInt16Indent opType = 694 + opStructFieldPtrAnonymousHeadStringTagInt32Indent opType = 695 + opStructFieldPtrAnonymousHeadStringTagInt64Indent opType = 696 + opStructFieldPtrAnonymousHeadStringTagUintIndent opType = 697 + opStructFieldPtrAnonymousHeadStringTagUint8Indent opType = 698 + opStructFieldPtrAnonymousHeadStringTagUint16Indent opType = 699 + opStructFieldPtrAnonymousHeadStringTagUint32Indent opType = 700 + opStructFieldPtrAnonymousHeadStringTagUint64Indent opType = 701 + opStructFieldPtrAnonymousHeadStringTagFloat32Indent opType = 702 + opStructFieldPtrAnonymousHeadStringTagFloat64Indent opType = 703 + opStructFieldPtrAnonymousHeadStringTagBoolIndent opType = 704 + opStructFieldPtrAnonymousHeadStringTagStringIndent opType = 705 + opStructFieldPtrAnonymousHeadStringTagBytesIndent opType = 706 + opStructFieldPtrAnonymousHeadStringTagArrayIndent opType = 707 + opStructFieldPtrAnonymousHeadStringTagMapIndent opType = 708 + opStructFieldPtrAnonymousHeadStringTagMapLoadIndent opType = 709 + opStructFieldPtrAnonymousHeadStringTagSliceIndent opType = 710 + opStructFieldPtrAnonymousHeadStringTagStructIndent opType = 711 + opStructFieldPtrAnonymousHeadStringTagMarshalJSONIndent opType = 712 + opStructFieldPtrAnonymousHeadStringTagMarshalTextIndent opType = 713 + opStructFieldIntIndent opType = 714 + opStructFieldInt8Indent opType = 715 + opStructFieldInt16Indent opType = 716 + opStructFieldInt32Indent opType = 717 + opStructFieldInt64Indent opType = 718 + opStructFieldUintIndent opType = 719 + opStructFieldUint8Indent opType = 720 + opStructFieldUint16Indent opType = 721 + opStructFieldUint32Indent opType = 722 + opStructFieldUint64Indent opType = 723 + opStructFieldFloat32Indent opType = 724 + opStructFieldFloat64Indent opType = 725 + opStructFieldBoolIndent opType = 726 + opStructFieldStringIndent opType = 727 + opStructFieldBytesIndent opType = 728 + opStructFieldArrayIndent opType = 729 + opStructFieldMapIndent opType = 730 + opStructFieldMapLoadIndent opType = 731 + opStructFieldSliceIndent opType = 732 + opStructFieldStructIndent opType = 733 + opStructFieldMarshalJSONIndent opType = 734 + opStructFieldMarshalTextIndent opType = 735 + opStructFieldOmitEmptyIntIndent opType = 736 + opStructFieldOmitEmptyInt8Indent opType = 737 + opStructFieldOmitEmptyInt16Indent opType = 738 + opStructFieldOmitEmptyInt32Indent opType = 739 + opStructFieldOmitEmptyInt64Indent opType = 740 + opStructFieldOmitEmptyUintIndent opType = 741 + opStructFieldOmitEmptyUint8Indent opType = 742 + opStructFieldOmitEmptyUint16Indent opType = 743 + opStructFieldOmitEmptyUint32Indent opType = 744 + opStructFieldOmitEmptyUint64Indent opType = 745 + opStructFieldOmitEmptyFloat32Indent opType = 746 + opStructFieldOmitEmptyFloat64Indent opType = 747 + opStructFieldOmitEmptyBoolIndent opType = 748 + opStructFieldOmitEmptyStringIndent opType = 749 + opStructFieldOmitEmptyBytesIndent opType = 750 + opStructFieldOmitEmptyArrayIndent opType = 751 + opStructFieldOmitEmptyMapIndent opType = 752 + opStructFieldOmitEmptyMapLoadIndent opType = 753 + opStructFieldOmitEmptySliceIndent opType = 754 + opStructFieldOmitEmptyStructIndent opType = 755 + opStructFieldOmitEmptyMarshalJSONIndent opType = 756 + opStructFieldOmitEmptyMarshalTextIndent opType = 757 + opStructFieldStringTagIntIndent opType = 758 + opStructFieldStringTagInt8Indent opType = 759 + opStructFieldStringTagInt16Indent opType = 760 + opStructFieldStringTagInt32Indent opType = 761 + opStructFieldStringTagInt64Indent opType = 762 + opStructFieldStringTagUintIndent opType = 763 + opStructFieldStringTagUint8Indent opType = 764 + opStructFieldStringTagUint16Indent opType = 765 + opStructFieldStringTagUint32Indent opType = 766 + opStructFieldStringTagUint64Indent opType = 767 + opStructFieldStringTagFloat32Indent opType = 768 + opStructFieldStringTagFloat64Indent opType = 769 + opStructFieldStringTagBoolIndent opType = 770 + opStructFieldStringTagStringIndent opType = 771 + opStructFieldStringTagBytesIndent opType = 772 + opStructFieldStringTagArrayIndent opType = 773 + opStructFieldStringTagMapIndent opType = 774 + opStructFieldStringTagMapLoadIndent opType = 775 + opStructFieldStringTagSliceIndent opType = 776 + opStructFieldStringTagStructIndent opType = 777 + opStructFieldStringTagMarshalJSONIndent opType = 778 + opStructFieldStringTagMarshalTextIndent opType = 779 ) func (t opType) String() string { @@ -803,6 +807,8 @@ func (t opType) String() string { return "End" case opInterface: return "Interface" + case opInterfaceEnd: + return "InterfaceEnd" case opPtr: return "Ptr" case opSliceHead: @@ -867,6 +873,8 @@ func (t opType) String() string { return "StructFieldStringTag" case opStructFieldRecursive: return "StructFieldRecursive" + case opStructFieldRecursiveEnd: + return "StructFieldRecursiveEnd" case opStructEnd: return "StructEnd" case opStructAnonymousEnd: @@ -1579,6 +1587,8 @@ func (t opType) String() string { return "EndIndent" case opInterfaceIndent: return "InterfaceIndent" + case opInterfaceEndIndent: + return "InterfaceEndIndent" case opPtrIndent: return "PtrIndent" case opSliceHeadIndent: @@ -1643,6 +1653,8 @@ func (t opType) String() string { return "StructFieldStringTagIndent" case opStructFieldRecursiveIndent: return "StructFieldRecursiveIndent" + case opStructFieldRecursiveEndIndent: + return "StructFieldRecursiveEndIndent" case opStructEndIndent: return "StructEndIndent" case opStructAnonymousEndIndent: @@ -2361,6 +2373,8 @@ func (t opType) codeType() codeType { return codeOp case opInterface: return codeOp + case opInterfaceEnd: + return codeOp case opPtr: return codeOp case opSliceHead: @@ -2425,6 +2439,8 @@ func (t opType) codeType() codeType { return codeStructField case opStructFieldRecursive: return codeStructFieldRecursive + case opStructFieldRecursiveEnd: + return codeOp case opStructEnd: return codeStructField case opStructAnonymousEnd: @@ -3137,6 +3153,8 @@ func (t opType) codeType() codeType { return codeOp case opInterfaceIndent: return codeOp + case opInterfaceEndIndent: + return codeOp case opPtrIndent: return codeOp case opSliceHeadIndent: @@ -3201,6 +3219,8 @@ func (t opType) codeType() codeType { return codeStructField case opStructFieldRecursiveIndent: return codeStructFieldRecursive + case opStructFieldRecursiveEndIndent: + return codeOp case opStructEndIndent: return codeStructField case opStructAnonymousEndIndent: @@ -3919,6 +3939,8 @@ func (t opType) toIndent() opType { return opEndIndent case opInterface: return opInterfaceIndent + case opInterfaceEnd: + return opInterfaceEndIndent case opPtr: return opPtrIndent case opSliceHead: @@ -3983,6 +4005,8 @@ func (t opType) toIndent() opType { return opStructFieldStringTagIndent case opStructFieldRecursive: return opStructFieldRecursiveIndent + case opStructFieldRecursiveEnd: + return opStructFieldRecursiveEndIndent case opStructEnd: return opStructEndIndent case opStructAnonymousEnd: @@ -4695,6 +4719,8 @@ func (t opType) toIndent() opType { return opEndIndent case opInterfaceIndent: return opInterfaceIndent + case opInterfaceEndIndent: + return opInterfaceEndIndent case opPtrIndent: return opPtrIndent case opSliceHeadIndent: @@ -4759,6 +4785,8 @@ func (t opType) toIndent() opType { return opStructFieldStringTagIndent case opStructFieldRecursiveIndent: return opStructFieldRecursiveIndent + case opStructFieldRecursiveEndIndent: + return opStructFieldRecursiveEndIndent case opStructEndIndent: return opStructEndIndent case opStructAnonymousEndIndent: diff --git a/encode_vm.go b/encode_vm.go index 81b9750..888bd7e 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -22,6 +22,7 @@ func store(base uintptr, idx uintptr, p uintptr) { } func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map[uintptr]struct{}, code *opcode) error { + ptrOffset := uintptr(0) ctxptr := ctx.ptr() for { switch code.op { @@ -142,13 +143,43 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map } c = code } - ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, c.totalLength()), + + beforeLastCode := c.beforeLastCode() + lastCode := beforeLastCode.next + lastCode.idx = beforeLastCode.idx + uintptrSize + totalLength := uintptr(code.totalLength()) + nextTotalLength := uintptr(c.totalLength()) + curlen := uintptr(len(ctx.ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset = ptrOffset + totalLength*uintptrSize // curlen * uintptrSize } - ctx.init(uintptr(header.ptr)) - if err := e.run(ctx, recursiveLevel+1, seenPtr, c); err != nil { - return err + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.ptrs = append(ctx.ptrs, make([]uintptr, newLen-curlen)...) + store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr)) + } else { + store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr)) } + ctxptr = ctx.ptr() + ptrOffset // assign new ctxptr + if load(ctxptr, 0) != uintptr(header.ptr) { + panic(nil) + } + // save current ctxptr + store(ctxptr, lastCode.idx, oldOffset) + + // link lastCode ( opInterfaceEnd ) => code.next + lastCode.op = opInterfaceEnd + lastCode.next = code.next + + code = c + recursiveLevel++ + case opInterfaceEnd: + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.idx) + ctxptr = ctx.ptr() + offset + ptrOffset = offset code = code.next case opMarshalJSON: ptr := load(ctxptr, code.idx) From efcf2dec06c359c76231a5ac53c264c04f2815ef Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 3 Sep 2020 22:05:46 +0900 Subject: [PATCH 13/18] Refactor --- encode_vm.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/encode_vm.go b/encode_vm.go index 888bd7e..b592e93 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -152,20 +152,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map curlen := uintptr(len(ctx.ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset - ptrOffset = ptrOffset + totalLength*uintptrSize // curlen * uintptrSize - } + ptrOffset += totalLength * uintptrSize + newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.ptrs = append(ctx.ptrs, make([]uintptr, newLen-curlen)...) - store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr)) - } else { - store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr)) } ctxptr = ctx.ptr() + ptrOffset // assign new ctxptr - if load(ctxptr, 0) != uintptr(header.ptr) { - panic(nil) - } - // save current ctxptr + + store(ctxptr, 0, uintptr(header.ptr)) store(ctxptr, lastCode.idx, oldOffset) // link lastCode ( opInterfaceEnd ) => code.next From 3a3122c2866f9a13555822e0568b280133960096 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 4 Sep 2020 13:48:21 +0900 Subject: [PATCH 14/18] Add opStructFieldRecursiveEnd --- encode_opcode.go | 2 +- encode_vm.go | 52 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/encode_opcode.go b/encode_opcode.go index 9b0cc81..ea40704 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -81,7 +81,7 @@ func (c *opcode) totalLength() int { var idx int for code := c; code.op != opEnd; { idx = int(code.idx / uintptrSize) - if code.op == opInterfaceEnd { + if code.op == opInterfaceEnd || code.op == opStructFieldRecursiveEnd { break } switch code.op.codeType() { diff --git a/encode_vm.go b/encode_vm.go index b592e93..813ef8b 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -617,17 +617,53 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map } } seenPtr[ptr] = struct{}{} - c := *(code.jmp.code) - ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, c.totalLength()), - } - ctx.init(ptr) + c := code.jmp.code c.end.next = newEndOp(&encodeCompileContext{}) c.op = c.op.ptrHeadToHead() - if err := e.run(ctx, recursiveLevel+1, seenPtr, &c); err != nil { - return err + + beforeLastCode := c.end + lastCode := beforeLastCode.next + + lastCode.idx = beforeLastCode.idx + uintptrSize + lastCode.elemIdx = lastCode.idx + uintptrSize + + // extend length to alloc slot for elemIdx + totalLength := uintptr(code.totalLength() + 1) + nextTotalLength := uintptr(c.totalLength() + 1) + + curlen := uintptr(len(ctx.ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += totalLength * uintptrSize + + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.ptrs = append(ctx.ptrs, make([]uintptr, newLen-curlen)...) } - code = code.next + ctxptr = ctx.ptr() + ptrOffset // assign new ctxptr + + store(ctxptr, 0, ptr) + store(ctxptr, lastCode.idx, oldOffset) + store(ctxptr, lastCode.elemIdx, uintptr(unsafe.Pointer(code.next))) + + // link lastCode ( opStructFieldRecursiveEnd ) => code.next + lastCode.op = opStructFieldRecursiveEnd + code = c + recursiveLevel++ + case opStructFieldRecursiveEnd: + recursiveLevel-- + + // Since the pointer addresses of root code and code.jmp.code may be common, + // `opStructFieldRecursive` processing may replace `opEnd` of root code with `opRecursiveEnd`. + // At that time, `recursiveLevel` becomes -1, so return here as normal processing. + if recursiveLevel < 0 { + return nil + } + // restore ctxptr + offset := load(ctxptr, code.idx) + code = (*opcode)(unsafe.Pointer(load(ctxptr, code.elemIdx))) + ctxptr = ctx.ptr() + offset + ptrOffset = offset case opStructFieldPtrHead: ptr := load(ctxptr, code.idx) if ptr != 0 { From f297c99af16ac04bd9e711b53a550dc1d112192a Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 4 Sep 2020 13:53:25 +0900 Subject: [PATCH 15/18] Remove unused arguments --- encode.go | 6 ++---- encode_vm.go | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/encode.go b/encode.go index 6297a1a..f139c5c 100644 --- a/encode.go +++ b/encode.go @@ -165,8 +165,7 @@ func (e *Encoder) encode(v interface{}) error { ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) ctx.init(p) - seenPtr := map[uintptr]struct{}{} - err := e.run(ctx, 0, seenPtr, code) + err := e.run(ctx, code) codeSet.ctx.Put(ctx) return err } @@ -214,8 +213,7 @@ func (e *Encoder) encode(v interface{}) error { c = code } - seenPtr := map[uintptr]struct{}{} - if err := e.run(ctx, 0, seenPtr, c); err != nil { + if err := e.run(ctx, c); err != nil { codeSet.ctx.Put(ctx) return err } diff --git a/encode_vm.go b/encode_vm.go index 813ef8b..ca052fc 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -21,9 +21,12 @@ func store(base uintptr, idx uintptr, p uintptr) { *(*uintptr)(unsafe.Pointer(base + idx)) = p } -func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map[uintptr]struct{}, code *opcode) error { +func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { + recursiveLevel := 0 + seenPtr := map[uintptr]struct{}{} ptrOffset := uintptr(0) ctxptr := ctx.ptr() + for { switch code.op { case opPtr: From 3e4e83bf345715f40fc0ec09e4346642ce5548ab Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 4 Sep 2020 19:33:46 +0900 Subject: [PATCH 16/18] Save iter value --- encode_vm.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/encode_vm.go b/encode_vm.go index ca052fc..5f45b04 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -21,6 +21,10 @@ func store(base uintptr, idx uintptr, p uintptr) { *(*uintptr)(unsafe.Pointer(base + idx)) = p } +var ( + globalArray = []interface{}{} +) + func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { recursiveLevel := 0 seenPtr := map[uintptr]struct{}{} @@ -430,6 +434,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) + globalArray = append(globalArray, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) From 02e04238a2c44c9aabdc3ff06deec667557dc58e Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 4 Sep 2020 20:28:27 +0900 Subject: [PATCH 17/18] Add keepRefs field --- encode.go | 3 ++- encode_context.go | 4 +++- encode_vm.go | 10 +++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/encode.go b/encode.go index f139c5c..e192e34 100644 --- a/encode.go +++ b/encode.go @@ -196,7 +196,8 @@ func (e *Encoder) encode(v interface{}) error { ctx: sync.Pool{ New: func() interface{} { return &encodeRuntimeContext{ - ptrs: make([]uintptr, codeLength), + ptrs: make([]uintptr, codeLength), + keepRefs: make([]unsafe.Pointer, 8), } }, }, diff --git a/encode_context.go b/encode_context.go index 0b30e45..ce52702 100644 --- a/encode_context.go +++ b/encode_context.go @@ -85,11 +85,13 @@ func (c *encodeCompileContext) decPtrIndex() { } type encodeRuntimeContext struct { - ptrs []uintptr + ptrs []uintptr + keepRefs []unsafe.Pointer } func (c *encodeRuntimeContext) init(p uintptr) { c.ptrs[0] = p + c.keepRefs = c.keepRefs[:0] } func (c *encodeRuntimeContext) ptr() uintptr { diff --git a/encode_vm.go b/encode_vm.go index 5f45b04..29ddb30 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -21,10 +21,6 @@ func store(base uintptr, idx uintptr, p uintptr) { *(*uintptr)(unsafe.Pointer(base + idx)) = p } -var ( - globalArray = []interface{}{} -) - func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { recursiveLevel := 0 seenPtr := map[uintptr]struct{}{} @@ -434,7 +430,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) - globalArray = append(globalArray, iter) + ctx.keepRefs = append(ctx.keepRefs, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) @@ -458,6 +454,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) + ctx.keepRefs = append(ctx.keepRefs, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) @@ -502,6 +499,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) + ctx.keepRefs = append(ctx.keepRefs, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) @@ -528,6 +526,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) + ctx.keepRefs = append(ctx.keepRefs, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) @@ -552,6 +551,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) iter := mapiterinit(code.typ, unsafe.Pointer(ptr)) + ctx.keepRefs = append(ctx.keepRefs, iter) store(ctxptr, code.elemIdx, 0) store(ctxptr, code.length, uintptr(mlen)) store(ctxptr, code.mapIter, uintptr(iter)) From 91a2768d1acf5f4f2d61f2305003ff36b5efa9c7 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 4 Sep 2020 21:46:16 +0900 Subject: [PATCH 18/18] Revert json_test.go --- json_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/json_test.go b/json_test.go index bb25fce..f3a066c 100644 --- a/json_test.go +++ b/json_test.go @@ -222,7 +222,6 @@ func trim(b []byte) []byte { var ( jsonBig []byte - jsonVal interface{} ) func initBig() { @@ -233,8 +232,8 @@ func initBig() { if testing.Short() { n = 100 } - jsonVal = genValue(n) - b, err := json.Marshal(jsonVal) + v := genValue(n) + b, err := json.Marshal(v) if err != nil { panic(err) }