2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-25 02:46:43 +08:00

fix: support dynamic interface indirection

This commit is contained in:
chenzhuoyu 2021-07-06 20:46:31 +08:00 committed by Oxygen
parent 91e58904fe
commit 4937f48f3c
10 changed files with 315 additions and 92 deletions

View file

@ -17,6 +17,7 @@
package decoder package decoder
import ( import (
`encoding/json`
`fmt` `fmt`
`math` `math`
`reflect` `reflect`
@ -88,8 +89,10 @@ const (
_LB_error = "_error" _LB_error = "_error"
_LB_im_error = "_im_error" _LB_im_error = "_im_error"
_LB_eof_error = "_eof_error" _LB_eof_error = "_eof_error"
_LB_type_error = "_type_error"
_LB_field_error = "_field_error" _LB_field_error = "_field_error"
_LB_range_error = "_range_error" _LB_range_error = "_range_error"
_LB_stack_error = "_stack_error"
_LB_base64_error = "_base64_error" _LB_base64_error = "_base64_error"
_LB_unquote_error = "_unquote_error" _LB_unquote_error = "_unquote_error"
_LB_parsing_error = "_parsing_error" _LB_parsing_error = "_parsing_error"
@ -201,8 +204,10 @@ func (self *_Assembler) compile() {
self.prologue() self.prologue()
self.instrs() self.instrs()
self.epilogue() self.epilogue()
self.type_error()
self.field_error() self.field_error()
self.range_error() self.range_error()
self.stack_error()
self.base64_error() self.base64_error()
self.parsing_error() self.parsing_error()
} }
@ -211,6 +216,7 @@ func (self *_Assembler) compile() {
var _OpFuncTab = [256]func(*_Assembler, *_Instr) { var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
_OP_any : (*_Assembler)._asm_OP_any, _OP_any : (*_Assembler)._asm_OP_any,
_OP_dyn : (*_Assembler)._asm_OP_dyn,
_OP_str : (*_Assembler)._asm_OP_str, _OP_str : (*_Assembler)._asm_OP_str,
_OP_bin : (*_Assembler)._asm_OP_bin, _OP_bin : (*_Assembler)._asm_OP_bin,
_OP_bool : (*_Assembler)._asm_OP_bool, _OP_bool : (*_Assembler)._asm_OP_bool,
@ -373,6 +379,7 @@ func (self *_Assembler) call_vf(fn obj.Addr) {
var ( var (
_F_convT64 = jit.Func(convT64) _F_convT64 = jit.Func(convT64)
_F_error_wrap = jit.Func(error_wrap) _F_error_wrap = jit.Func(error_wrap)
_F_error_type = jit.Func(error_type)
_F_error_field = jit.Func(error_field) _F_error_field = jit.Func(error_field)
_F_error_value = jit.Func(error_value) _F_error_value = jit.Func(error_value)
) )
@ -392,6 +399,20 @@ var (
_I_base64_CorruptInputError = jit.Itab(_T_error, base64CorruptInputError) _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() { func (self *_Assembler) field_error() {
self.Link(_LB_field_error) // _field_error: self.Link(_LB_field_error) // _field_error:
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0 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 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() { func (self *_Assembler) base64_error() {
self.Link(_LB_base64_error) self.Link(_LB_base64_error)
self.Emit("NEGQ", _AX) // NEGQ AX 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) { func (self *_Assembler) mem_clear_rem(size int64, ptrfree bool) {
self.Emit("MOVQ" , jit.Imm(size), _CX) // MOVQ ${size}, CX 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.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 0), _AX) // MOVQ (ST)(AX), 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("SUBQ", _VP, _AX) // SUBQ VP, AX
self.Emit("ADDQ" , _AX, _CX) // ADDQ AX, CX self.Emit("ADDQ", _AX, _CX) // ADDQ AX, CX
self.Emit("MOVQ" , _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP) 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", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.mem_clear_fn(ptrfree) // CALL_GO memclr{Has,NoHeap}Pointers 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 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 **/ /** OpCode Assembler Functions **/
var ( var (
@ -885,7 +940,6 @@ var (
) )
var ( var (
_F_decodeTypedPointer obj.Addr
_F_FieldMap_GetCaseInsensitive obj.Addr _F_FieldMap_GetCaseInsensitive obj.Addr
) )
@ -895,16 +949,50 @@ const (
_Fe_Hash = int64(unsafe.Offsetof(caching.FieldEntry{}.Hash)) _Fe_Hash = int64(unsafe.Offsetof(caching.FieldEntry{}.Hash))
) )
const (
_Vk_Ptr = int64(reflect.Ptr)
_Gt_KindFlags = int64(unsafe.Offsetof(rt.GoType{}.KindFlags))
)
func init() { func init() {
_F_decodeTypedPointer = jit.Func(decodeTypedPointer)
_F_FieldMap_GetCaseInsensitive = jit.Func((*caching.FieldMap).GetCaseInsensitive) _F_FieldMap_GetCaseInsensitive = jit.Func((*caching.FieldMap).GetCaseInsensitive)
} }
func (self *_Assembler) _asm_OP_any(_ *_Instr) { func (self *_Assembler) _asm_OP_any(_ *_Instr) {
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.Emit("MOVQ" , _ARG_fv, _DF) // MOVQ fv, DF
self.call(_F_decodeValue) // CALL decodeValue self.call(_F_decodeValue) // CALL decodeValue
self.Emit("TESTQ", _EP, _EP) // TESTQ EP, EP self.Emit("TESTQ" , _EP, _EP) // TESTQ EP, EP
self.Sjmp("JNZ" , _LB_parsing_error) // JNZ _parsing_error 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) { 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) { func (self *_Assembler) _asm_OP_save(_ *_Instr) {
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX 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("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("ADDQ", jit.Imm(8), _AX) // ADDQ $8, AX
self.Emit("MOVQ", _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST) 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) { func (self *_Assembler) _asm_OP_recurse(p *_Instr) {
self.Emit("MOVQ" , jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX self.Emit("MOVQ", jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX
self.Emit("MOVQ" , _ARG_fv, _CX) // MOVQ fv, cx self.decode_dynamic(_AX, _VP) // DECODE AX, VP
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
} }
func (self *_Assembler) _asm_OP_goto(p *_Instr) { func (self *_Assembler) _asm_OP_goto(p *_Instr) {

View file

@ -17,6 +17,7 @@
package decoder package decoder
import ( import (
`encoding/json`
`fmt` `fmt`
`reflect` `reflect`
`sort` `sort`
@ -33,6 +34,7 @@ type _Op uint8
const ( const (
_OP_any _Op = iota + 1 _OP_any _Op = iota + 1
_OP_dyn
_OP_str _OP_str
_OP_bin _OP_bin
_OP_bool _OP_bool
@ -104,6 +106,7 @@ const (
var _OpNames = [256]string { var _OpNames = [256]string {
_OP_any : "any", _OP_any : "any",
_OP_dyn : "dyn",
_OP_str : "str", _OP_str : "str",
_OP_bin : "bin", _OP_bin : "bin",
_OP_bool : "bool", _OP_bool : "bool",
@ -295,7 +298,7 @@ func (self _Instr) i64() int64 {
} }
func (self _Instr) vlen() int { func (self _Instr) vlen() int {
return (*rt.GoType)(self.p).Size() return int((*rt.GoType)(self.p).Size)
} }
func (self _Instr) isBranch() bool { func (self _Instr) isBranch() bool {
@ -310,6 +313,7 @@ func (self _Instr) isBranch() bool {
func (self _Instr) disassemble() string { func (self _Instr) disassemble() string {
switch self.op() { switch self.op() {
case _OP_dyn : fallthrough
case _OP_deref : fallthrough case _OP_deref : fallthrough
case _OP_map_key_i8 : fallthrough case _OP_map_key_i8 : fallthrough
case _OP_map_key_i16 : 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.Ptr : self.compilePtr (p, sp, vt)
case reflect.Slice : self.compileSlice (p, sp, vt.Elem()) case reflect.Slice : self.compileSlice (p, sp, vt.Elem())
case reflect.Struct : self.compileStruct (p, sp, vt) 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.Float32 : self.compileMapOp(p, sp, vt, _OP_map_key_f32)
case reflect.Float64 : self.compileMapOp(p, sp, vt, _OP_map_key_f64) case reflect.Float64 : self.compileMapOp(p, sp, vt, _OP_map_key_f64)
case reflect.String : self.compileMapOp(p, sp, vt, _OP_map_key_str) 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) p.rel(v)
/* check for pointer data */ /* 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())) p.int(_OP_array_clear, int(vt.Size()))
} else { } else {
p.int(_OP_array_clear_p, int(vt.Size())) 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) { func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
i := p.pc() i := p.pc()
n := vt.NumMethod() p.add(_OP_is_null)
/* only empty interface is acceptable */ /* check for empty interface */
if n != 0 { if vt.NumMethod() == 0 {
panic(error_type(vt)) p.add(_OP_any)
} else {
p.rtt(_OP_dyn, vt)
} }
/* check for nil, and compile the interface */ /* finish the OpCode */
p.add(_OP_is_null)
p.add(_OP_any)
j := p.pc() j := p.pc()
p.add(_OP_goto) p.add(_OP_goto)
p.pin(i) 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) { func (self *_Compiler) compileUnmarshalJson(p *_Program, vt reflect.Type) {
i := p.pc() i := p.pc()
v := _OP_unmarshal
p.add(_OP_is_null) p.add(_OP_is_null)
/* must not be an interface */ /* check for dynamic interface */
if vt.Kind() == reflect.Interface { if vt.Kind() == reflect.Interface {
panic(error_type(vt)) v = _OP_dyn
} }
/* call the unmarshaler */ /* call the unmarshaler */
p.rtt(_OP_unmarshal, vt) p.rtt(v, vt)
self.compileUnmarshalEnd(p, vt, i) self.compileUnmarshalEnd(p, vt, i)
} }
func (self *_Compiler) compileUnmarshalText(p *_Program, vt reflect.Type) { func (self *_Compiler) compileUnmarshalText(p *_Program, vt reflect.Type) {
i := p.pc() i := p.pc()
v := _OP_unmarshal_text
p.add(_OP_is_null) p.add(_OP_is_null)
p.chr(_OP_match_char, '"')
/* must not be an interface */ /* check for dynamic interface */
if vt.Kind() == reflect.Interface { if vt.Kind() == reflect.Interface {
panic(error_type(vt)) v = _OP_dyn
} else {
p.chr(_OP_match_char, '"')
} }
/* call the unmarshaler */ /* call the unmarshaler */
p.rtt(_OP_unmarshal_text, vt) p.rtt(v, vt)
self.compileUnmarshalEnd(p, vt, i) self.compileUnmarshalEnd(p, vt, i)
} }

View file

@ -25,6 +25,7 @@ import (
`strings` `strings`
`github.com/bytedance/sonic/internal/native/types` `github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
) )
type SyntaxError struct { 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 { func error_wrap(src string, pos int, code types.ParsingError) error {
return SyntaxError { return SyntaxError {
Pos : pos, Pos : pos,
@ -94,10 +103,12 @@ func error_wrap(src string, pos int, code types.ParsingError) error {
} }
} }
func error_type(vtype reflect.Type) error { //go:nosplit
return &json.UnmarshalTypeError{Type: vtype} func error_type(vt *rt.GoType) error {
return &json.UnmarshalTypeError{Type: vt.Pack()}
} }
//go:nosplit
func error_field(name string) error { func error_field(name string) error {
return errors.New("json: unknown field " + strconv.Quote(name)) return errors.New("json: unknown field " + strconv.Quote(name))
} }

View file

@ -239,7 +239,7 @@ func (self _Instr) i64() int64 {
} }
func (self _Instr) vlen() int { func (self _Instr) vlen() int {
return (*rt.GoType)(self.p).Size() return int((*rt.GoType)(self.p).Size)
} }
func (self _Instr) isBranch() bool { func (self _Instr) isBranch() bool {

View file

@ -71,7 +71,7 @@ func encodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *_Sta
return encodeNil(buf) return encodeNil(buf)
} else if fn, err := findOrCompile(vt); err != nil { } else if fn, err := findOrCompile(vt); err != nil {
return err return err
} else if vt.Indir() { } else if (vt.KindFlags & rt.F_direct) == 0 {
return fn(buf, *vp, sb) return fn(buf, *vp, sb)
} else { } else {
return fn(buf, unsafe.Pointer(vp), sb) 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 { 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 return true
} else { } else {
return isZeroTyped(p, vt) return isZeroTyped(p, vt)

View file

@ -29,34 +29,34 @@ var _subr__b64encode uintptr
//go:noescape //go:noescape
//go:linkname memmove runtime.memmove //go:linkname memmove runtime.memmove
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
//go:linkname newobject runtime.newobject //go:linkname newobject runtime.newobject
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func newobject(typ *rt.GoType) unsafe.Pointer func newobject(typ *rt.GoType) unsafe.Pointer
//go:linkname growslice runtime.growslice //go:linkname growslice runtime.growslice
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
//go:linkname assertI2I runtime.assertI2I //go:linkname assertI2I runtime.assertI2I
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface
//go:linkname mapiternext runtime.mapiternext //go:linkname mapiternext runtime.mapiternext
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func mapiternext(it unsafe.Pointer) func mapiternext(it unsafe.Pointer)
//go:linkname mapiterinit runtime.mapiterinit //go:linkname mapiterinit runtime.mapiterinit
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func mapiterinit(t *rt.GoType, m unsafe.Pointer, it *rt.GoMapIterator) func mapiterinit(t *rt.GoType, m unsafe.Pointer, it *rt.GoMapIterator)
//go:linkname isValidNumber encoding/json.isValidNumber //go:linkname isValidNumber encoding/json.isValidNumber
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func isValidNumber(s string) bool func isValidNumber(s string) bool
//go:noescape //go:noescape
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers //go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
//goland:noinspection ALL //goland:noinspection GoUnusedParameter
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)

View file

@ -52,7 +52,7 @@ func newProgramMap() *_ProgramMap {
func (self *_ProgramMap) get(vt *rt.GoType) interface{} { func (self *_ProgramMap) get(vt *rt.GoType) interface{} {
i := self.m + 1 i := self.m + 1
p := vt.Hash() & self.m p := vt.Hash & self.m
/* linear probing */ /* linear probing */
for ; i > 0; i-- { for ; i > 0; i-- {
@ -99,7 +99,7 @@ func (self *_ProgramMap) rehash() *_ProgramMap {
} }
func (self *_ProgramMap) insert(vt *rt.GoType, fn interface{}) { func (self *_ProgramMap) insert(vt *rt.GoType, fn interface{}) {
h := vt.Hash() h := vt.Hash
p := h & self.m p := h & self.m
/* linear probing */ /* linear probing */

View file

@ -21,37 +21,31 @@ import (
`unsafe` `unsafe`
) )
var reflectRtypeItab = findReflectRtypeItab() var (
reflectRtypeItab = findReflectRtypeItab()
)
const ( const (
_KindMask = (1 << 5) - 1 F_direct = 1 << 5
_DirectIface = 1 << 5 F_kind_mask = (1 << 5) - 1
) )
type GoType struct { type GoType struct {
nb uintptr Size uintptr
ptrd uintptr PtrData uintptr
hash uint32 Hash uint32
tflags uint8 Flags uint8
align uint8 Align uint8
falign uint8 FieldAlign uint8
kflags uint8 KindFlags uint8
traits unsafe.Pointer Traits unsafe.Pointer
gcdata *byte GCData *byte
str int32 Str int32
p int32 PtrToSelf int32
}
func (self *GoType) Size() int {
return int(self.nb)
}
func (self *GoType) Hash() uint32 {
return self.hash
} }
func (self *GoType) Kind() reflect.Kind { 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) { func (self *GoType) Pack() (t reflect.Type) {
@ -60,14 +54,6 @@ func (self *GoType) Pack() (t reflect.Type) {
return 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 { func (self *GoType) String() string {
return self.Pack().String() return self.Pack().String()
} }

111
issue39_test.go Normal file
View 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
View 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)
}