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, }, } }