Add opcodeIndex to opcode

This commit is contained in:
Masaaki Goshima 2020-08-30 17:32:26 +09:00
parent e508ad41ba
commit a9e2386e42
3 changed files with 258 additions and 105 deletions

View File

@ -10,13 +10,13 @@ func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) {
typ := ctx.typ typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(ctx, opMarshalJSON), nil return e.compileMarshalJSON(ctx)
case rtype_ptrTo(typ).Implements(marshalJSONType): case rtype_ptrTo(typ).Implements(marshalJSONType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil return e.compileMarshalJSONPtr(ctx)
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType):
return newOpCode(ctx, opMarshalText), nil return e.compileMarshalText(ctx)
case rtype_ptrTo(typ).Implements(marshalTextType): case rtype_ptrTo(typ).Implements(marshalTextType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil return e.compileMarshalTextPtr(ctx)
} }
isPtr := false isPtr := false
if typ.Kind() == reflect.Ptr { if typ.Kind() == reflect.Ptr {
@ -49,13 +49,13 @@ func (e *Encoder) compile(ctx *encodeCompileContext) (*opcode, error) {
typ := ctx.typ typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(ctx, opMarshalJSON), nil return e.compileMarshalJSON(ctx)
case rtype_ptrTo(typ).Implements(marshalJSONType): case rtype_ptrTo(typ).Implements(marshalJSONType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil return e.compileMarshalJSONPtr(ctx)
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType):
return newOpCode(ctx, opMarshalText), nil return e.compileMarshalText(ctx)
case rtype_ptrTo(typ).Implements(marshalTextType): case rtype_ptrTo(typ).Implements(marshalTextType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil return e.compileMarshalTextPtr(ctx)
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
@ -112,13 +112,13 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) {
typ := ctx.typ typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(ctx, opMarshalJSON), nil return e.compileMarshalJSON(ctx)
case rtype_ptrTo(typ).Implements(marshalJSONType): case rtype_ptrTo(typ).Implements(marshalJSONType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalJSON), nil return e.compileMarshalJSONPtr(ctx)
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType):
return newOpCode(ctx, opMarshalText), nil return e.compileMarshalText(ctx)
case rtype_ptrTo(typ).Implements(marshalTextType): case rtype_ptrTo(typ).Implements(marshalTextType):
return newOpCode(ctx.withType(rtype_ptrTo(typ)), opMarshalText), nil return e.compileMarshalTextPtr(ctx)
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
@ -131,93 +131,152 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) {
return nil, &UnsupportedTypeError{Type: rtype2type(typ)} 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) { func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) {
ptrOpcodeIndex := ctx.opcodeIndex
ctx.incOpcodeIndex()
code, err := e.compile(ctx.withType(ctx.typ.Elem())) code, err := e.compile(ctx.withType(ctx.typ.Elem()))
if err != nil { if err != nil {
return nil, err 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) {
return (*opcode)(unsafe.Pointer(&interfaceCode{ code := (*opcode)(unsafe.Pointer(&interfaceCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opInterface, op: opInterface,
typ: ctx.typ, typ: ctx.typ,
idx: ctx.opcodeIndex,
indent: ctx.indent, indent: ctx.indent,
next: newEndOp(ctx), next: newEndOp(ctx),
}, },
root: ctx.root, root: ctx.root,
})), nil }))
ctx.incOpcodeIndex()
return code, nil
} }
func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) {
@ -225,6 +284,9 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) {
elem := ctx.typ.Elem() elem := ctx.typ.Elem()
size := elem.Size() size := elem.Size()
header := newSliceHeaderCode(ctx)
ctx.incOpcodeIndex()
code, err := e.compile(ctx.withType(ctx.typ.Elem()).incIndent()) code, err := e.compile(ctx.withType(ctx.typ.Elem()).incIndent())
if err != nil { if err != nil {
return nil, err return nil, err
@ -234,15 +296,11 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) {
// ^ | // ^ |
// |________| // |________|
header := newSliceHeaderCode(ctx.indent) elemCode := newSliceElemCode(ctx, size)
elemCode := &sliceElemCode{ ctx.incOpcodeIndex()
opcodeHeader: &opcodeHeader{
op: opSliceElem,
indent: ctx.indent,
},
size: size,
}
end := newOpCode(ctx, opSliceEnd) end := newOpCode(ctx, opSliceEnd)
ctx.incOpcodeIndex()
if ctx.withIndent { if ctx.withIndent {
if ctx.root { if ctx.root {
header.op = opRootSliceHeadIndent header.op = opRootSliceHeadIndent
@ -270,6 +328,9 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) {
alen := typ.Len() alen := typ.Len()
size := elem.Size() size := elem.Size()
header := newArrayHeaderCode(ctx, alen)
ctx.incOpcodeIndex()
code, err := e.compile(ctx.withType(elem).incIndent()) code, err := e.compile(ctx.withType(elem).incIndent())
if err != nil { if err != nil {
return nil, err return nil, err
@ -278,15 +339,11 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) {
// ^ | // ^ |
// |________| // |________|
header := newArrayHeaderCode(ctx.indent, alen) elemCode := newArrayElemCode(ctx, alen, size)
elemCode := &arrayElemCode{ ctx.incOpcodeIndex()
opcodeHeader: &opcodeHeader{
op: opArrayElem,
},
len: uintptr(alen),
size: size,
}
end := newOpCode(ctx, opArrayEnd) end := newOpCode(ctx, opArrayEnd)
ctx.incOpcodeIndex()
if ctx.withIndent { if ctx.withIndent {
header.op = opArrayHeadIndent header.op = opArrayHeadIndent
@ -324,27 +381,34 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode,
// ^ | // ^ |
// |_______________________| // |_______________________|
ctx = ctx.incIndent() ctx = ctx.incIndent()
header := newMapHeaderCode(ctx, withLoad)
ctx.incOpcodeIndex()
typ := ctx.typ typ := ctx.typ
keyType := ctx.typ.Key() keyType := ctx.typ.Key()
keyCode, err := e.compileKey(ctx.withType(keyType)) keyCode, err := e.compileKey(ctx.withType(keyType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
value := newMapValueCode(ctx)
ctx.incOpcodeIndex()
valueType := typ.Elem() valueType := typ.Elem()
valueCode, err := e.compile(ctx.withType(valueType)) valueCode, err := e.compile(ctx.withType(valueType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
key := newMapKeyCode(ctx.indent) key := newMapKeyCode(ctx)
value := newMapValueCode(ctx.indent) ctx.incOpcodeIndex()
ctx = ctx.decIndent() ctx = ctx.decIndent()
header := newMapHeaderCode(typ, withLoad, ctx.indent)
header.key = key header.key = key
header.value = value header.value = value
end := newOpCode(ctx, opMapEnd) end := newOpCode(ctx, opMapEnd)
ctx.incOpcodeIndex()
if ctx.withIndent { if ctx.withIndent {
if header.op == opMapHead { 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 { func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode {
return (*opcode)(unsafe.Pointer(&recursiveCode{ c := (*opcode)(unsafe.Pointer(&recursiveCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opStructFieldRecursive, op: opStructFieldRecursive,
typ: ctx.typ, typ: ctx.typ,
idx: ctx.opcodeIndex,
indent: ctx.indent, indent: ctx.indent,
next: newEndOp(ctx), next: newEndOp(ctx),
}, },
jmp: code, jmp: code,
})) }))
ctx.incOpcodeIndex()
return c
} }
func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode { func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
@ -548,9 +615,9 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
return nil 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-- fieldCode.indent--
op := e.optimizeStructHeader(valueCode.op, tag, withIndent) op := e.optimizeStructHeader(valueCode.op, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
switch op { switch op {
case opStructFieldHead, case opStructFieldHead,
@ -581,12 +648,13 @@ func (e *Encoder) structHeader(fieldCode *structFieldCode, valueCode *opcode, ta
opStructFieldHeadStringTagIndent: opStructFieldHeadStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decOpcodeIndex()
return (*opcode)(unsafe.Pointer(fieldCode)) 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)) code := (*opcode)(unsafe.Pointer(fieldCode))
op := e.optimizeStructField(valueCode.op, tag, withIndent) op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
switch op { switch op {
case opStructField, case opStructField,
@ -617,6 +685,7 @@ func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, tag
opStructFieldStringTagIndent: opStructFieldStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decOpcodeIndex()
return code return code
} }
@ -657,6 +726,10 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) {
if codeType == codeStructField { if codeType == codeStructField {
if e.isNotExistsField(code.next.toStructFieldCode()) { if e.isNotExistsField(code.next.toStructFieldCode()) {
code.next = code.nextField code.next = code.nextField
diff := code.next.idx - code.idx
for i := 0; i < diff; i++ {
code.next.decOpcodeIndex()
}
linkPrevToNextField(prev, code) linkPrevToNextField(prev, code)
code = prev code = prev
} }
@ -690,6 +763,10 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
} else if f.op == opStructEnd { } else if f.op == opStructEnd {
f.op = opStructAnonymousEnd f.op = opStructAnonymousEnd
} else if existsKey { } else if existsKey {
diff := f.nextField.idx - f.idx
for i := 0; i < diff; i++ {
f.nextField.decOpcodeIndex()
}
linkPrevToNextField(prevAnonymousField, f) linkPrevToNextField(prevAnonymousField, f)
} }
@ -737,6 +814,10 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
// head operation // head operation
fieldPair.curField.op = opStructFieldAnonymousHead fieldPair.curField.op = opStructFieldAnonymousHead
} else { } else {
diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx
for i := 0; i < diff; i++ {
fieldPair.curField.nextField.decOpcodeIndex()
}
linkPrevToNextField(fieldPair.prevField, fieldPair.curField) linkPrevToNextField(fieldPair.prevField, fieldPair.curField)
} }
fieldPair.linked = true fieldPair.linked = true
@ -750,6 +831,10 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
// head operation // head operation
fieldPair.curField.op = opStructFieldAnonymousHead fieldPair.curField.op = opStructFieldAnonymousHead
} else { } else {
diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx
for i := 0; i < diff; i++ {
fieldPair.curField.nextField.decOpcodeIndex()
}
linkPrevToNextField(fieldPair.prevField, fieldPair.curField) linkPrevToNextField(fieldPair.prevField, fieldPair.curField)
} }
fieldPair.linked = true fieldPair.linked = true
@ -808,10 +893,13 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
fieldType = rtype_ptrTo(fieldType) fieldType = rtype_ptrTo(fieldType)
} }
} }
fieldOpcodeIndex := ctx.opcodeIndex
ctx.incOpcodeIndex()
valueCode, err := e.compile(ctx.withType(fieldType)) valueCode, err := e.compile(ctx.withType(fieldType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
if field.Anonymous { if field.Anonymous {
for k, v := range e.anonymousStructFieldPairMap(typ, tags, valueCode.toStructFieldCode()) { for k, v := range e.anonymousStructFieldPairMap(typ, tags, valueCode.toStructFieldCode()) {
anonymousFields[k] = append(anonymousFields[k], v...) anonymousFields[k] = append(anonymousFields[k], v...)
@ -825,12 +913,14 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
opUint, opUint8, opUint16, opUint32, opUint64, opUint, opUint8, opUint16, opUint32, opUint64,
opFloat32, opFloat64, opBool, opString, opBytes: opFloat32, opFloat64, opBool, opString, opBytes:
valueCode = valueCode.next valueCode = valueCode.next
ctx.decOpcodeIndex()
} }
} }
key := fmt.Sprintf(`"%s":`, tag.key) key := fmt.Sprintf(`"%s":`, tag.key)
fieldCode := &structFieldCode{ fieldCode := &structFieldCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
typ: valueCode.typ, typ: valueCode.typ,
idx: fieldOpcodeIndex,
next: valueCode, next: valueCode,
indent: ctx.indent, indent: ctx.indent,
}, },
@ -841,13 +931,13 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
offset: field.Offset, offset: field.Offset,
} }
if fieldIdx == 0 { if fieldIdx == 0 {
code = e.structHeader(fieldCode, valueCode, tag, ctx.withIndent) code = e.structHeader(ctx, fieldCode, valueCode, tag)
head = fieldCode head = fieldCode
prevField = fieldCode prevField = fieldCode
} else { } else {
fcode := (*opcode)(unsafe.Pointer(fieldCode)) fcode := (*opcode)(unsafe.Pointer(fieldCode))
code.next = fcode code.next = fcode
code = e.structField(fieldCode, valueCode, tag, ctx.withIndent) code = e.structField(ctx, fieldCode, valueCode, tag)
prevField.nextField = fcode prevField.nextField = fcode
prevField = fieldCode prevField = fieldCode
} }
@ -860,9 +950,31 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
op: opStructEnd, op: opStructEnd,
typ: nil, typ: nil,
indent: ctx.indent, 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 { if ctx.withIndent {
structEndCode.op = opStructEndIndent structEndCode.op = opStructEndIndent
} }
@ -871,21 +983,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
prevField.nextField = structEndCode 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 head.end = structEndCode
code.next = structEndCode code.next = structEndCode

View File

@ -6,6 +6,8 @@ type encodeCompileContext struct {
root bool root bool
opcodeIndex int opcodeIndex int
indent int indent int
parent *encodeCompileContext
} }
func (c *encodeCompileContext) context() *encodeCompileContext { func (c *encodeCompileContext) context() *encodeCompileContext {
@ -15,6 +17,7 @@ func (c *encodeCompileContext) context() *encodeCompileContext {
root: c.root, root: c.root,
opcodeIndex: c.opcodeIndex, opcodeIndex: c.opcodeIndex,
indent: c.indent, indent: c.indent,
parent: c,
} }
} }
@ -35,3 +38,17 @@ func (c *encodeCompileContext) decIndent() *encodeCompileContext {
ctx.indent-- ctx.indent--
return ctx 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()
}
}

View File

@ -15,6 +15,7 @@ func copyOpcode(code *opcode) *opcode {
type opcodeHeader struct { type opcodeHeader struct {
op opType op opType
typ *rtype typ *rtype
idx int
ptr uintptr ptr uintptr
indent int indent int
next *opcode next *opcode
@ -24,6 +25,7 @@ func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader {
return &opcodeHeader{ return &opcodeHeader{
op: h.op, op: h.op,
typ: h.typ, typ: h.typ,
idx: h.idx,
ptr: h.ptr, ptr: h.ptr,
indent: h.indent, indent: h.indent,
next: h.next.copy(codeMap), next: h.next.copy(codeMap),
@ -35,14 +37,7 @@ type opcode struct {
} }
func newOpCode(ctx *encodeCompileContext, op opType) *opcode { func newOpCode(ctx *encodeCompileContext, op opType) *opcode {
return &opcode{ return newOpCodeWithNext(ctx, op, newEndOp(ctx))
opcodeHeader: &opcodeHeader{
op: op,
typ: ctx.typ,
indent: ctx.indent,
next: newEndOp(ctx),
},
}
} }
func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode {
@ -50,6 +45,7 @@ func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opco
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: op, op: op,
typ: ctx.typ, typ: ctx.typ,
idx: ctx.opcodeIndex,
indent: ctx.indent, indent: ctx.indent,
next: next, next: next,
}, },
@ -82,6 +78,22 @@ func (c *opcode) beforeLastCode() *opcode {
return nil 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 { func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil { if c == nil {
return nil return nil
@ -125,22 +137,22 @@ func (c *opcode) dump() string {
indent := strings.Repeat(" ", code.indent) indent := strings.Repeat(" ", code.indent)
switch code.op.codeType() { switch code.op.codeType() {
case codeArrayElem: 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 code = code.toArrayElemCode().end
case codeSliceElem: 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 code = code.toSliceElemCode().end
case codeMapKey: 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 code = code.toMapKeyCode().end
case codeStructField: case codeStructField:
sf := code.toStructFieldCode() sf := code.toStructFieldCode()
key := sf.displayKey key := sf.displayKey
offset := sf.offset 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 code = code.next
default: 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 code = code.next
} }
} }
@ -193,15 +205,27 @@ type sliceHeaderCode struct {
end *opcode end *opcode
} }
func newSliceHeaderCode(indent int) *sliceHeaderCode { func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode {
return &sliceHeaderCode{ return &sliceHeaderCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opSliceHead, 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 { func (c *sliceHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil { if c == nil {
return nil return nil
@ -264,16 +288,28 @@ type arrayHeaderCode struct {
end *opcode end *opcode
} }
func newArrayHeaderCode(indent, alen int) *arrayHeaderCode { func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode {
return &arrayHeaderCode{ return &arrayHeaderCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opArrayHead, op: opArrayHead,
indent: indent, idx: ctx.opcodeIndex,
indent: ctx.indent,
}, },
len: uintptr(alen), 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 { func (c *arrayHeaderCode) copy(codeMap map[uintptr]*opcode) *opcode {
if c == nil { if c == nil {
return nil return nil
@ -475,7 +511,7 @@ func (c *mapValueCode) set(iter unsafe.Pointer) {
c.iter = iter c.iter = iter
} }
func newMapHeaderCode(typ *rtype, withLoad bool, indent int) *mapHeaderCode { func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode {
var op opType var op opType
if withLoad { if withLoad {
op = opMapHeadLoad op = opMapHeadLoad
@ -485,26 +521,29 @@ func newMapHeaderCode(typ *rtype, withLoad bool, indent int) *mapHeaderCode {
return &mapHeaderCode{ return &mapHeaderCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: op, op: op,
typ: typ, typ: ctx.typ,
indent: indent, idx: ctx.opcodeIndex,
indent: ctx.indent,
}, },
} }
} }
func newMapKeyCode(indent int) *mapKeyCode { func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode {
return &mapKeyCode{ return &mapKeyCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opMapKey, op: opMapKey,
indent: indent, idx: ctx.opcodeIndex,
indent: ctx.indent,
}, },
} }
} }
func newMapValueCode(indent int) *mapValueCode { func newMapValueCode(ctx *encodeCompileContext) *mapValueCode {
return &mapValueCode{ return &mapValueCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opMapValue, op: opMapValue,
indent: indent, idx: ctx.opcodeIndex,
indent: ctx.indent,
}, },
} }
} }