Merge pull request #230 from goccy/feature/fix-opcode-layout

Fix opcode layout
This commit is contained in:
Masaaki Goshima 2021-05-31 21:34:00 +09:00 committed by GitHub
commit ca4e811a0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 4223 additions and 4158 deletions

View File

@ -179,7 +179,13 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
} }
p := uintptr(header.ptr) p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength) var code *encoder.Opcode
if (opt & EncodeOptionHTMLEscape) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
ctx.Init(code, p, codeSet.CodeLength)
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
buf, err := encodeRunCode(ctx, b, codeSet, opt) buf, err := encodeRunCode(ctx, b, codeSet, opt)
@ -206,8 +212,14 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption
return nil, err return nil, err
} }
var code *encoder.Opcode
if (opt & EncodeOptionHTMLEscape) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
p := uintptr(header.ptr) p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength) ctx.Init(code, p, codeSet.CodeLength)
buf, err := encodeRunCode(ctx, b, codeSet, opt) buf, err := encodeRunCode(ctx, b, codeSet, opt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -233,8 +245,14 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
return nil, err return nil, err
} }
var code *encoder.Opcode
if (opt & EncodeOptionHTMLEscape) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
p := uintptr(header.ptr) p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength) ctx.Init(code, p, codeSet.CodeLength)
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent, opt) buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent, opt)
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)

View File

@ -48,7 +48,7 @@ var opTypeStrings = [{{ .OpLen }}]string{
{{- end }} {{- end }}
} }
type OpType int type OpType uint16
const ( const (
{{- range $index, $type := .OpTypes }} {{- range $index, $type := .OpTypes }}

File diff suppressed because it is too large Load Diff

View File

@ -55,19 +55,29 @@ func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) {
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
code, err := compileHead(&compileContext{ noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType, typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{}, structTypeToCompiledCode: map[uintptr]*CompiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
code = copyOpcode(code) escapeKeyCode, err := compileHead(&compileContext{
codeLength := code.TotalLength() typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{ codeSet := &OpcodeSet{
Type: copiedType, Type: copiedType,
Code: code, NoescapeKeyCode: noescapeKeyCode,
CodeLength: codeLength, EscapeKeyCode: escapeKeyCode,
CodeLength: codeLength,
} }
storeOpcodeSet(typeptr, codeSet, opcodeMap) storeOpcodeSet(typeptr, codeSet, opcodeMap)
return codeSet, nil return codeSet, nil
@ -246,6 +256,7 @@ func linkRecursiveCode(c *Opcode) {
continue continue
} }
code.Jmp.Code = copyOpcode(code.Jmp.Code) code.Jmp.Code = copyOpcode(code.Jmp.Code)
c := code.Jmp.Code c := code.Jmp.Code
c.End.Next = newEndOp(&compileContext{}) c.End.Next = newEndOp(&compileContext{})
c.Op = c.Op.PtrHeadToHead() c.Op = c.Op.PtrHeadToHead()
@ -268,6 +279,7 @@ func linkRecursiveCode(c *Opcode) {
code.Jmp.Linked = true code.Jmp.Linked = true
linkRecursiveCode(code.Jmp.Code) linkRecursiveCode(code.Jmp.Code)
code = code.Next code = code.Next
continue continue
} }
@ -518,9 +530,13 @@ func compileMarshalJSON(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpMarshalJSON) code := newOpCode(ctx, OpMarshalJSON)
typ := ctx.typ typ := ctx.typ
if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) { if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) {
code.AddrForMarshaler = true code.Flags |= AddrForMarshalerFlags
}
if isNilableType(typ) {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
} }
code.IsNilableType = isNilableType(typ)
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -529,9 +545,13 @@ func compileMarshalText(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpMarshalText) code := newOpCode(ctx, OpMarshalText)
typ := ctx.typ typ := ctx.typ
if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) { if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) {
code.AddrForMarshaler = true code.Flags |= AddrForMarshalerFlags
}
if isNilableType(typ) {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
} }
code.IsNilableType = isNilableType(typ)
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -540,7 +560,7 @@ const intSize = 32 << (^uint(0) >> 63)
func compileInt(ctx *compileContext) (*Opcode, error) { func compileInt(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpInt) code := newOpCode(ctx, OpInt)
code.setMaskAndRshiftNum(intSize) code.NumBitSize = intSize
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -556,7 +576,7 @@ func compileIntPtr(ctx *compileContext) (*Opcode, error) {
func compileInt8(ctx *compileContext) (*Opcode, error) { func compileInt8(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpInt) code := newOpCode(ctx, OpInt)
code.setMaskAndRshiftNum(8) code.NumBitSize = 8
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -572,7 +592,7 @@ func compileInt8Ptr(ctx *compileContext) (*Opcode, error) {
func compileInt16(ctx *compileContext) (*Opcode, error) { func compileInt16(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpInt) code := newOpCode(ctx, OpInt)
code.setMaskAndRshiftNum(16) code.NumBitSize = 16
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -588,7 +608,7 @@ func compileInt16Ptr(ctx *compileContext) (*Opcode, error) {
func compileInt32(ctx *compileContext) (*Opcode, error) { func compileInt32(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpInt) code := newOpCode(ctx, OpInt)
code.setMaskAndRshiftNum(32) code.NumBitSize = 32
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -604,7 +624,7 @@ func compileInt32Ptr(ctx *compileContext) (*Opcode, error) {
func compileInt64(ctx *compileContext) (*Opcode, error) { func compileInt64(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpInt) code := newOpCode(ctx, OpInt)
code.setMaskAndRshiftNum(64) code.NumBitSize = 64
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -620,7 +640,7 @@ func compileInt64Ptr(ctx *compileContext) (*Opcode, error) {
func compileUint(ctx *compileContext) (*Opcode, error) { func compileUint(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUint) code := newOpCode(ctx, OpUint)
code.setMaskAndRshiftNum(intSize) code.NumBitSize = intSize
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -636,7 +656,7 @@ func compileUintPtr(ctx *compileContext) (*Opcode, error) {
func compileUint8(ctx *compileContext) (*Opcode, error) { func compileUint8(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUint) code := newOpCode(ctx, OpUint)
code.setMaskAndRshiftNum(8) code.NumBitSize = 8
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -652,7 +672,7 @@ func compileUint8Ptr(ctx *compileContext) (*Opcode, error) {
func compileUint16(ctx *compileContext) (*Opcode, error) { func compileUint16(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUint) code := newOpCode(ctx, OpUint)
code.setMaskAndRshiftNum(16) code.NumBitSize = 16
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -668,7 +688,7 @@ func compileUint16Ptr(ctx *compileContext) (*Opcode, error) {
func compileUint32(ctx *compileContext) (*Opcode, error) { func compileUint32(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUint) code := newOpCode(ctx, OpUint)
code.setMaskAndRshiftNum(32) code.NumBitSize = 32
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -684,7 +704,7 @@ func compileUint32Ptr(ctx *compileContext) (*Opcode, error) {
func compileUint64(ctx *compileContext) (*Opcode, error) { func compileUint64(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUint) code := newOpCode(ctx, OpUint)
code.setMaskAndRshiftNum(64) code.NumBitSize = 64
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -700,70 +720,70 @@ func compileUint64Ptr(ctx *compileContext) (*Opcode, error) {
func compileIntString(ctx *compileContext) (*Opcode, error) { func compileIntString(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpIntString) code := newOpCode(ctx, OpIntString)
code.setMaskAndRshiftNum(intSize) code.NumBitSize = intSize
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileInt8String(ctx *compileContext) (*Opcode, error) { func compileInt8String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpIntString) code := newOpCode(ctx, OpIntString)
code.setMaskAndRshiftNum(8) code.NumBitSize = 8
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileInt16String(ctx *compileContext) (*Opcode, error) { func compileInt16String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpIntString) code := newOpCode(ctx, OpIntString)
code.setMaskAndRshiftNum(16) code.NumBitSize = 16
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileInt32String(ctx *compileContext) (*Opcode, error) { func compileInt32String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpIntString) code := newOpCode(ctx, OpIntString)
code.setMaskAndRshiftNum(32) code.NumBitSize = 32
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileInt64String(ctx *compileContext) (*Opcode, error) { func compileInt64String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpIntString) code := newOpCode(ctx, OpIntString)
code.setMaskAndRshiftNum(64) code.NumBitSize = 64
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileUintString(ctx *compileContext) (*Opcode, error) { func compileUintString(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUintString) code := newOpCode(ctx, OpUintString)
code.setMaskAndRshiftNum(intSize) code.NumBitSize = intSize
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileUint8String(ctx *compileContext) (*Opcode, error) { func compileUint8String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUintString) code := newOpCode(ctx, OpUintString)
code.setMaskAndRshiftNum(8) code.NumBitSize = 8
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileUint16String(ctx *compileContext) (*Opcode, error) { func compileUint16String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUintString) code := newOpCode(ctx, OpUintString)
code.setMaskAndRshiftNum(16) code.NumBitSize = 16
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileUint32String(ctx *compileContext) (*Opcode, error) { func compileUint32String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUintString) code := newOpCode(ctx, OpUintString)
code.setMaskAndRshiftNum(32) code.NumBitSize = 32
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
func compileUint64String(ctx *compileContext) (*Opcode, error) { func compileUint64String(ctx *compileContext) (*Opcode, error) {
code := newOpCode(ctx, OpUintString) code := newOpCode(ctx, OpUintString)
code.setMaskAndRshiftNum(64) code.NumBitSize = 64
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -879,7 +899,7 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
code.Indirect = true code.Flags |= IndirectFlags
// header => opcode => elem => end // header => opcode => elem => end
// ^ | // ^ |
@ -891,7 +911,6 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
end := newOpCode(ctx, OpSliceEnd) end := newOpCode(ctx, OpSliceEnd)
ctx.incIndex() ctx.incIndex()
header.Elem = elemCode
header.End = end header.End = end
header.Next = code header.Next = code
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode)) code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
@ -934,7 +953,7 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
code.Indirect = true code.Flags |= IndirectFlags
// header => opcode => elem => end // header => opcode => elem => end
// ^ | // ^ |
// |________| // |________|
@ -945,7 +964,6 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
end := newOpCode(ctx, OpArrayEnd) end := newOpCode(ctx, OpArrayEnd)
ctx.incIndex() ctx.incIndex()
header.Elem = elemCode
header.End = end header.End = end
header.Next = code header.Next = code
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode)) code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
@ -976,16 +994,13 @@ func compileMap(ctx *compileContext) (*Opcode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueCode.Indirect = true valueCode.Flags |= IndirectFlags
key := newMapKeyCode(ctx, header) key := newMapKeyCode(ctx, header)
ctx.incIndex() ctx.incIndex()
ctx = ctx.decIndent() ctx = ctx.decIndent()
header.MapKey = key
header.MapValue = value
end := newMapEndCode(ctx, header) end := newMapEndCode(ctx, header)
ctx.incIndex() ctx.incIndex()
@ -1052,8 +1067,7 @@ func compiledCode(ctx *compileContext) *Opcode {
func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode { func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
op := optimizeStructHeader(valueCode, tag) op := optimizeStructHeader(valueCode, tag)
fieldCode.Op = op fieldCode.Op = op
fieldCode.Mask = valueCode.Mask fieldCode.NumBitSize = valueCode.NumBitSize
fieldCode.RshiftNum = valueCode.RshiftNum
fieldCode.PtrNum = valueCode.PtrNum fieldCode.PtrNum = valueCode.PtrNum
if op.IsMultipleOpHead() { if op.IsMultipleOpHead() {
return valueCode.BeforeLastCode() return valueCode.BeforeLastCode()
@ -1065,9 +1079,8 @@ func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag
func structField(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode { func structField(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
op := optimizeStructField(valueCode, tag) op := optimizeStructField(valueCode, tag)
fieldCode.Op = op fieldCode.Op = op
fieldCode.NumBitSize = valueCode.NumBitSize
fieldCode.PtrNum = valueCode.PtrNum fieldCode.PtrNum = valueCode.PtrNum
fieldCode.Mask = valueCode.Mask
fieldCode.RshiftNum = valueCode.RshiftNum
if op.IsMultipleOpField() { if op.IsMultipleOpField() {
return valueCode.BeforeLastCode() return valueCode.BeforeLastCode()
} }
@ -1082,7 +1095,7 @@ func isNotExistsField(head *Opcode) bool {
if head.Op != OpStructHead { if head.Op != OpStructHead {
return false return false
} }
if !head.AnonymousHead { if (head.Flags & AnonymousHeadFlags) == 0 {
return false return false
} }
if head.Next == nil { if head.Next == nil {
@ -1117,7 +1130,7 @@ func optimizeAnonymousFields(head *Opcode) {
if isNotExistsField(code.Next) { if isNotExistsField(code.Next) {
code.Next = code.NextField code.Next = code.NextField
diff := code.Next.DisplayIdx - code.DisplayIdx diff := code.Next.DisplayIdx - code.DisplayIdx
for i := 0; i < diff; i++ { for i := uint32(0); i < diff; i++ {
code.Next.decOpcodeIndex() code.Next.decOpcodeIndex()
} }
linkPrevToNextField(code, removedFields) linkPrevToNextField(code, removedFields)
@ -1147,20 +1160,20 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
isHeadOp := strings.Contains(f.Op.String(), "Head") isHeadOp := strings.Contains(f.Op.String(), "Head")
if existsKey && f.Next != nil && strings.Contains(f.Next.Op.String(), "Recursive") { if existsKey && f.Next != nil && strings.Contains(f.Next.Op.String(), "Recursive") {
// through // through
} else if isHeadOp && !f.AnonymousHead { } else if isHeadOp && (f.Flags&AnonymousHeadFlags) == 0 {
if existsKey { if existsKey {
// TODO: need to remove this head // TODO: need to remove this head
f.Op = OpStructHead f.Op = OpStructHead
f.AnonymousKey = true f.Flags |= AnonymousKeyFlags
f.AnonymousHead = true f.Flags |= AnonymousHeadFlags
} else if named == "" { } else if named == "" {
f.AnonymousHead = true f.Flags |= AnonymousHeadFlags
} }
} else if named == "" && f.Op == OpStructEnd { } else if named == "" && f.Op == OpStructEnd {
f.Op = OpStructAnonymousEnd f.Op = OpStructAnonymousEnd
} else if existsKey { } else if existsKey {
diff := f.NextField.DisplayIdx - f.DisplayIdx diff := f.NextField.DisplayIdx - f.DisplayIdx
for i := 0; i < diff; i++ { for i := uint32(0); i < diff; i++ {
f.NextField.decOpcodeIndex() f.NextField.decOpcodeIndex()
} }
linkPrevToNextField(f, removedFields) linkPrevToNextField(f, removedFields)
@ -1179,7 +1192,7 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
anonymousFields[key] = append(anonymousFields[key], structFieldPair{ anonymousFields[key] = append(anonymousFields[key], structFieldPair{
prevField: prevAnonymousField, prevField: prevAnonymousField,
curField: f, curField: f,
isTaggedKey: f.IsTaggedKey, isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
}) })
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField { if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
for k, v := range anonymousFieldPairRecursively(named, f.Next) { for k, v := range anonymousFieldPairRecursively(named, f.Next) {
@ -1200,12 +1213,12 @@ func anonymousFieldPairRecursively(named string, valueCode *Opcode) map[string][
f := valueCode f := valueCode
var prevAnonymousField *Opcode var prevAnonymousField *Opcode
for { for {
if f.DisplayKey != "" && f.AnonymousHead { if f.DisplayKey != "" && (f.Flags&AnonymousHeadFlags) != 0 {
key := fmt.Sprintf("%s.%s", named, f.DisplayKey) key := fmt.Sprintf("%s.%s", named, f.DisplayKey)
anonymousFields[key] = append(anonymousFields[key], structFieldPair{ anonymousFields[key] = append(anonymousFields[key], structFieldPair{
prevField: prevAnonymousField, prevField: prevAnonymousField,
curField: f, curField: f,
isTaggedKey: f.IsTaggedKey, isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
}) })
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField { if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
for k, v := range anonymousFieldPairRecursively(named, f.Next) { for k, v := range anonymousFieldPairRecursively(named, f.Next) {
@ -1238,11 +1251,11 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
if fieldPair.prevField == nil { if fieldPair.prevField == nil {
// head operation // head operation
fieldPair.curField.Op = OpStructHead fieldPair.curField.Op = OpStructHead
fieldPair.curField.AnonymousHead = true fieldPair.curField.Flags |= AnonymousHeadFlags
fieldPair.curField.AnonymousKey = true fieldPair.curField.Flags |= AnonymousKeyFlags
} 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 := uint32(0); i < diff; i++ {
fieldPair.curField.NextField.decOpcodeIndex() fieldPair.curField.NextField.decOpcodeIndex()
} }
removedFields[fieldPair.curField] = struct{}{} removedFields[fieldPair.curField] = struct{}{}
@ -1258,12 +1271,12 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
if fieldPair.prevField == nil { if fieldPair.prevField == nil {
// head operation // head operation
fieldPair.curField.Op = OpStructHead fieldPair.curField.Op = OpStructHead
fieldPair.curField.AnonymousHead = true fieldPair.curField.Flags |= AnonymousHeadFlags
fieldPair.curField.AnonymousKey = true fieldPair.curField.Flags |= AnonymousKeyFlags
} else { } else {
diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx
removedFields[fieldPair.curField] = struct{}{} removedFields[fieldPair.curField] = struct{}{}
for i := 0; i < diff; i++ { for i := uint32(0); i < diff; i++ {
fieldPair.curField.NextField.decOpcodeIndex() fieldPair.curField.NextField.decOpcodeIndex()
} }
linkPrevToNextField(fieldPair.curField, removedFields) linkPrevToNextField(fieldPair.curField, removedFields)
@ -1273,7 +1286,7 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
} }
} else { } else {
for _, fieldPair := range taggedPairs { for _, fieldPair := range taggedPairs {
fieldPair.curField.IsTaggedKey = false fieldPair.curField.Flags &= ^IsTaggedKeyFlags
} }
} }
} }
@ -1402,46 +1415,68 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
// fix issue144 // fix issue144
if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) { if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) {
valueCode.Indirect = indirect if indirect {
valueCode.Flags |= IndirectFlags
} else {
valueCode.Flags &= ^IndirectFlags
}
} }
} else { } else {
if indirect { if indirect {
// if parent is indirect type, set child indirect property to true // if parent is indirect type, set child indirect property to true
valueCode.Indirect = indirect valueCode.Flags |= IndirectFlags
} else { } else {
// if parent is not indirect type and child have only one field, set child indirect property to false // if parent is not indirect type and child have only one field, set child indirect property to false
if i == 0 && valueCode.NextField != nil && valueCode.NextField.Op == OpStructEnd { if i == 0 && valueCode.NextField != nil && valueCode.NextField.Op == OpStructEnd {
valueCode.Indirect = indirect valueCode.Flags &= ^IndirectFlags
} }
} }
} }
key := fmt.Sprintf(`"%s":`, tag.Key) var flags OpFlags
escapedKey := fmt.Sprintf(`%s:`, string(AppendEscapedString([]byte{}, tag.Key))) if indirect {
flags |= IndirectFlags
}
if field.Anonymous {
flags |= AnonymousKeyFlags
}
if tag.IsTaggedKey {
flags |= IsTaggedKeyFlags
}
if nilcheck {
flags |= NilCheckFlags
}
if addrForMarshaler {
flags |= AddrForMarshalerFlags
}
if strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface {
flags |= IsNextOpPtrTypeFlags
}
if isNilableType {
flags |= IsNilableTypeFlags
}
var key string
if ctx.escapeKey {
key = fmt.Sprintf(`%s:`, string(AppendEscapedString([]byte{}, tag.Key)))
} else {
key = fmt.Sprintf(`"%s":`, tag.Key)
}
fieldCode := &Opcode{ fieldCode := &Opcode{
Type: valueCode.Type, Idx: opcodeOffset(fieldPtrIndex),
DisplayIdx: fieldOpcodeIndex, Next: valueCode,
Idx: opcodeOffset(fieldPtrIndex), Flags: flags,
Next: valueCode, Key: key,
Indent: ctx.indent, Offset: uint32(field.Offset),
AnonymousKey: field.Anonymous, Type: valueCode.Type,
Key: []byte(key), DisplayIdx: fieldOpcodeIndex,
EscapedKey: []byte(escapedKey), Indent: ctx.indent,
IsTaggedKey: tag.IsTaggedKey, DisplayKey: tag.Key,
DisplayKey: tag.Key,
Offset: field.Offset,
Indirect: indirect,
Nilcheck: nilcheck,
AddrForMarshaler: addrForMarshaler,
IsNextOpPtrType: strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface,
IsNilableType: isNilableType,
} }
if fieldIdx == 0 { if fieldIdx == 0 {
fieldCode.HeadIdx = fieldCode.Idx
code = structHeader(ctx, fieldCode, valueCode, tag) code = structHeader(ctx, fieldCode, valueCode, tag)
head = fieldCode head = fieldCode
prevField = fieldCode prevField = fieldCode
} else { } else {
fieldCode.HeadIdx = head.HeadIdx fieldCode.Idx = head.Idx
code.Next = fieldCode code.Next = fieldCode
code = structField(ctx, fieldCode, valueCode, tag) code = structField(ctx, fieldCode, valueCode, tag)
prevField.NextField = fieldCode prevField.NextField = fieldCode
@ -1453,9 +1488,9 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
structEndCode := &Opcode{ structEndCode := &Opcode{
Op: OpStructEnd, Op: OpStructEnd,
Next: newEndOp(ctx),
Type: nil, Type: nil,
Indent: ctx.indent, Indent: ctx.indent,
Next: newEndOp(ctx),
} }
ctx = ctx.decIndent() ctx = ctx.decIndent()
@ -1464,12 +1499,11 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
if head == nil { if head == nil {
head = &Opcode{ head = &Opcode{
Op: OpStructHead, Op: OpStructHead,
Idx: opcodeOffset(ctx.ptrIndex),
NextField: structEndCode,
Type: typ, Type: typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex),
HeadIdx: opcodeOffset(ctx.ptrIndex),
Indent: ctx.indent, Indent: ctx.indent,
NextField: structEndCode,
} }
structEndCode.PrevField = head structEndCode.PrevField = head
ctx.incIndex() ctx.incIndex()
@ -1494,8 +1528,8 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
delete(ctx.structTypeToCompiledCode, typeptr) delete(ctx.structTypeToCompiledCode, typeptr)
if !disableIndirectConversion && !head.Indirect && isPtr { if !disableIndirectConversion && (head.Flags&IndirectFlags == 0) && isPtr {
head.Indirect = true head.Flags |= IndirectFlags
} }
return ret, nil return ret, nil

View File

@ -20,19 +20,29 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
code, err := compileHead(&compileContext{ noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType, typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{}, structTypeToCompiledCode: map[uintptr]*CompiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
code = copyOpcode(code) escapeKeyCode, err := compileHead(&compileContext{
codeLength := code.TotalLength() typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{ codeSet := &OpcodeSet{
Type: copiedType, Type: copiedType,
Code: code, NoescapeKeyCode: noescapeKeyCode,
CodeLength: codeLength, EscapeKeyCode: escapeKeyCode,
CodeLength: codeLength,
} }
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet
return codeSet, nil return codeSet, nil

View File

@ -26,19 +26,30 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
code, err := compileHead(&compileContext{ noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType, typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{}, structTypeToCompiledCode: map[uintptr]*CompiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
code = copyOpcode(code) escapeKeyCode, err := compileHead(&compileContext{
codeLength := code.TotalLength() typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{ codeSet := &OpcodeSet{
Type: copiedType, Type: copiedType,
Code: code, NoescapeKeyCode: noescapeKeyCode,
CodeLength: codeLength, EscapeKeyCode: escapeKeyCode,
CodeLength: codeLength,
} }
setsMu.Lock() setsMu.Lock()
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet

View File

@ -9,9 +9,10 @@ import (
type compileContext struct { type compileContext struct {
typ *runtime.Type typ *runtime.Type
opcodeIndex int opcodeIndex uint32
ptrIndex int ptrIndex int
indent int indent uint32
escapeKey bool
structTypeToCompiledCode map[uintptr]*CompiledCode structTypeToCompiledCode map[uintptr]*CompiledCode
parent *compileContext parent *compileContext
@ -23,6 +24,7 @@ func (c *compileContext) context() *compileContext {
opcodeIndex: c.opcodeIndex, opcodeIndex: c.opcodeIndex,
ptrIndex: c.ptrIndex, ptrIndex: c.ptrIndex,
indent: c.indent, indent: c.indent,
escapeKey: c.escapeKey,
structTypeToCompiledCode: c.structTypeToCompiledCode, structTypeToCompiledCode: c.structTypeToCompiledCode,
parent: c, parent: c,
} }
@ -106,12 +108,13 @@ type RuntimeContext struct {
Ptrs []uintptr Ptrs []uintptr
KeepRefs []unsafe.Pointer KeepRefs []unsafe.Pointer
SeenPtr []uintptr SeenPtr []uintptr
BaseIndent int BaseIndent uint32
Prefix []byte Prefix []byte
IndentStr []byte IndentStr []byte
Code *Opcode
} }
func (c *RuntimeContext) Init(p uintptr, codelen int) { func (c *RuntimeContext) Init(code *Opcode, p uintptr, codelen int) {
if len(c.Ptrs) < codelen { if len(c.Ptrs) < codelen {
c.Ptrs = make([]uintptr, codelen) c.Ptrs = make([]uintptr, codelen)
} }
@ -119,6 +122,7 @@ func (c *RuntimeContext) Init(p uintptr, codelen int) {
c.KeepRefs = c.KeepRefs[:0] c.KeepRefs = c.KeepRefs[:0]
c.SeenPtr = c.SeenPtr[:0] c.SeenPtr = c.SeenPtr[:0]
c.BaseIndent = 0 c.BaseIndent = 0
c.Code = code
} }
func (c *RuntimeContext) Ptr() uintptr { func (c *RuntimeContext) Ptr() uintptr {

View File

@ -14,5 +14,5 @@ func TestDumpOpcode(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
codeSet.Code.Dump() codeSet.EscapeKeyCode.Dump()
} }

View File

@ -102,9 +102,10 @@ func (t OpType) IsMultipleOpField() bool {
} }
type OpcodeSet struct { type OpcodeSet struct {
Type *runtime.Type Type *runtime.Type
Code *Opcode NoescapeKeyCode *Opcode
CodeLength int EscapeKeyCode *Opcode
CodeLength int
} }
type CompiledCode struct { type CompiledCode struct {
@ -362,7 +363,7 @@ func AppendNumber(b []byte, n json.Number) ([]byte, error) {
func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) { func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type rv := reflect.ValueOf(v) // convert by dynamic interface type
if code.AddrForMarshaler { if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() { if rv.CanAddr() {
rv = rv.Addr() rv = rv.Addr()
} else { } else {
@ -392,7 +393,7 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) { func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type rv := reflect.ValueOf(v) // convert by dynamic interface type
if code.AddrForMarshaler { if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() { if rv.CanAddr() {
rv = rv.Addr() rv = rv.Addr()
} else { } else {
@ -415,7 +416,7 @@ func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v inte
indentedBuf, err := doIndent( indentedBuf, err := doIndent(
b, b,
marshalBuf, marshalBuf,
string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), ctx.BaseIndent+code.Indent), string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)),
string(ctx.IndentStr), string(ctx.IndentStr),
escape, escape,
) )
@ -428,7 +429,7 @@ func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v inte
func AppendMarshalText(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) { func AppendMarshalText(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type rv := reflect.ValueOf(v) // convert by dynamic interface type
if code.AddrForMarshaler { if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() { if rv.CanAddr() {
rv = rv.Addr() rv = rv.Addr()
} else { } else {
@ -454,7 +455,7 @@ func AppendMarshalText(code *Opcode, b []byte, v interface{}, escape bool) ([]by
func AppendMarshalTextIndent(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) { func AppendMarshalTextIndent(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type rv := reflect.ValueOf(v) // convert by dynamic interface type
if code.AddrForMarshaler { if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() { if rv.CanAddr() {
rv = rv.Addr() rv = rv.Addr()
} else { } else {
@ -498,16 +499,16 @@ func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte {
b = append(b, '\n') b = append(b, '\n')
b = append(b, ctx.Prefix...) b = append(b, ctx.Prefix...)
indentNum := ctx.BaseIndent + code.Indent - 1 indentNum := ctx.BaseIndent + code.Indent - 1
for i := 0; i < indentNum; i++ { for i := uint32(0); i < indentNum; i++ {
b = append(b, ctx.IndentStr...) b = append(b, ctx.IndentStr...)
} }
return append(b, '}', ',', '\n') return append(b, '}', ',', '\n')
} }
func AppendIndent(ctx *RuntimeContext, b []byte, indent int) []byte { func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte {
b = append(b, ctx.Prefix...) b = append(b, ctx.Prefix...)
indentNum := ctx.BaseIndent + indent indentNum := ctx.BaseIndent + indent
for i := 0; i < indentNum; i++ { for i := uint32(0); i < indentNum; i++ {
b = append(b, ctx.IndentStr...) b = append(b, ctx.IndentStr...)
} }
return b return b

View File

@ -49,9 +49,14 @@ var intBELookup = [100]uint16{
var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup} var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup}
func numMask(numBitSize uint8) uint64 {
return 1<<numBitSize - 1
}
func AppendInt(out []byte, u64 uint64, code *Opcode) []byte { func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
n := u64 & code.Mask mask := numMask(code.NumBitSize)
negative := (u64>>code.RshiftNum)&1 == 1 n := u64 & mask
negative := (u64>>(code.NumBitSize-1))&1 == 1
if !negative { if !negative {
if n < 10 { if n < 10 {
return append(out, byte(n+'0')) return append(out, byte(n+'0'))
@ -60,7 +65,7 @@ func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
return append(out, byte(u), byte(u>>8)) return append(out, byte(u), byte(u>>8))
} }
} else { } else {
n = -n & code.Mask n = -n & mask
} }
lookup := intLookup[endianness] lookup := intLookup[endianness]
@ -92,7 +97,8 @@ func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
} }
func AppendUint(out []byte, u64 uint64, code *Opcode) []byte { func AppendUint(out []byte, u64 uint64, code *Opcode) []byte {
n := u64 & code.Mask mask := numMask(code.NumBitSize)
n := u64 & mask
if n < 10 { if n < 10 {
return append(out, byte(n+'0')) return append(out, byte(n+'0'))
} else if n < 100 { } else if n < 100 {

View File

@ -2,7 +2,6 @@ package encoder
import ( import (
"fmt" "fmt"
"math"
"strings" "strings"
"unsafe" "unsafe"
@ -11,61 +10,43 @@ import (
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)
type OpFlags uint8
const (
AnonymousHeadFlags OpFlags = 1 << 0
AnonymousKeyFlags OpFlags = 1 << 1
IndirectFlags OpFlags = 1 << 2
IsTaggedKeyFlags OpFlags = 1 << 3
NilCheckFlags OpFlags = 1 << 4
AddrForMarshalerFlags OpFlags = 1 << 5
IsNextOpPtrTypeFlags OpFlags = 1 << 6
IsNilableTypeFlags OpFlags = 1 << 7
)
type Opcode struct { type Opcode struct {
Op OpType // operation type Op OpType // operation type
Type *runtime.Type // go type Idx uint32 // offset to access ptr
DisplayIdx int // opcode index Next *Opcode // next opcode
Key []byte // struct field key End *Opcode // array/slice/struct/map end
EscapedKey []byte // struct field key ( HTML escaped ) NextField *Opcode // next struct field
PtrNum int // pointer number: e.g. double pointer is 2. Key string // struct field key
DisplayKey string // key text to display Offset uint32 // offset size from struct header
IsTaggedKey bool // whether tagged key PtrNum uint8 // pointer number: e.g. double pointer is 2.
AnonymousKey bool // whether anonymous key Flags OpFlags
AnonymousHead bool // whether anonymous head or not NumBitSize uint8
Indirect bool // whether indirect or not _ [1]uint8 // 1
Nilcheck bool // whether needs to nilcheck or not
AddrForMarshaler bool // whether needs to addr for marshaler or not
IsNextOpPtrType bool // whether next operation is ptr type or not
IsNilableType bool // whether type is nilable or not
RshiftNum uint8 // use to take bit for judging whether negative integer or not
Mask uint64 // mask for number
Indent int // indent number
Idx uintptr // offset to access ptr Type *runtime.Type // go type
HeadIdx uintptr // offset to access slice/struct head PrevField *Opcode // prev struct field
ElemIdx uintptr // offset to access array/slice/map elem Jmp *CompiledCode // for recursive call
Length uintptr // offset to access slice/map length or array length ElemIdx uint32 // offset to access array/slice/map elem
MapIter uintptr // offset to access map iterator Length uint32 // offset to access slice/map length or array length
MapPos uintptr // offset to access position list for sorted map MapIter uint32 // offset to access map iterator
Offset uintptr // offset size from struct header MapPos uint32 // offset to access position list for sorted map
Size uintptr // array/slice elem size Indent uint32 // indent number
Size uint32 // array/slice elem size
MapKey *Opcode // map key DisplayIdx uint32 // opcode index
MapValue *Opcode // map value DisplayKey string // key text to display
Elem *Opcode // array/slice elem
End *Opcode // array/slice/struct/map end
PrevField *Opcode // prev struct field
NextField *Opcode // next struct field
Next *Opcode // next opcode
Jmp *CompiledCode // for recursive call
}
func rshitNum(bitSize uint8) uint8 {
return bitSize - 1
}
func (c *Opcode) setMaskAndRshiftNum(bitSize uint8) {
switch bitSize {
case 8:
c.Mask = math.MaxUint8
case 16:
c.Mask = math.MaxUint16
case 32:
c.Mask = math.MaxUint32
case 64:
c.Mask = math.MaxUint64
}
c.RshiftNum = rshitNum(bitSize)
} }
func (c *Opcode) ToHeaderType(isString bool) OpType { func (c *Opcode) ToHeaderType(isString bool) OpType {
@ -278,8 +259,8 @@ func newOpCode(ctx *compileContext, op OpType) *Opcode {
return newOpCodeWithNext(ctx, op, newEndOp(ctx)) return newOpCodeWithNext(ctx, op, newEndOp(ctx))
} }
func opcodeOffset(idx int) uintptr { func opcodeOffset(idx int) uint32 {
return uintptr(idx) * uintptrSize return uint32(idx) * uintptrSize
} }
func copyOpcode(code *Opcode) *Opcode { func copyOpcode(code *Opcode) *Opcode {
@ -290,11 +271,11 @@ func copyOpcode(code *Opcode) *Opcode {
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode { func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: op, Op: op,
Idx: opcodeOffset(ctx.ptrIndex),
Next: next,
Type: ctx.typ, Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent, Indent: ctx.indent,
Idx: opcodeOffset(ctx.ptrIndex),
Next: next,
} }
} }
@ -311,37 +292,24 @@ func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
return code return code
} }
copied := &Opcode{ copied := &Opcode{
Op: c.Op, Op: c.Op,
Type: c.Type, Key: c.Key,
DisplayIdx: c.DisplayIdx, PtrNum: c.PtrNum,
Key: c.Key, NumBitSize: c.NumBitSize,
EscapedKey: c.EscapedKey, Flags: c.Flags,
DisplayKey: c.DisplayKey, Idx: c.Idx,
PtrNum: c.PtrNum, Offset: c.Offset,
Mask: c.Mask, Type: c.Type,
RshiftNum: c.RshiftNum, DisplayIdx: c.DisplayIdx,
IsTaggedKey: c.IsTaggedKey, DisplayKey: c.DisplayKey,
AnonymousKey: c.AnonymousKey, ElemIdx: c.ElemIdx,
AnonymousHead: c.AnonymousHead, Length: c.Length,
Indirect: c.Indirect, MapIter: c.MapIter,
Nilcheck: c.Nilcheck, MapPos: c.MapPos,
AddrForMarshaler: c.AddrForMarshaler, Size: c.Size,
IsNextOpPtrType: c.IsNextOpPtrType, Indent: c.Indent,
IsNilableType: c.IsNilableType,
Indent: c.Indent,
Idx: c.Idx,
HeadIdx: c.HeadIdx,
ElemIdx: c.ElemIdx,
Length: c.Length,
MapIter: c.MapIter,
MapPos: c.MapPos,
Offset: c.Offset,
Size: c.Size,
} }
codeMap[addr] = copied codeMap[addr] = copied
copied.MapKey = c.MapKey.copy(codeMap)
copied.MapValue = c.MapValue.copy(codeMap)
copied.Elem = c.Elem.copy(codeMap)
copied.End = c.End.copy(codeMap) copied.End = c.End.copy(codeMap)
copied.PrevField = c.PrevField.copy(codeMap) copied.PrevField = c.PrevField.copy(codeMap)
copied.NextField = c.NextField.copy(codeMap) copied.NextField = c.NextField.copy(codeMap)
@ -387,9 +355,8 @@ func (c *Opcode) TotalLength() int {
func (c *Opcode) decOpcodeIndex() { func (c *Opcode) decOpcodeIndex() {
for code := c; code.Op != OpEnd; { for code := c; code.Op != OpEnd; {
code.DisplayIdx-- code.DisplayIdx--
code.Idx -= uintptrSize if code.Idx > 0 {
if code.HeadIdx > 0 { code.Idx -= uintptrSize
code.HeadIdx -= uintptrSize
} }
if code.ElemIdx > 0 { if code.ElemIdx > 0 {
code.ElemIdx -= uintptrSize code.ElemIdx -= uintptrSize
@ -422,19 +389,18 @@ func (c *Opcode) decIndent() {
} }
func (c *Opcode) dumpHead(code *Opcode) string { func (c *Opcode) dumpHead(code *Opcode) string {
var length uintptr var length uint32
if code.Op.CodeType() == CodeArrayHead { if code.Op.CodeType() == CodeArrayHead {
length = code.Length length = code.Length
} else { } else {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d])`, `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.HeadIdx/uintptrSize,
code.ElemIdx/uintptrSize, code.ElemIdx/uintptrSize,
length, length,
) )
@ -442,12 +408,11 @@ func (c *Opcode) dumpHead(code *Opcode) string {
func (c *Opcode) dumpMapHead(code *Opcode) string { func (c *Opcode) dumpMapHead(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.HeadIdx/uintptrSize,
code.ElemIdx/uintptrSize, code.ElemIdx/uintptrSize,
code.Length/uintptrSize, code.Length/uintptrSize,
code.MapIter/uintptrSize, code.MapIter/uintptrSize,
@ -458,7 +423,7 @@ func (c *Opcode) dumpMapEnd(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`, `[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.MapPos/uintptrSize, code.MapPos/uintptrSize,
@ -467,19 +432,18 @@ func (c *Opcode) dumpMapEnd(code *Opcode) string {
} }
func (c *Opcode) dumpElem(code *Opcode) string { func (c *Opcode) dumpElem(code *Opcode) string {
var length uintptr var length uint32
if code.Op.CodeType() == CodeArrayElem { if code.Op.CodeType() == CodeArrayElem {
length = code.Length length = code.Length
} else { } else {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][size:%d])`, `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.HeadIdx/uintptrSize,
code.ElemIdx/uintptrSize, code.ElemIdx/uintptrSize,
length, length,
code.Size, code.Size,
@ -488,14 +452,13 @@ func (c *Opcode) dumpElem(code *Opcode) string {
func (c *Opcode) dumpField(code *Opcode) string { func (c *Opcode) dumpField(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][key:%s][offset:%d][headIdx:%d])`, `[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.DisplayKey, code.DisplayKey,
code.Offset, code.Offset,
code.HeadIdx/uintptrSize,
) )
} }
@ -503,7 +466,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.ElemIdx/uintptrSize, code.ElemIdx/uintptrSize,
@ -516,7 +479,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapIter:%d])`, `[%d]%s%s ([idx:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
code.MapIter/uintptrSize, code.MapIter/uintptrSize,
@ -555,7 +518,7 @@ func (c *Opcode) Dump() string {
codes = append(codes, fmt.Sprintf( codes = append(codes, fmt.Sprintf(
"[%d]%s%s ([idx:%d])", "[%d]%s%s ([idx:%d])",
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", code.Indent), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
code.Idx/uintptrSize, code.Idx/uintptrSize,
)) ))
@ -610,9 +573,8 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
length := opcodeOffset(ctx.ptrIndex) length := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpSlice, Op: OpSlice,
DisplayIdx: ctx.opcodeIndex,
Idx: idx, Idx: idx,
HeadIdx: idx, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
Length: length, Length: length,
Indent: ctx.indent, Indent: ctx.indent,
@ -622,13 +584,12 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode { func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpSliceElem, Op: OpSliceElem,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex),
HeadIdx: head.Idx,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
Length: head.Length, Length: head.Length,
Indent: ctx.indent, Indent: ctx.indent,
Size: size, Size: uint32(size),
} }
} }
@ -638,25 +599,23 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpArray, Op: OpArray,
DisplayIdx: ctx.opcodeIndex,
Idx: idx, Idx: idx,
HeadIdx: idx, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
Indent: ctx.indent, Indent: ctx.indent,
Length: uintptr(alen), Length: uint32(alen),
} }
} }
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode { func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpArrayElem, Op: OpArrayElem,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex),
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
HeadIdx: head.HeadIdx, Length: uint32(length),
Length: uintptr(length),
Indent: ctx.indent, Indent: ctx.indent,
Size: size, Size: uint32(size),
} }
} }
@ -670,9 +629,9 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
mapIter := opcodeOffset(ctx.ptrIndex) mapIter := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMap, Op: OpMap,
Idx: idx,
Type: ctx.typ, Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: idx,
ElemIdx: elemIdx, ElemIdx: elemIdx,
Length: length, Length: length,
MapIter: mapIter, MapIter: mapIter,
@ -683,8 +642,8 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode { func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapKey, Op: OpMapKey,
DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
Length: head.Length, Length: head.Length,
MapIter: head.MapIter, MapIter: head.MapIter,
@ -695,8 +654,8 @@ func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode { func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapValue, Op: OpMapValue,
DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
Length: head.Length, Length: head.Length,
MapIter: head.MapIter, MapIter: head.MapIter,
@ -710,34 +669,34 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMapEnd, Op: OpMapEnd,
DisplayIdx: ctx.opcodeIndex,
Idx: idx, Idx: idx,
Next: newEndOp(ctx),
DisplayIdx: ctx.opcodeIndex,
Length: head.Length, Length: head.Length,
MapPos: mapPos, MapPos: mapPos,
Indent: ctx.indent, Indent: ctx.indent,
Next: newEndOp(ctx),
} }
} }
func newInterfaceCode(ctx *compileContext) *Opcode { func newInterfaceCode(ctx *compileContext) *Opcode {
return &Opcode{ return &Opcode{
Op: OpInterface, Op: OpInterface,
Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx),
Type: ctx.typ, Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex),
Indent: ctx.indent, Indent: ctx.indent,
Next: newEndOp(ctx),
} }
} }
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode { func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpRecursive, Op: OpRecursive,
Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx),
Type: ctx.typ, Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Idx: opcodeOffset(ctx.ptrIndex),
Indent: ctx.indent, Indent: ctx.indent,
Next: newEndOp(ctx),
Jmp: jmp, Jmp: jmp,
} }
} }

View File

@ -425,7 +425,7 @@ var opTypeStrings = [400]string{
"StructEndOmitEmpty", "StructEndOmitEmpty",
} }
type OpType int type OpType uint16
const ( const (
OpEnd OpType = 0 OpEnd OpType = 0

View File

@ -14,7 +14,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
fmt.Println(codeSet.Type) fmt.Println(codeSet.Type)
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [ALL OPCODE]") fmt.Println("* [ALL OPCODE]")
fmt.Println(codeSet.Code.Dump()) fmt.Println(ctx.Code.Dump())
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [CONTEXT]") fmt.Println("* [CONTEXT]")
fmt.Printf("%+v\n", ctx) fmt.Printf("%+v\n", ctx)

View File

@ -37,20 +37,20 @@ func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder: opcode %s has not been implemented", op) return fmt.Errorf("encoder: opcode %s has not been implemented", op)
} }
func load(base uintptr, idx uintptr) uintptr { func load(base uintptr, idx uint32) uintptr {
addr := base + idx addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr)) return **(**uintptr)(unsafe.Pointer(&addr))
} }
func store(base uintptr, idx uintptr, p uintptr) { func store(base uintptr, idx uint32, p uintptr) {
addr := base + idx addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p **(**uintptr)(unsafe.Pointer(&addr)) = p
} }
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + idx addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr)) p := **(**uintptr)(unsafe.Pointer(&addr))
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -70,8 +70,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
func ptrToPtr(p uintptr) uintptr { func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
} }
func ptrToNPtr(p uintptr, ptrNum int) uintptr { func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -146,6 +146,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
newPtrs[0] = uintptr(iface.ptr) newPtrs[0] = uintptr(iface.ptr)
ctx.Ptrs = newPtrs ctx.Ptrs = newPtrs
ctx.Code = ifaceCodeSet.NoescapeKeyCode
bb, err := Run(ctx, b, ifaceCodeSet, opt) bb, err := Run(ctx, b, ifaceCodeSet, opt)
if err != nil { if err != nil {

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
fmt.Println(codeSet.Type) fmt.Println(codeSet.Type)
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [ALL OPCODE]") fmt.Println("* [ALL OPCODE]")
fmt.Println(codeSet.Code.Dump()) fmt.Println(ctx.Code.Dump())
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [CONTEXT]") fmt.Println("* [CONTEXT]")
fmt.Printf("%+v\n", ctx) fmt.Printf("%+v\n", ctx)

View File

@ -37,20 +37,20 @@ func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder (escaped): opcode %s has not been implemented", op) return fmt.Errorf("encoder (escaped): opcode %s has not been implemented", op)
} }
func load(base uintptr, idx uintptr) uintptr { func load(base uintptr, idx uint32) uintptr {
addr := base + idx addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr)) return **(**uintptr)(unsafe.Pointer(&addr))
} }
func store(base uintptr, idx uintptr, p uintptr) { func store(base uintptr, idx uint32, p uintptr) {
addr := base + idx addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p **(**uintptr)(unsafe.Pointer(&addr)) = p
} }
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + idx addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr)) p := **(**uintptr)(unsafe.Pointer(&addr))
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -70,8 +70,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
func ptrToPtr(p uintptr) uintptr { func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
} }
func ptrToNPtr(p uintptr, ptrNum int) uintptr { func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -146,6 +146,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
newPtrs[0] = uintptr(iface.ptr) newPtrs[0] = uintptr(iface.ptr)
ctx.Ptrs = newPtrs ctx.Ptrs = newPtrs
ctx.Code = ifaceCodeSet.EscapeKeyCode
bb, err := Run(ctx, b, ifaceCodeSet, opt) bb, err := Run(ctx, b, ifaceCodeSet, opt)
if err != nil { if err != nil {
@ -193,7 +194,7 @@ func appendStructHead(b []byte) []byte {
} }
func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return append(b, code.EscapedKey...) return append(b, code.Key...)
} }
func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
fmt.Println(codeSet.Type) fmt.Println(codeSet.Type)
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [ALL OPCODE]") fmt.Println("* [ALL OPCODE]")
fmt.Println(codeSet.Code.Dump()) fmt.Println(ctx.Code.Dump())
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [CONTEXT]") fmt.Println("* [CONTEXT]")
fmt.Printf("%+v\n", ctx) fmt.Printf("%+v\n", ctx)

View File

@ -39,20 +39,20 @@ func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder (indent+escaped): opcode %s has not been implemented", op) return fmt.Errorf("encoder (indent+escaped): opcode %s has not been implemented", op)
} }
func load(base uintptr, idx uintptr) uintptr { func load(base uintptr, idx uint32) uintptr {
addr := base + idx addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr)) return **(**uintptr)(unsafe.Pointer(&addr))
} }
func store(base uintptr, idx uintptr, p uintptr) { func store(base uintptr, idx uint32, p uintptr) {
addr := base + idx addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p **(**uintptr)(unsafe.Pointer(&addr)) = p
} }
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + idx addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr)) p := **(**uintptr)(unsafe.Pointer(&addr))
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -72,8 +72,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
func ptrToPtr(p uintptr) uintptr { func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
} }
func ptrToNPtr(p uintptr, ptrNum int) uintptr { func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -137,6 +137,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
oldBaseIndent := ctx.BaseIndent oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent = code.Indent ctx.BaseIndent = code.Indent
ctx.Code = ifaceCodeSet.EscapeKeyCode
bb, err := Run(ctx, b, ifaceCodeSet, opt) bb, err := Run(ctx, b, ifaceCodeSet, opt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -204,7 +205,7 @@ func appendStructHead(b []byte) []byte {
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = appendIndent(ctx, b, code.Indent) b = appendIndent(ctx, b, code.Indent)
b = append(b, code.EscapedKey...) b = append(b, code.Key...)
return append(b, ' ') return append(b, ' ')
} }
@ -225,7 +226,7 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
} }
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
ctx.BaseIndent = int(load(ctxptr, code.Length)) ctx.BaseIndent = uint32(load(ctxptr, code.Length))
} }
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
fmt.Println(codeSet.Type) fmt.Println(codeSet.Type)
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [ALL OPCODE]") fmt.Println("* [ALL OPCODE]")
fmt.Println(codeSet.Code.Dump()) fmt.Println(ctx.Code.Dump())
fmt.Printf("\n") fmt.Printf("\n")
fmt.Println("* [CONTEXT]") fmt.Println("* [CONTEXT]")
fmt.Printf("%+v\n", ctx) fmt.Printf("%+v\n", ctx)

View File

@ -39,20 +39,20 @@ func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op) return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
} }
func load(base uintptr, idx uintptr) uintptr { func load(base uintptr, idx uint32) uintptr {
addr := base + idx addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr)) return **(**uintptr)(unsafe.Pointer(&addr))
} }
func store(base uintptr, idx uintptr, p uintptr) { func store(base uintptr, idx uint32, p uintptr) {
addr := base + idx addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p **(**uintptr)(unsafe.Pointer(&addr)) = p
} }
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + idx addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr)) p := **(**uintptr)(unsafe.Pointer(&addr))
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -72,8 +72,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
func ptrToPtr(p uintptr) uintptr { func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
} }
func ptrToNPtr(p uintptr, ptrNum int) uintptr { func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := 0; i < ptrNum; i++ { for i := uint8(0); i < ptrNum; i++ {
if p == 0 { if p == 0 {
return 0 return 0
} }
@ -137,6 +137,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
oldBaseIndent := ctx.BaseIndent oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent = code.Indent ctx.BaseIndent = code.Indent
ctx.Code = ifaceCodeSet.NoescapeKeyCode
bb, err := Run(ctx, b, ifaceCodeSet, opt) bb, err := Run(ctx, b, ifaceCodeSet, opt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -225,7 +226,7 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
} }
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
ctx.BaseIndent = int(load(ctxptr, code.Length)) ctx.BaseIndent = uint32(load(ctxptr, code.Length))
} }
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {

File diff suppressed because it is too large Load Diff

18
size_test.go Normal file
View File

@ -0,0 +1,18 @@
package json
import (
"testing"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
)
func TestOpcodeSize(t *testing.T) {
const uintptrSize = 4 << (^uintptr(0) >> 63)
if uintptrSize == 8 {
size := unsafe.Sizeof(encoder.Opcode{})
if size != 128 {
t.Fatalf("unexpected opcode size: expected 128bytes but got %dbytes", size)
}
}
}