mirror of https://github.com/goccy/go-json.git
Remove only operation and add indirect property to opcode
This commit is contained in:
parent
40cc5ff367
commit
c6f40ed546
|
@ -163,7 +163,7 @@ func (t opType) headToPtrHead() opType {
|
||||||
}
|
}
|
||||||
suffix := "Ptr"+t.String()[idx+len("Field"):]
|
suffix := "Ptr"+t.String()[idx+len("Field"):]
|
||||||
|
|
||||||
const toPtrOffset = 12
|
const toPtrOffset = 6
|
||||||
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) + toPtrOffset)
|
return opType(int(t) + toPtrOffset)
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ func (t opType) headToNPtrHead() opType {
|
||||||
}
|
}
|
||||||
suffix := "NPtr"+t.String()[idx+len("Field"):]
|
suffix := "NPtr"+t.String()[idx+len("Field"):]
|
||||||
|
|
||||||
const toPtrOffset = 24
|
const toPtrOffset = 12
|
||||||
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) + toPtrOffset)
|
return opType(int(t) + toPtrOffset)
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ func (t opType) headToNPtrHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToAnonymousHead() opType {
|
func (t opType) headToAnonymousHead() opType {
|
||||||
const toAnonymousOffset = 6
|
const toAnonymousOffset = 3
|
||||||
if strings.Contains(opType(int(t) + toAnonymousOffset).String(), "Anonymous") {
|
if strings.Contains(opType(int(t) + toAnonymousOffset).String(), "Anonymous") {
|
||||||
return opType(int(t) + toAnonymousOffset)
|
return opType(int(t) + toAnonymousOffset)
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ func (t opType) headToAnonymousHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToOmitEmptyHead() opType {
|
func (t opType) headToOmitEmptyHead() opType {
|
||||||
const toOmitEmptyOffset = 2
|
const toOmitEmptyOffset = 1
|
||||||
if strings.Contains(opType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") {
|
if strings.Contains(opType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") {
|
||||||
return opType(int(t) + toOmitEmptyOffset)
|
return opType(int(t) + toOmitEmptyOffset)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ func (t opType) headToOmitEmptyHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToStringTagHead() opType {
|
func (t opType) headToStringTagHead() opType {
|
||||||
const toStringTagOffset = 4
|
const toStringTagOffset = 2
|
||||||
if strings.Contains(opType(int(t) + toStringTagOffset).String(), "StringTag") {
|
if strings.Contains(opType(int(t) + toStringTagOffset).String(), "StringTag") {
|
||||||
return opType(int(t) + toStringTagOffset)
|
return opType(int(t) + toStringTagOffset)
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ func (t opType) ptrHeadToHead() opType {
|
||||||
}
|
}
|
||||||
suffix := t.String()[idx+len("Ptr"):]
|
suffix := t.String()[idx+len("Ptr"):]
|
||||||
|
|
||||||
const toPtrOffset = 12
|
const toPtrOffset = 6
|
||||||
if strings.Contains(opType(int(t) - toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t) - toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) - toPtrOffset)
|
return opType(int(t) - toPtrOffset)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1774,11 +1774,11 @@ func TestCoverInt(t *testing.T) {
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
}
|
}
|
||||||
if err := enc.Encode(test.data); err != nil {
|
if err := enc.Encode(test.data); err != nil {
|
||||||
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
|
||||||
}
|
}
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
if buf.String() != stdresult {
|
if buf.String() != stdresult {
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,9 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
encodeConvertHeadOnlyCode(code, isPtr)
|
if !code.indirect && isPtr {
|
||||||
|
code.indirect = true
|
||||||
|
}
|
||||||
encodeOptimizeStructEnd(code)
|
encodeOptimizeStructEnd(code)
|
||||||
encodeLinkRecursiveCode(code)
|
encodeLinkRecursiveCode(code)
|
||||||
return code, nil
|
return code, nil
|
||||||
|
@ -105,11 +107,13 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
} else if isPtr && typ.Implements(marshalJSONType) {
|
} else if isPtr && typ.Implements(marshalJSONType) {
|
||||||
typ = orgType
|
typ = orgType
|
||||||
}
|
}
|
||||||
code, err := encodeCompile(ctx.withType(typ))
|
code, err := encodeCompile(ctx.withType(typ), isPtr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
encodeConvertHeadOnlyCode(code, isPtr)
|
if !code.indirect && isPtr {
|
||||||
|
code.indirect = true
|
||||||
|
}
|
||||||
encodeOptimizeStructEnd(code)
|
encodeOptimizeStructEnd(code)
|
||||||
encodeLinkRecursiveCode(code)
|
encodeLinkRecursiveCode(code)
|
||||||
return code, nil
|
return code, nil
|
||||||
|
@ -200,55 +204,6 @@ func encodeOptimizeStructEnd(c *opcode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeConvertHeadOnlyCode(c *opcode, isPtrHead bool) {
|
|
||||||
if c.nextField == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.nextField.op.codeType() != codeStructEnd {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch c.op {
|
|
||||||
case opStructFieldHead:
|
|
||||||
encodeConvertHeadOnlyCode(c.next, false)
|
|
||||||
if !strings.Contains(c.next.op.String(), "Only") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.op = opStructFieldHeadOnly
|
|
||||||
case opStructFieldHeadOmitEmpty:
|
|
||||||
encodeConvertHeadOnlyCode(c.next, false)
|
|
||||||
if !strings.Contains(c.next.op.String(), "Only") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.op = opStructFieldHeadOmitEmptyOnly
|
|
||||||
case opStructFieldHeadStringTag:
|
|
||||||
encodeConvertHeadOnlyCode(c.next, false)
|
|
||||||
if !strings.Contains(c.next.op.String(), "Only") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.op = opStructFieldHeadStringTagOnly
|
|
||||||
case opStructFieldPtrHead:
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(c.op.String(), "Marshal") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.Contains(c.op.String(), "Slice") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.Contains(c.op.String(), "Map") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isPtrOp := strings.Contains(c.op.String(), "Ptr")
|
|
||||||
if isPtrOp && !isPtrHead {
|
|
||||||
c.op = c.op.headToOnlyHead()
|
|
||||||
} else if !isPtrOp && isPtrHead {
|
|
||||||
c.op = c.op.headToPtrHead().headToOnlyHead()
|
|
||||||
} else if isPtrOp && isPtrHead {
|
|
||||||
c.op = c.op.headToPtrHead().headToOnlyHead()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeImplementsMarshaler(typ *rtype) bool {
|
func encodeImplementsMarshaler(typ *rtype) bool {
|
||||||
switch {
|
switch {
|
||||||
case typ.Implements(marshalJSONType):
|
case typ.Implements(marshalJSONType):
|
||||||
|
@ -263,7 +218,7 @@ func encodeImplementsMarshaler(typ *rtype) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeCompile(ctx *encodeCompileContext) (*opcode, error) {
|
func encodeCompile(ctx *encodeCompileContext, isPtr bool) (*opcode, error) {
|
||||||
typ := ctx.typ
|
typ := ctx.typ
|
||||||
switch {
|
switch {
|
||||||
case typ.Implements(marshalJSONType):
|
case typ.Implements(marshalJSONType):
|
||||||
|
@ -289,7 +244,7 @@ func encodeCompile(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return encodeCompileMap(ctx, true)
|
return encodeCompileMap(ctx, true)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return encodeCompileStruct(ctx, false)
|
return encodeCompileStruct(ctx, isPtr)
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
return encodeCompileInterface(ctx)
|
return encodeCompileInterface(ctx)
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
|
@ -371,7 +326,7 @@ func encodeCompilePtr(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
ptrOpcodeIndex := ctx.opcodeIndex
|
ptrOpcodeIndex := ctx.opcodeIndex
|
||||||
ptrIndex := ctx.ptrIndex
|
ptrIndex := ctx.ptrIndex
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()))
|
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -642,7 +597,7 @@ func encodeCompileSlice(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
header := newSliceHeaderCode(ctx)
|
header := newSliceHeaderCode(ctx)
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
|
|
||||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()).incIndent())
|
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()).incIndent(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -676,7 +631,7 @@ func encodeCompileArray(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
header := newArrayHeaderCode(ctx, alen)
|
header := newArrayHeaderCode(ctx, alen)
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
|
|
||||||
code, err := encodeCompile(ctx.withType(elem).incIndent())
|
code, err := encodeCompile(ctx.withType(elem).incIndent(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -734,7 +689,7 @@ func encodeCompileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, error)
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
|
|
||||||
valueType := typ.Elem()
|
valueType := typ.Elem()
|
||||||
valueCode, err := encodeCompile(ctx.withType(valueType))
|
valueCode, err := encodeCompile(ctx.withType(valueType), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1227,6 +1182,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
||||||
// ^ |
|
// ^ |
|
||||||
// |__________|
|
// |__________|
|
||||||
fieldNum := typ.NumField()
|
fieldNum := typ.NumField()
|
||||||
|
indirect := ifaceIndir(typ)
|
||||||
fieldIdx := 0
|
fieldIdx := 0
|
||||||
var (
|
var (
|
||||||
head *opcode
|
head *opcode
|
||||||
|
@ -1258,7 +1214,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
||||||
fieldOpcodeIndex := ctx.opcodeIndex
|
fieldOpcodeIndex := ctx.opcodeIndex
|
||||||
fieldPtrIndex := ctx.ptrIndex
|
fieldPtrIndex := ctx.ptrIndex
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
valueCode, err := encodeCompile(ctx.withType(fieldType))
|
valueCode, err := encodeCompile(ctx.withType(fieldType), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1280,6 +1236,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf(`"%s":`, tag.key)
|
key := fmt.Sprintf(`"%s":`, tag.key)
|
||||||
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
|
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
|
||||||
|
valueCode.indirect = indirect
|
||||||
fieldCode := &opcode{
|
fieldCode := &opcode{
|
||||||
typ: valueCode.typ,
|
typ: valueCode.typ,
|
||||||
displayIdx: fieldOpcodeIndex,
|
displayIdx: fieldOpcodeIndex,
|
||||||
|
@ -1292,6 +1249,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
||||||
isTaggedKey: tag.isTaggedKey,
|
isTaggedKey: tag.isTaggedKey,
|
||||||
displayKey: tag.key,
|
displayKey: tag.key,
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
|
indirect: indirect,
|
||||||
}
|
}
|
||||||
if fieldIdx == 0 {
|
if fieldIdx == 0 {
|
||||||
fieldCode.headIdx = fieldCode.idx
|
fieldCode.headIdx = fieldCode.idx
|
||||||
|
|
|
@ -19,11 +19,10 @@ type opcode struct {
|
||||||
isTaggedKey bool // whether tagged key
|
isTaggedKey bool // whether tagged key
|
||||||
anonymousKey bool // whether anonymous key
|
anonymousKey bool // whether anonymous key
|
||||||
root bool // whether root
|
root bool // whether root
|
||||||
|
indirect bool // whether indirect or not
|
||||||
rshiftNum uint8 // use to take bit for judging whether negative integer or not
|
rshiftNum uint8 // use to take bit for judging whether negative integer or not
|
||||||
mask uint64 // mask for number
|
mask uint64 // mask for number
|
||||||
indent int // indent number
|
indent int // indent number
|
||||||
rshiftNum uint8 // use to take bit for judging whether negative integer or not
|
|
||||||
mask uint64 // mask for number
|
|
||||||
|
|
||||||
idx uintptr // offset to access ptr
|
idx uintptr // offset to access ptr
|
||||||
headIdx uintptr // offset to access slice/struct head
|
headIdx uintptr // offset to access slice/struct head
|
||||||
|
@ -93,6 +92,7 @@ func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode {
|
||||||
isTaggedKey: c.isTaggedKey,
|
isTaggedKey: c.isTaggedKey,
|
||||||
anonymousKey: c.anonymousKey,
|
anonymousKey: c.anonymousKey,
|
||||||
root: c.root,
|
root: c.root,
|
||||||
|
indirect: c.indirect,
|
||||||
indent: c.indent,
|
indent: c.indent,
|
||||||
idx: c.idx,
|
idx: c.idx,
|
||||||
headIdx: c.headIdx,
|
headIdx: c.headIdx,
|
||||||
|
|
|
@ -1722,7 +1722,7 @@ func (t opType) headToPtrHead() opType {
|
||||||
}
|
}
|
||||||
suffix := "Ptr" + t.String()[idx+len("Field"):]
|
suffix := "Ptr" + t.String()[idx+len("Field"):]
|
||||||
|
|
||||||
const toPtrOffset = 12
|
const toPtrOffset = 6
|
||||||
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) + toPtrOffset)
|
return opType(int(t) + toPtrOffset)
|
||||||
}
|
}
|
||||||
|
@ -1743,7 +1743,7 @@ func (t opType) headToNPtrHead() opType {
|
||||||
}
|
}
|
||||||
suffix := "NPtr" + t.String()[idx+len("Field"):]
|
suffix := "NPtr" + t.String()[idx+len("Field"):]
|
||||||
|
|
||||||
const toPtrOffset = 24
|
const toPtrOffset = 12
|
||||||
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) + toPtrOffset)
|
return opType(int(t) + toPtrOffset)
|
||||||
}
|
}
|
||||||
|
@ -1751,7 +1751,7 @@ func (t opType) headToNPtrHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToAnonymousHead() opType {
|
func (t opType) headToAnonymousHead() opType {
|
||||||
const toAnonymousOffset = 6
|
const toAnonymousOffset = 3
|
||||||
if strings.Contains(opType(int(t)+toAnonymousOffset).String(), "Anonymous") {
|
if strings.Contains(opType(int(t)+toAnonymousOffset).String(), "Anonymous") {
|
||||||
return opType(int(t) + toAnonymousOffset)
|
return opType(int(t) + toAnonymousOffset)
|
||||||
}
|
}
|
||||||
|
@ -1759,7 +1759,7 @@ func (t opType) headToAnonymousHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToOmitEmptyHead() opType {
|
func (t opType) headToOmitEmptyHead() opType {
|
||||||
const toOmitEmptyOffset = 2
|
const toOmitEmptyOffset = 1
|
||||||
if strings.Contains(opType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") {
|
if strings.Contains(opType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") {
|
||||||
return opType(int(t) + toOmitEmptyOffset)
|
return opType(int(t) + toOmitEmptyOffset)
|
||||||
}
|
}
|
||||||
|
@ -1768,7 +1768,7 @@ func (t opType) headToOmitEmptyHead() opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToStringTagHead() opType {
|
func (t opType) headToStringTagHead() opType {
|
||||||
const toStringTagOffset = 4
|
const toStringTagOffset = 2
|
||||||
if strings.Contains(opType(int(t)+toStringTagOffset).String(), "StringTag") {
|
if strings.Contains(opType(int(t)+toStringTagOffset).String(), "StringTag") {
|
||||||
return opType(int(t) + toStringTagOffset)
|
return opType(int(t) + toStringTagOffset)
|
||||||
}
|
}
|
||||||
|
@ -1782,7 +1782,7 @@ func (t opType) ptrHeadToHead() opType {
|
||||||
}
|
}
|
||||||
suffix := t.String()[idx+len("Ptr"):]
|
suffix := t.String()[idx+len("Ptr"):]
|
||||||
|
|
||||||
const toPtrOffset = 12
|
const toPtrOffset = 6
|
||||||
if strings.Contains(opType(int(t)-toPtrOffset).String(), suffix) {
|
if strings.Contains(opType(int(t)-toPtrOffset).String(), suffix) {
|
||||||
return opType(int(t) - toPtrOffset)
|
return opType(int(t) - toPtrOffset)
|
||||||
}
|
}
|
||||||
|
|
1311
encode_vm.go
1311
encode_vm.go
File diff suppressed because it is too large
Load Diff
1297
encode_vm_escaped.go
1297
encode_vm_escaped.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1420
encode_vm_indent.go
1420
encode_vm_indent.go
File diff suppressed because it is too large
Load Diff
4
rtype.go
4
rtype.go
|
@ -244,6 +244,10 @@ func (t *rtype) Out(i int) reflect.Type {
|
||||||
return rtype_Out(t, i)
|
return rtype_Out(t, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname ifaceIndir reflect.ifaceIndir
|
||||||
|
//go:noescape
|
||||||
|
func ifaceIndir(*rtype) bool
|
||||||
|
|
||||||
//go:linkname rtype2type reflect.toType
|
//go:linkname rtype2type reflect.toType
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func rtype2type(t *rtype) reflect.Type
|
func rtype2type(t *rtype) reflect.Type
|
||||||
|
|
Loading…
Reference in New Issue