Compare commits

...

3 Commits

Author SHA1 Message Date
Masaaki Goshima 8ec9df385c Add optimizer 2020-11-15 02:49:38 +09:00
Masaaki Goshima 4855599414 WIP 2020-11-15 02:49:16 +09:00
Masaaki Goshima 1d14ceb03e Fix optimizer 2020-11-14 22:38:16 +09:00
5 changed files with 5830 additions and 4331 deletions

View File

@ -26,16 +26,11 @@ type headType struct {
OmitEmptyPtrHead string OmitEmptyPtrHead string
AnonymousOmitEmptyHead string AnonymousOmitEmptyHead string
AnonymousOmitEmptyPtrHead string AnonymousOmitEmptyPtrHead string
StringTagHead string
StringTagPtrHead string
AnonymousStringTagHead string
AnonymousStringTagPtrHead string
} }
type fieldType struct { type fieldType struct {
Field string Field string
OmitEmptyField string OmitEmptyField string
StringTagField string
} }
func _main() error { func _main() error {
@ -88,6 +83,46 @@ func (t opType) toIndent() opType {
return t return t
} }
func (t opType) toString() opType {
switch t {
case opInt:
return opIntString
case opInt8:
return opInt8String
case opInt16:
return opInt16String
case opInt32:
return opInt32String
case opInt64:
return opInt64String
case opUint:
return opUintString
case opUint8:
return opUint8String
case opUint16:
return opUint16String
case opUint32:
return opUint32String
case opUint64:
return opUint64String
case opFloat32:
return opFloat32String
case opFloat64:
return opFloat64String
case opBool:
return opBoolString
case opString:
return opStringString
case opBytes:
return opBytesString
case opMarshalJSON:
return opMarshalJSONString
case opMarshalText:
return opMarshalTextString
}
return t
}
func (t opType) headToPtrHead() opType { func (t opType) headToPtrHead() opType {
switch t { switch t {
{{- range $type := .HeadTypes }} {{- range $type := .HeadTypes }}
@ -99,10 +134,6 @@ func (t opType) headToPtrHead() opType {
return op{{ $type.OmitEmptyPtrHead }} return op{{ $type.OmitEmptyPtrHead }}
case op{{ $type.AnonymousOmitEmptyHead }}: case op{{ $type.AnonymousOmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }} return op{{ $type.AnonymousOmitEmptyPtrHead }}
case op{{ $type.StringTagHead }}:
return op{{ $type.StringTagPtrHead }}
case op{{ $type.AnonymousStringTagHead }}:
return op{{ $type.AnonymousStringTagPtrHead }}
{{- end }} {{- end }}
} }
return t return t
@ -119,10 +150,6 @@ func (t opType) headToAnonymousHead() opType {
return op{{ $type.AnonymousOmitEmptyHead }} return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.OmitEmptyPtrHead }}: case op{{ $type.OmitEmptyPtrHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }} return op{{ $type.AnonymousOmitEmptyPtrHead }}
case op{{ $type.StringTagHead }}:
return op{{ $type.AnonymousStringTagHead }}
case op{{ $type.StringTagPtrHead }}:
return op{{ $type.AnonymousStringTagPtrHead }}
{{- end }} {{- end }}
} }
return t return t
@ -140,18 +167,6 @@ func (t opType) headToOmitEmptyHead() opType {
return t return t
} }
func (t opType) headToStringTagHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.StringTagHead }}
case op{{ $type.PtrHead }}:
return op{{ $type.StringTagPtrHead }}
{{- end }}
}
return t
}
func (t opType) ptrHeadToHead() opType { func (t opType) ptrHeadToHead() opType {
switch t { switch t {
{{- range $type := .HeadTypes }} {{- range $type := .HeadTypes }}
@ -163,10 +178,6 @@ func (t opType) ptrHeadToHead() opType {
return op{{ $type.OmitEmptyHead }} return op{{ $type.OmitEmptyHead }}
case op{{ $type.AnonymousOmitEmptyPtrHead }}: case op{{ $type.AnonymousOmitEmptyPtrHead }}:
return op{{ $type.AnonymousOmitEmptyHead }} return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.StringTagPtrHead }}:
return op{{ $type.StringTagHead }}
case op{{ $type.AnonymousStringTagPtrHead }}:
return op{{ $type.AnonymousStringTagHead }}
{{- end }} {{- end }}
} }
return t return t
@ -182,16 +193,6 @@ func (t opType) fieldToOmitEmptyField() opType {
return t return t
} }
func (t opType) fieldToStringTagField() opType {
switch t {
{{- range $type := .FieldTypes }}
case op{{ $type.Field }}:
return op{{ $type.StringTagField }}
{{- end }}
}
return t
}
`) `)
if err != nil { if err != nil {
return err return err
@ -215,6 +216,14 @@ func (t opType) fieldToStringTagField() opType {
"float32", "float64", "bool", "string", "bytes", "float32", "float64", "bool", "string", "bytes",
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText",
} }
// primitiveStringTypes primitive types for StringTag
primitiveStringTypes := []string{}
for _, typ := range primitiveTypes {
primitiveStringTypes = append(primitiveStringTypes, fmt.Sprintf("%sString", typ))
}
primitiveTypes = append(primitiveTypes, primitiveStringTypes...)
primitiveTypesUpper := []string{} primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes { for _, typ := range primitiveTypes {
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:]) primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
@ -239,19 +248,15 @@ func (t opType) fieldToStringTagField() opType {
{"MapEnd", "MapEndIndent", "Op"}, {"MapEnd", "MapEndIndent", "Op"},
{"StructFieldHead", "StructFieldHeadIndent", "StructField"}, {"StructFieldHead", "StructFieldHeadIndent", "StructField"},
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"}, {"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
{"StructFieldHeadStringTag", "StructFieldHeadStringTagIndent", "StructField"},
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"}, {"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
{"StructFieldAnonymousSkipHead", "StructFieldAnonymousSkipHeadIndent", "StructField"},
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"}, {"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"}, {"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"}, {"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"}, {"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"}, {"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
{"StructField", "StructFieldIndent", "StructField"}, {"StructField", "StructFieldIndent", "StructField"},
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"}, {"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"}, {"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"}, {"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
{"StructEnd", "StructEndIndent", "StructField"}, {"StructEnd", "StructEndIndent", "StructField"},
@ -267,20 +272,15 @@ func (t opType) fieldToStringTagField() opType {
for _, prefix := range []string{ for _, prefix := range []string{
"StructFieldHead", "StructFieldHead",
"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmpty",
"StructFieldHeadStringTag",
"StructFieldAnonymousHead", "StructFieldAnonymousHead",
"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmpty",
"StructFieldAnonymousHeadStringTag",
"StructFieldPtrHead", "StructFieldPtrHead",
"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmpty",
"StructFieldPtrHeadStringTag",
"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHead",
"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmpty",
"StructFieldPtrAnonymousHeadStringTag",
"StructField", "StructField",
"StructFieldPtr", "StructFieldPtr",
"StructFieldOmitEmpty", "StructFieldOmitEmpty",
"StructFieldStringTag",
} { } {
for _, typ := range primitiveTypesUpper { for _, typ := range primitiveTypesUpper {
opTypes = append(opTypes, opType{ opTypes = append(opTypes, opType{
@ -304,12 +304,8 @@ func (t opType) fieldToStringTagField() opType {
AnonymousPtrHead: "StructFieldPtrAnonymousHead", AnonymousPtrHead: "StructFieldPtrAnonymousHead",
OmitEmptyHead: "StructFieldHeadOmitEmpty", OmitEmptyHead: "StructFieldHeadOmitEmpty",
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty", OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
StringTagHead: "StructFieldHeadStringTag",
StringTagPtrHead: "StructFieldPtrHeadStringTag",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty", AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty", AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
} }
headTypes := []headType{base} headTypes := []headType{base}
for _, prim := range primitiveTypesUpper { for _, prim := range primitiveTypesUpper {
@ -322,10 +318,6 @@ func (t opType) fieldToStringTagField() opType {
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim), OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim), AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim), AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim),
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, prim),
}) })
} }
for _, typ := range headTypes { for _, typ := range headTypes {
@ -338,31 +330,24 @@ func (t opType) fieldToStringTagField() opType {
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead), OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead), AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead), AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead),
}) })
} }
baseField := fieldType{ baseField := fieldType{
Field: "StructField", Field: "StructField",
OmitEmptyField: "StructFieldOmitEmpty", OmitEmptyField: "StructFieldOmitEmpty",
StringTagField: "StructFieldStringTag",
} }
fieldTypes := []fieldType{baseField} fieldTypes := []fieldType{baseField}
for _, prim := range primitiveTypesUpper { for _, prim := range primitiveTypesUpper {
fieldTypes = append(fieldTypes, fieldType{ fieldTypes = append(fieldTypes, fieldType{
Field: fmt.Sprintf("%s%s", baseField.Field, prim), Field: fmt.Sprintf("%s%s", baseField.Field, prim),
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim), OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
StringTagField: fmt.Sprintf("%s%s", baseField.StringTagField, prim),
}) })
} }
for _, typ := range fieldTypes { for _, typ := range fieldTypes {
fieldTypes = append(fieldTypes, fieldType{ fieldTypes = append(fieldTypes, fieldType{
Field: fmt.Sprintf("%sIndent", typ.Field), Field: fmt.Sprintf("%sIndent", typ.Field),
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField), OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
StringTagField: fmt.Sprintf("%sIndent", typ.StringTagField),
}) })
} }

View File

@ -139,13 +139,15 @@ func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ptrHeadOp := code.op.headToPtrHead() /*
if code.op != ptrHeadOp { ptrHeadOp := code.op.headToPtrHead()
code.op = ptrHeadOp if code.op != ptrHeadOp {
code.decOpcodeIndex() code.op = ptrHeadOp
ctx.decIndex() code.decOpcodeIndex()
return code, nil ctx.decIndex()
} return code, nil
}
*/
c := ctx.context() c := ctx.context()
c.opcodeIndex = ptrOpcodeIndex c.opcodeIndex = ptrOpcodeIndex
return newOpCodeWithNext(c, opPtr, code), nil return newOpCodeWithNext(c, opPtr, code), nil
@ -571,12 +573,10 @@ func (e *Encoder) typeToFieldType(code *opcode) opType {
} }
func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent bool) opType {
headType := e.typeToHeaderType(op) headType := opStructFieldHead // e.typeToHeaderType(op)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
headType = headType.headToOmitEmptyHead() headType = headType.headToOmitEmptyHead()
case tag.isString:
headType = headType.headToStringTagHead()
} }
if withIndent { if withIndent {
return headType.toIndent() return headType.toIndent()
@ -585,12 +585,10 @@ func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent boo
} }
func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType {
fieldType := e.typeToFieldType(code) fieldType := opStructField // e.typeToFieldType(code)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
fieldType = fieldType.fieldToOmitEmptyField() fieldType = fieldType.fieldToOmitEmptyField()
case tag.isString:
fieldType = fieldType.fieldToStringTagField()
} }
if withIndent { if withIndent {
return fieldType.toIndent() return fieldType.toIndent()
@ -636,7 +634,6 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
opStructFieldHeadOmitEmptyMap, opStructFieldHeadOmitEmptyMap,
opStructFieldHeadOmitEmptyMapLoad, opStructFieldHeadOmitEmptyMapLoad,
opStructFieldHeadOmitEmptyStruct, opStructFieldHeadOmitEmptyStruct,
opStructFieldHeadStringTag,
opStructFieldHeadIndent, opStructFieldHeadIndent,
opStructFieldHeadSliceIndent, opStructFieldHeadSliceIndent,
opStructFieldHeadArrayIndent, opStructFieldHeadArrayIndent,
@ -648,8 +645,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
opStructFieldHeadOmitEmptyArrayIndent, opStructFieldHeadOmitEmptyArrayIndent,
opStructFieldHeadOmitEmptyMapIndent, opStructFieldHeadOmitEmptyMapIndent,
opStructFieldHeadOmitEmptyMapLoadIndent, opStructFieldHeadOmitEmptyMapLoadIndent,
opStructFieldHeadOmitEmptyStructIndent, opStructFieldHeadOmitEmptyStructIndent:
opStructFieldHeadStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decOpcodeIndex() ctx.decOpcodeIndex()
@ -673,7 +669,6 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu
opStructFieldOmitEmptyMap, opStructFieldOmitEmptyMap,
opStructFieldOmitEmptyMapLoad, opStructFieldOmitEmptyMapLoad,
opStructFieldOmitEmptyStruct, opStructFieldOmitEmptyStruct,
opStructFieldStringTag,
opStructFieldIndent, opStructFieldIndent,
opStructFieldSliceIndent, opStructFieldSliceIndent,
opStructFieldArrayIndent, opStructFieldArrayIndent,
@ -685,8 +680,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu
opStructFieldOmitEmptyArrayIndent, opStructFieldOmitEmptyArrayIndent,
opStructFieldOmitEmptyMapIndent, opStructFieldOmitEmptyMapIndent,
opStructFieldOmitEmptyMapLoadIndent, opStructFieldOmitEmptyMapLoadIndent,
opStructFieldOmitEmptyStructIndent, opStructFieldOmitEmptyStructIndent:
opStructFieldStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decIndex() ctx.decIndex()
@ -751,16 +745,26 @@ type structFieldPair struct {
linked bool linked bool
} }
func (e *Encoder) isAnonymousStructType(code *opcode) bool {
if code.op == opPtr {
code = code.next
}
return code.op.codeType() == codeStructField
}
func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *opcode) map[string][]structFieldPair { func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *opcode) map[string][]structFieldPair {
anonymousFields := map[string][]structFieldPair{} anonymousFields := map[string][]structFieldPair{}
f := valueCode f := valueCode
if f.op == opPtr {
f = f.next
}
var prevAnonymousField *opcode var prevAnonymousField *opcode
for { for {
existsKey := tags.existsKey(f.displayKey)
op := f.op.headToAnonymousHead() op := f.op.headToAnonymousHead()
existsKey := tags.existsKey(f.displayKey)
if op != f.op { if op != f.op {
if existsKey { if existsKey {
f.op = opStructFieldAnonymousHead f.op = opStructFieldAnonymousSkipHead
} else { } else {
f.op = op f.op = op
} }
@ -773,7 +777,6 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
} }
linkPrevToNextField(prevAnonymousField, f) linkPrevToNextField(prevAnonymousField, f)
} }
if f.displayKey == "" { if f.displayKey == "" {
if f.nextField == nil { if f.nextField == nil {
break break
@ -802,7 +805,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
return anonymousFields return anonymousFields
} }
func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPair) { func (e *Encoder) removeConflictAnonymousFields(anonymousFields map[string][]structFieldPair) {
for _, fieldPairs := range anonymousFields { for _, fieldPairs := range anonymousFields {
if len(fieldPairs) == 1 { if len(fieldPairs) == 1 {
continue continue
@ -816,7 +819,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
if !fieldPair.linked { if !fieldPair.linked {
if fieldPair.prevField == nil { if fieldPair.prevField == nil {
// head operation // head operation
fieldPair.curField.op = opStructFieldAnonymousHead fieldPair.curField.op = opStructFieldAnonymousSkipHead
} else { } else {
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
for i := 0; i < diff; i++ { for i := 0; i < diff; i++ {
@ -833,7 +836,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
if !fieldPair.linked { if !fieldPair.linked {
if fieldPair.prevField == nil { if fieldPair.prevField == nil {
// head operation // head operation
fieldPair.curField.op = opStructFieldAnonymousHead fieldPair.curField.op = opStructFieldAnonymousSkipHead
} else { } else {
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
for i := 0; i < diff; i++ { for i := 0; i < diff; i++ {
@ -934,13 +937,16 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
idx: opcodeOffset(fieldPtrIndex), idx: opcodeOffset(fieldPtrIndex),
next: valueCode, next: valueCode,
indent: ctx.indent, indent: ctx.indent,
anonymousKey: field.Anonymous, anonymousKey: e.isAnonymousStructType(valueCode) && field.Anonymous,
key: []byte(key), key: []byte(key),
escapedKey: []byte(escapedKey), escapedKey: []byte(escapedKey),
isTaggedKey: tag.isTaggedKey, isTaggedKey: tag.isTaggedKey,
displayKey: tag.key, displayKey: tag.key,
offset: field.Offset, offset: field.Offset,
} }
if tag.isString {
valueCode.op = valueCode.op.toString()
}
if fieldIdx == 0 { if fieldIdx == 0 {
fieldCode.headIdx = fieldCode.idx fieldCode.headIdx = fieldCode.idx
code = e.structHeader(ctx, fieldCode, valueCode, tag) code = e.structHeader(ctx, fieldCode, valueCode, tag)
@ -997,8 +1003,8 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
head.end = structEndCode head.end = structEndCode
code.next = structEndCode code.next = structEndCode
e.optimizeConflictAnonymousFields(anonymousFields) e.removeConflictAnonymousFields(anonymousFields)
e.optimizeAnonymousFields(head) //e.optimizeAnonymousFields(head)
ret := (*opcode)(unsafe.Pointer(head)) ret := (*opcode)(unsafe.Pointer(head))
compiled.code = ret compiled.code = ret

51
encode_optimizer.go Normal file
View File

@ -0,0 +1,51 @@
package json
import "fmt"
type encodeOptimizerPlugin interface {
optimize(*opcode) (*opcode, error)
}
type encodeOptimizer struct {
optimizers []encodeOptimizerPlugin
}
func newEncodeOptimizer() *encodeOptimizer {
return &encodeOptimizer{}
}
func (o *encodeOptimizer) addOptimizer(plg encodeOptimizerPlugin) {
o.optimizers = append(o.optimizers, plg)
}
func (o *encodeOptimizer) optimize(code *opcode) (*opcode, error) {
for _, optimizer := range o.optimizers {
c, err := optimizer.optimize(code)
if err != nil {
return nil, err
}
code = c
}
return code, nil
}
type encodeStructHeadOptimizer struct {
}
func (o *encodeStructHeadOptimizer) optimize(code *opcode) (*opcode, error) {
head := code
for code.op != opEnd {
if code.op == opStructFieldHead {
fmt.Println("StructHead")
}
switch code.op.codeType() {
case codeArrayElem, codeSliceElem:
code = code.end
case codeMapKey:
code = code.end
default:
code = code.next
}
}
return head, nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff