mirror of https://github.com/goccy/go-json.git
Merge pull request #230 from goccy/feature/fix-opcode-layout
Fix opcode layout
This commit is contained in:
commit
ca4e811a0b
24
encode.go
24
encode.go
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,7 +425,7 @@ var opTypeStrings = [400]string{
|
||||||
"StructEndOmitEmpty",
|
"StructEndOmitEmpty",
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpType int
|
type OpType uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OpEnd OpType = 0
|
OpEnd OpType = 0
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue