mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 17:06:47 +08:00
fix: support dynamic interface indirection
This commit is contained in:
parent
91e58904fe
commit
4937f48f3c
10 changed files with 315 additions and 92 deletions
|
|
@ -17,6 +17,7 @@
|
|||
package decoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`math`
|
||||
`reflect`
|
||||
|
|
@ -88,8 +89,10 @@ const (
|
|||
_LB_error = "_error"
|
||||
_LB_im_error = "_im_error"
|
||||
_LB_eof_error = "_eof_error"
|
||||
_LB_type_error = "_type_error"
|
||||
_LB_field_error = "_field_error"
|
||||
_LB_range_error = "_range_error"
|
||||
_LB_stack_error = "_stack_error"
|
||||
_LB_base64_error = "_base64_error"
|
||||
_LB_unquote_error = "_unquote_error"
|
||||
_LB_parsing_error = "_parsing_error"
|
||||
|
|
@ -201,8 +204,10 @@ func (self *_Assembler) compile() {
|
|||
self.prologue()
|
||||
self.instrs()
|
||||
self.epilogue()
|
||||
self.type_error()
|
||||
self.field_error()
|
||||
self.range_error()
|
||||
self.stack_error()
|
||||
self.base64_error()
|
||||
self.parsing_error()
|
||||
}
|
||||
|
|
@ -211,6 +216,7 @@ func (self *_Assembler) compile() {
|
|||
|
||||
var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
|
||||
_OP_any : (*_Assembler)._asm_OP_any,
|
||||
_OP_dyn : (*_Assembler)._asm_OP_dyn,
|
||||
_OP_str : (*_Assembler)._asm_OP_str,
|
||||
_OP_bin : (*_Assembler)._asm_OP_bin,
|
||||
_OP_bool : (*_Assembler)._asm_OP_bool,
|
||||
|
|
@ -373,6 +379,7 @@ func (self *_Assembler) call_vf(fn obj.Addr) {
|
|||
var (
|
||||
_F_convT64 = jit.Func(convT64)
|
||||
_F_error_wrap = jit.Func(error_wrap)
|
||||
_F_error_type = jit.Func(error_type)
|
||||
_F_error_field = jit.Func(error_field)
|
||||
_F_error_value = jit.Func(error_value)
|
||||
)
|
||||
|
|
@ -392,6 +399,20 @@ var (
|
|||
_I_base64_CorruptInputError = jit.Itab(_T_error, base64CorruptInputError)
|
||||
)
|
||||
|
||||
var (
|
||||
_V_stackOverflow = jit.Imm(int64(uintptr(unsafe.Pointer(&stackOverflow))))
|
||||
_I_json_UnsupportedValueError = jit.Itab(_T_error, reflect.TypeOf(new(json.UnsupportedValueError)))
|
||||
)
|
||||
|
||||
func (self *_Assembler) type_error() {
|
||||
self.Link(_LB_type_error) // _type_error:
|
||||
self.Emit("MOVQ", _ET, jit.Ptr(_SP, 0)) // MOVQ ET, (SP)
|
||||
self.call_go(_F_error_type) // CALL_GO error_type
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 8), _ET) // MOVQ 8(SP), ET
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 16), _EP) // MOVQ 16(SP), EP
|
||||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) field_error() {
|
||||
self.Link(_LB_field_error) // _field_error:
|
||||
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
|
||||
|
|
@ -415,6 +436,13 @@ func (self *_Assembler) range_error() {
|
|||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) stack_error() {
|
||||
self.Link(_LB_stack_error) // _stack_error:
|
||||
self.Emit("MOVQ", _V_stackOverflow, _EP) // MOVQ ${_V_stackOverflow}, EP
|
||||
self.Emit("MOVQ", _I_json_UnsupportedValueError, _ET) // MOVQ ${_I_json_UnsupportedValueError}, ET
|
||||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) base64_error() {
|
||||
self.Link(_LB_base64_error)
|
||||
self.Emit("NEGQ", _AX) // NEGQ AX
|
||||
|
|
@ -697,13 +725,13 @@ func (self *_Assembler) mem_clear_fn(ptrfree bool) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) mem_clear_rem(size int64, ptrfree bool) {
|
||||
self.Emit("MOVQ" , jit.Imm(size), _CX) // MOVQ ${size}, CX
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 0), _AX) // MOVQ (ST)(AX), AX
|
||||
self.Emit("SUBQ" , _VP, _AX) // SUBQ VP, AX
|
||||
self.Emit("ADDQ" , _AX, _CX) // ADDQ AX, CX
|
||||
self.Emit("MOVQ" , _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP)
|
||||
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.Emit("MOVQ", jit.Imm(size), _CX) // MOVQ ${size}, CX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _AX) // MOVQ (ST)(AX), AX
|
||||
self.Emit("SUBQ", _VP, _AX) // SUBQ VP, AX
|
||||
self.Emit("ADDQ", _AX, _CX) // ADDQ AX, CX
|
||||
self.Emit("MOVQ", _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP)
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.mem_clear_fn(ptrfree) // CALL_GO memclr{Has,NoHeap}Pointers
|
||||
}
|
||||
|
||||
|
|
@ -859,6 +887,33 @@ func (self *_Assembler) unmarshal_func(t reflect.Type, fn obj.Addr, deref bool)
|
|||
self.Sjmp("JNZ" , _LB_error) // JNZ _error
|
||||
}
|
||||
|
||||
/** Dynamic Decoding Routine **/
|
||||
|
||||
var (
|
||||
_F_decodeTypedPointer obj.Addr
|
||||
)
|
||||
|
||||
func init() {
|
||||
_F_decodeTypedPointer = jit.Func(decodeTypedPointer)
|
||||
}
|
||||
|
||||
func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) {
|
||||
self.Emit("MOVQ" , _ARG_fv, _CX) // MOVQ fv, CX
|
||||
self.Emit("MOVOU", _ARG_sp, _X0) // MOVOU sp, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
|
||||
self.Emit("MOVQ" , _IC, jit.Ptr(_SP, 16)) // MOVQ IC, 16(SP)
|
||||
self.Emit("MOVQ" , vt, jit.Ptr(_SP, 24)) // MOVQ ${vt}, 24(SP)
|
||||
self.Emit("MOVQ" , vp, jit.Ptr(_SP, 32)) // MOVQ ${vp}, 32(SP)
|
||||
self.Emit("MOVQ" , _ST, jit.Ptr(_SP, 40)) // MOVQ ST, 40(SP)
|
||||
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 48)) // MOVQ CX, 48(SP)
|
||||
self.call_go(_F_decodeTypedPointer) // CALL_GO decodeTypedPointer
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 64), _ET) // MOVQ 64(SP), ET
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 72), _EP) // MOVQ 72(SP), EP
|
||||
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
|
||||
self.Sjmp("JNZ" , _LB_error) // JNZ _error
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 56), _IC) // MOVQ 56(SP), IC
|
||||
}
|
||||
|
||||
/** OpCode Assembler Functions **/
|
||||
|
||||
var (
|
||||
|
|
@ -885,7 +940,6 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
_F_decodeTypedPointer obj.Addr
|
||||
_F_FieldMap_GetCaseInsensitive obj.Addr
|
||||
)
|
||||
|
||||
|
|
@ -895,16 +949,50 @@ const (
|
|||
_Fe_Hash = int64(unsafe.Offsetof(caching.FieldEntry{}.Hash))
|
||||
)
|
||||
|
||||
const (
|
||||
_Vk_Ptr = int64(reflect.Ptr)
|
||||
_Gt_KindFlags = int64(unsafe.Offsetof(rt.GoType{}.KindFlags))
|
||||
)
|
||||
|
||||
func init() {
|
||||
_F_decodeTypedPointer = jit.Func(decodeTypedPointer)
|
||||
_F_FieldMap_GetCaseInsensitive = jit.Func((*caching.FieldMap).GetCaseInsensitive)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_any(_ *_Instr) {
|
||||
self.Emit("MOVQ" , _ARG_fv, _DF) // MOVQ fv, DF
|
||||
self.call(_F_decodeValue) // CALL decodeValue
|
||||
self.Emit("TESTQ", _EP, _EP) // TESTQ EP, EP
|
||||
self.Sjmp("JNZ" , _LB_parsing_error) // JNZ _parsing_error
|
||||
self.Emit("MOVQ" , jit.Ptr(_VP, 8), _CX) // MOVQ 8(VP), CX
|
||||
self.Emit("TESTQ" , _CX, _CX) // TESTQ CX, CX
|
||||
self.Sjmp("JZ" , "_decode_{n}") // JZ _decode_{n}
|
||||
self.Emit("CMPQ" , _CX, _VP) // CMPQ CX, VP
|
||||
self.Sjmp("JE" , "_decode_{n}") // JE _decode_{n}
|
||||
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
|
||||
self.Emit("MOVBLZX", jit.Ptr(_AX, _Gt_KindFlags), _DX) // MOVBLZX _Gt_KindFlags(AX), DX
|
||||
self.Emit("ANDL" , jit.Imm(rt.F_kind_mask), _DX) // ANDL ${F_kind_mask}, DX
|
||||
self.Emit("CMPL" , _DX, jit.Imm(_Vk_Ptr)) // CMPL DX, ${reflect.Ptr}
|
||||
self.Sjmp("JNE" , "_decode_{n}") // JNE _decode_{n}
|
||||
self.Emit("LEAQ" , jit.Ptr(_VP, 8), _DI) // LEAQ 8(VP), DI
|
||||
self.decode_dynamic(_AX, _DI) // DECODE AX, DI
|
||||
self.Sjmp("JMP" , "_decode_end_{n}") // JMP _decode_end_{n}
|
||||
self.Link("_decode_{n}") // _decode_{n}:
|
||||
self.Emit("MOVQ" , _ARG_fv, _DF) // MOVQ fv, DF
|
||||
self.call(_F_decodeValue) // CALL decodeValue
|
||||
self.Emit("TESTQ" , _EP, _EP) // TESTQ EP, EP
|
||||
self.Sjmp("JNZ" , _LB_parsing_error) // JNZ _parsing_error
|
||||
self.Link("_decode_end_{n}") // _decode_end_{n}:
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_dyn(p *_Instr) {
|
||||
self.Emit("MOVQ" , jit.Type(p.vt()), _ET) // MOVQ ${p.vt()}, ET
|
||||
self.Emit("CMPQ" , jit.Ptr(_VP, 8), jit.Imm(0)) // CMPQ 8(VP), $0
|
||||
self.Sjmp("JE" , _LB_type_error) // JE _type_error
|
||||
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
|
||||
self.Emit("MOVQ" , jit.Ptr(_AX, 8), _AX) // MOVQ 8(AX), AX
|
||||
self.Emit("MOVBLZX", jit.Ptr(_AX, _Gt_KindFlags), _DX) // MOVBLZX _Gt_KindFlags(AX), DX
|
||||
self.Emit("ANDL" , jit.Imm(rt.F_kind_mask), _DX) // ANDL ${F_kind_mask}, DX
|
||||
self.Emit("CMPL" , _DX, jit.Imm(_Vk_Ptr)) // CMPL DX, ${reflect.Ptr}
|
||||
self.Sjmp("JNE" , _LB_type_error) // JNE _type_error
|
||||
self.Emit("LEAQ" , jit.Ptr(_VP, 8), _DI) // LEAQ 8(VP), DI
|
||||
self.decode_dynamic(_AX, _DI) // DECODE AX, DI
|
||||
self.Link("_decode_end_{n}") // _decode_end_{n}:
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_str(_ *_Instr) {
|
||||
|
|
@ -1374,6 +1462,8 @@ func (self *_Assembler) _asm_OP_load(_ *_Instr) {
|
|||
|
||||
func (self *_Assembler) _asm_OP_save(_ *_Instr) {
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_MaxStack)) // CMPQ AX, ${_MaxStack}
|
||||
self.Sjmp("JA" , _LB_stack_error) // JA _stack_error
|
||||
self.Emit("MOVQ", _VP, jit.Sib(_ST, _AX, 1, 8)) // MOVQ VP, 8(ST)(AX)
|
||||
self.Emit("ADDQ", jit.Imm(8), _AX) // ADDQ $8, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
|
||||
|
|
@ -1398,21 +1488,8 @@ func (self *_Assembler) _asm_OP_drop_2(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_recurse(p *_Instr) {
|
||||
self.Emit("MOVQ" , jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX
|
||||
self.Emit("MOVQ" , _ARG_fv, _CX) // MOVQ fv, cx
|
||||
self.Emit("MOVOU", _ARG_sp, _X0) // MOVOU sp, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
|
||||
self.Emit("MOVQ" , _IC, jit.Ptr(_SP, 16)) // MOVQ IC, 16(SP)
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 24)) // MOVQ AX, 24(SP)
|
||||
self.Emit("MOVQ" , _VP, jit.Ptr(_SP, 32)) // MOVQ VP, 32(SP)
|
||||
self.Emit("MOVQ" , _ST, jit.Ptr(_SP, 40)) // MOVQ ST, 40(SP)
|
||||
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 48)) // MOVQ CX, 48(SP)
|
||||
self.call_go(_F_decodeTypedPointer) // CALL_GO decodeTypedPointer
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 64), _ET) // MOVQ 64(SP), ET
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 72), _EP) // MOVQ 72(SP), EP
|
||||
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
|
||||
self.Sjmp("JNZ" , _LB_error) // JNZ _error
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 56), _IC) // MOVQ 56(SP), IC
|
||||
self.Emit("MOVQ", jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX
|
||||
self.decode_dynamic(_AX, _VP) // DECODE AX, VP
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_goto(p *_Instr) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package decoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`sort`
|
||||
|
|
@ -33,6 +34,7 @@ type _Op uint8
|
|||
|
||||
const (
|
||||
_OP_any _Op = iota + 1
|
||||
_OP_dyn
|
||||
_OP_str
|
||||
_OP_bin
|
||||
_OP_bool
|
||||
|
|
@ -104,6 +106,7 @@ const (
|
|||
|
||||
var _OpNames = [256]string {
|
||||
_OP_any : "any",
|
||||
_OP_dyn : "dyn",
|
||||
_OP_str : "str",
|
||||
_OP_bin : "bin",
|
||||
_OP_bool : "bool",
|
||||
|
|
@ -295,7 +298,7 @@ func (self _Instr) i64() int64 {
|
|||
}
|
||||
|
||||
func (self _Instr) vlen() int {
|
||||
return (*rt.GoType)(self.p).Size()
|
||||
return int((*rt.GoType)(self.p).Size)
|
||||
}
|
||||
|
||||
func (self _Instr) isBranch() bool {
|
||||
|
|
@ -310,6 +313,7 @@ func (self _Instr) isBranch() bool {
|
|||
|
||||
func (self _Instr) disassemble() string {
|
||||
switch self.op() {
|
||||
case _OP_dyn : fallthrough
|
||||
case _OP_deref : fallthrough
|
||||
case _OP_map_key_i8 : fallthrough
|
||||
case _OP_map_key_i16 : fallthrough
|
||||
|
|
@ -573,7 +577,7 @@ func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
|
|||
case reflect.Ptr : self.compilePtr (p, sp, vt)
|
||||
case reflect.Slice : self.compileSlice (p, sp, vt.Elem())
|
||||
case reflect.Struct : self.compileStruct (p, sp, vt)
|
||||
default : panic (error_type(vt))
|
||||
default : panic (&json.UnmarshalTypeError{Type: vt})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +607,7 @@ func (self *_Compiler) compileMapUt(p *_Program, sp int, vt reflect.Type) {
|
|||
case reflect.Float32 : self.compileMapOp(p, sp, vt, _OP_map_key_f32)
|
||||
case reflect.Float64 : self.compileMapOp(p, sp, vt, _OP_map_key_f64)
|
||||
case reflect.String : self.compileMapOp(p, sp, vt, _OP_map_key_str)
|
||||
default : panic(error_type(vt))
|
||||
default : panic(&json.UnmarshalTypeError{Type: vt})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +712,7 @@ func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type) {
|
|||
p.rel(v)
|
||||
|
||||
/* check for pointer data */
|
||||
if rt.UnpackType(vt.Elem()).NoPtr() {
|
||||
if rt.UnpackType(vt.Elem()).PtrData == 0 {
|
||||
p.int(_OP_array_clear, int(vt.Size()))
|
||||
} else {
|
||||
p.int(_OP_array_clear_p, int(vt.Size()))
|
||||
|
|
@ -991,16 +995,16 @@ func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Typ
|
|||
|
||||
func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
|
||||
i := p.pc()
|
||||
n := vt.NumMethod()
|
||||
p.add(_OP_is_null)
|
||||
|
||||
/* only empty interface is acceptable */
|
||||
if n != 0 {
|
||||
panic(error_type(vt))
|
||||
/* check for empty interface */
|
||||
if vt.NumMethod() == 0 {
|
||||
p.add(_OP_any)
|
||||
} else {
|
||||
p.rtt(_OP_dyn, vt)
|
||||
}
|
||||
|
||||
/* check for nil, and compile the interface */
|
||||
p.add(_OP_is_null)
|
||||
p.add(_OP_any)
|
||||
/* finish the OpCode */
|
||||
j := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(i)
|
||||
|
|
@ -1034,30 +1038,33 @@ func (self *_Compiler) compileUnmarshalEnd(p *_Program, vt reflect.Type, i int)
|
|||
|
||||
func (self *_Compiler) compileUnmarshalJson(p *_Program, vt reflect.Type) {
|
||||
i := p.pc()
|
||||
v := _OP_unmarshal
|
||||
p.add(_OP_is_null)
|
||||
|
||||
/* must not be an interface */
|
||||
/* check for dynamic interface */
|
||||
if vt.Kind() == reflect.Interface {
|
||||
panic(error_type(vt))
|
||||
v = _OP_dyn
|
||||
}
|
||||
|
||||
/* call the unmarshaler */
|
||||
p.rtt(_OP_unmarshal, vt)
|
||||
p.rtt(v, vt)
|
||||
self.compileUnmarshalEnd(p, vt, i)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileUnmarshalText(p *_Program, vt reflect.Type) {
|
||||
i := p.pc()
|
||||
v := _OP_unmarshal_text
|
||||
p.add(_OP_is_null)
|
||||
p.chr(_OP_match_char, '"')
|
||||
|
||||
/* must not be an interface */
|
||||
/* check for dynamic interface */
|
||||
if vt.Kind() == reflect.Interface {
|
||||
panic(error_type(vt))
|
||||
v = _OP_dyn
|
||||
} else {
|
||||
p.chr(_OP_match_char, '"')
|
||||
}
|
||||
|
||||
/* call the unmarshaler */
|
||||
p.rtt(_OP_unmarshal_text, vt)
|
||||
p.rtt(v, vt)
|
||||
self.compileUnmarshalEnd(p, vt, i)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
`strings`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
type SyntaxError struct {
|
||||
|
|
@ -86,6 +87,14 @@ func clamp_zero(v int) int {
|
|||
}
|
||||
}
|
||||
|
||||
/** JIT Error Helpers **/
|
||||
|
||||
var stackOverflow = &json.UnsupportedValueError {
|
||||
Str : "Value nesting too deep",
|
||||
Value : reflect.ValueOf("..."),
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_wrap(src string, pos int, code types.ParsingError) error {
|
||||
return SyntaxError {
|
||||
Pos : pos,
|
||||
|
|
@ -94,10 +103,12 @@ func error_wrap(src string, pos int, code types.ParsingError) error {
|
|||
}
|
||||
}
|
||||
|
||||
func error_type(vtype reflect.Type) error {
|
||||
return &json.UnmarshalTypeError{Type: vtype}
|
||||
//go:nosplit
|
||||
func error_type(vt *rt.GoType) error {
|
||||
return &json.UnmarshalTypeError{Type: vt.Pack()}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_field(name string) error {
|
||||
return errors.New("json: unknown field " + strconv.Quote(name))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ func (self _Instr) i64() int64 {
|
|||
}
|
||||
|
||||
func (self _Instr) vlen() int {
|
||||
return (*rt.GoType)(self.p).Size()
|
||||
return int((*rt.GoType)(self.p).Size)
|
||||
}
|
||||
|
||||
func (self _Instr) isBranch() bool {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func encodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *_Sta
|
|||
return encodeNil(buf)
|
||||
} else if fn, err := findOrCompile(vt); err != nil {
|
||||
return err
|
||||
} else if vt.Indir() {
|
||||
} else if (vt.KindFlags & rt.F_direct) == 0 {
|
||||
return fn(buf, *vp, sb)
|
||||
} else {
|
||||
return fn(buf, unsafe.Pointer(vp), sb)
|
||||
|
|
@ -95,7 +95,7 @@ func encodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler) error {
|
|||
}
|
||||
|
||||
func isZeroSafe(p unsafe.Pointer, vt *rt.GoType) bool {
|
||||
if native.Lzero(p, vt.Size()) == 0 {
|
||||
if native.Lzero(p, int(vt.Size)) == 0 {
|
||||
return true
|
||||
} else {
|
||||
return isZeroTyped(p, vt)
|
||||
|
|
|
|||
|
|
@ -29,34 +29,34 @@ var _subr__b64encode uintptr
|
|||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname newobject runtime.newobject
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func newobject(typ *rt.GoType) unsafe.Pointer
|
||||
|
||||
//go:linkname growslice runtime.growslice
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname assertI2I runtime.assertI2I
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface
|
||||
|
||||
//go:linkname mapiternext runtime.mapiternext
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiternext(it unsafe.Pointer)
|
||||
|
||||
//go:linkname mapiterinit runtime.mapiterinit
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiterinit(t *rt.GoType, m unsafe.Pointer, it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname isValidNumber encoding/json.isValidNumber
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func isValidNumber(s string) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection ALL
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func newProgramMap() *_ProgramMap {
|
|||
|
||||
func (self *_ProgramMap) get(vt *rt.GoType) interface{} {
|
||||
i := self.m + 1
|
||||
p := vt.Hash() & self.m
|
||||
p := vt.Hash & self.m
|
||||
|
||||
/* linear probing */
|
||||
for ; i > 0; i-- {
|
||||
|
|
@ -99,7 +99,7 @@ func (self *_ProgramMap) rehash() *_ProgramMap {
|
|||
}
|
||||
|
||||
func (self *_ProgramMap) insert(vt *rt.GoType, fn interface{}) {
|
||||
h := vt.Hash()
|
||||
h := vt.Hash
|
||||
p := h & self.m
|
||||
|
||||
/* linear probing */
|
||||
|
|
|
|||
|
|
@ -21,37 +21,31 @@ import (
|
|||
`unsafe`
|
||||
)
|
||||
|
||||
var reflectRtypeItab = findReflectRtypeItab()
|
||||
var (
|
||||
reflectRtypeItab = findReflectRtypeItab()
|
||||
)
|
||||
|
||||
const (
|
||||
_KindMask = (1 << 5) - 1
|
||||
_DirectIface = 1 << 5
|
||||
F_direct = 1 << 5
|
||||
F_kind_mask = (1 << 5) - 1
|
||||
)
|
||||
|
||||
type GoType struct {
|
||||
nb uintptr
|
||||
ptrd uintptr
|
||||
hash uint32
|
||||
tflags uint8
|
||||
align uint8
|
||||
falign uint8
|
||||
kflags uint8
|
||||
traits unsafe.Pointer
|
||||
gcdata *byte
|
||||
str int32
|
||||
p int32
|
||||
}
|
||||
|
||||
func (self *GoType) Size() int {
|
||||
return int(self.nb)
|
||||
}
|
||||
|
||||
func (self *GoType) Hash() uint32 {
|
||||
return self.hash
|
||||
Size uintptr
|
||||
PtrData uintptr
|
||||
Hash uint32
|
||||
Flags uint8
|
||||
Align uint8
|
||||
FieldAlign uint8
|
||||
KindFlags uint8
|
||||
Traits unsafe.Pointer
|
||||
GCData *byte
|
||||
Str int32
|
||||
PtrToSelf int32
|
||||
}
|
||||
|
||||
func (self *GoType) Kind() reflect.Kind {
|
||||
return reflect.Kind(self.kflags & _KindMask)
|
||||
return reflect.Kind(self.KindFlags & F_kind_mask)
|
||||
}
|
||||
|
||||
func (self *GoType) Pack() (t reflect.Type) {
|
||||
|
|
@ -60,14 +54,6 @@ func (self *GoType) Pack() (t reflect.Type) {
|
|||
return
|
||||
}
|
||||
|
||||
func (self *GoType) NoPtr() bool {
|
||||
return self.ptrd == 0
|
||||
}
|
||||
|
||||
func (self *GoType) Indir() bool {
|
||||
return (self.kflags & _DirectIface) == 0
|
||||
}
|
||||
|
||||
func (self *GoType) String() string {
|
||||
return self.Pack().String()
|
||||
}
|
||||
|
|
|
|||
111
issue39_test.go
Normal file
111
issue39_test.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sonic
|
||||
|
||||
import (
|
||||
`testing`
|
||||
|
||||
`github.com/bytedance/sonic/decoder`
|
||||
`github.com/stretchr/testify/require`
|
||||
)
|
||||
|
||||
type normalIfaceIssue39 interface {
|
||||
Foo()
|
||||
}
|
||||
|
||||
type normalWrapIssue39 struct {
|
||||
F normalIfaceIssue39
|
||||
}
|
||||
|
||||
type normalImplIssue39 struct {
|
||||
X int
|
||||
}
|
||||
|
||||
func (_ *normalImplIssue39) Foo() {}
|
||||
|
||||
type jsonIfaceIssue39 interface {
|
||||
UnmarshalJSON(b []byte) error
|
||||
}
|
||||
|
||||
type jsonWrapIssue39 struct {
|
||||
F jsonIfaceIssue39
|
||||
}
|
||||
|
||||
type jsonImplIssue39 struct {
|
||||
a string
|
||||
}
|
||||
|
||||
func (self *jsonImplIssue39) UnmarshalJSON(b []byte) error{
|
||||
self.a = string(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
type textIfaceIssue39 interface {
|
||||
UnmarshalText(b []byte) error
|
||||
}
|
||||
|
||||
type textWrapIssue39 struct {
|
||||
F textIfaceIssue39
|
||||
}
|
||||
|
||||
type textImplIssue39 struct {
|
||||
a string
|
||||
}
|
||||
|
||||
func (self *textImplIssue39) UnmarshalText(b []byte) error{
|
||||
self.a = string(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestIssue39_Iface(t *testing.T) {
|
||||
p := new(normalImplIssue39)
|
||||
obj := normalWrapIssue39{F: p}
|
||||
err := Unmarshal([]byte(`{"F":{"X":123}}`), &obj)
|
||||
if err != nil {
|
||||
if v, ok := err.(decoder.SyntaxError); ok {
|
||||
println(v.Description())
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, 123, p.X)
|
||||
}
|
||||
|
||||
func TestIssue39_UnmarshalJSON(t *testing.T) {
|
||||
p := &jsonImplIssue39{}
|
||||
obj := jsonWrapIssue39{F: p}
|
||||
err := Unmarshal([]byte(`{"F":"xx"}`), &obj)
|
||||
if err != nil {
|
||||
if v, ok := err.(decoder.SyntaxError); ok {
|
||||
println(v.Description())
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, `"xx"`, p.a)
|
||||
}
|
||||
|
||||
func TestIssue39_UnmarshalText(t *testing.T) {
|
||||
p := &textImplIssue39{}
|
||||
obj := textWrapIssue39{F: p}
|
||||
err := Unmarshal([]byte(`{"F":"xx"}`), &obj)
|
||||
if err != nil {
|
||||
if v, ok := err.(decoder.SyntaxError); ok {
|
||||
println(v.Description())
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, `xx`, p.a)
|
||||
}
|
||||
31
issue5_test.go
Normal file
31
issue5_test.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sonic
|
||||
|
||||
import (
|
||||
`testing`
|
||||
|
||||
`github.com/stretchr/testify/require`
|
||||
)
|
||||
|
||||
func TestIssue5(t *testing.T) {
|
||||
var x int
|
||||
var i interface{} = &x
|
||||
err := Unmarshal([]byte(`1`), &i)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, x)
|
||||
}
|
||||
Loading…
Reference in a new issue