Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opt: encoder VM #593

Merged
merged 7 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 39 additions & 14 deletions internal/encoder/alg/spec.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build (amd64 && go1.16 && !go1.22) || (arm64 && go1.20 && !go1.22)
// +build amd64,go1.16,!go1.22 arm64,go1.20,!go1.22

/**
Expand All @@ -20,6 +21,7 @@ package alg

import (
"runtime"
"strconv"
"unsafe"

"github.com/bytedance/sonic/internal/native"
Expand Down Expand Up @@ -150,6 +152,9 @@ func HtmlEscape(dst []byte, src []byte) []byte {
}

func F64toa(buf []byte, v float64) ([]byte) {
if v == 0 {
return append(buf, '0')
}
buf = rt.GuardSlice2(buf, 64)
ret := native.F64toa((*byte)(rt.IndexByte(buf, len(buf))), v)
if ret > 0 {
Expand All @@ -160,6 +165,9 @@ func F64toa(buf []byte, v float64) ([]byte) {
}

func F32toa(buf []byte, v float32) ([]byte) {
if v == 0 {
return append(buf, '0')
}
buf = rt.GuardSlice2(buf, 64)
ret := native.F32toa((*byte)(rt.IndexByte(buf, len(buf))), v)
if ret > 0 {
Expand All @@ -169,22 +177,39 @@ func F32toa(buf []byte, v float32) ([]byte) {
}
}

// func I64toa(buf []byte, v int64) ([]byte) {
// if -10 < v && v < 10 {
// buf = rt.GuardSlice2(buf, 32)
// ret := native.I64toa((*byte)(rt.IndexByte(buf, len(buf))), v)
// if ret > 0 {
// return buf[:len(buf)+ret]
// } else {
// return buf
// }
// } else {
// return strconv.AppendInt(buf, v, 10)
// }
// }

// func U64toa(buf []byte, v uint64) ([]byte) {
// if v < 10 {
// buf = rt.GuardSlice2(buf, 32)
// ret := native.U64toa((*byte)(rt.IndexByte(buf, len(buf))), v)
// if ret > 0 {
// return buf[:len(buf)+ret]
// } else {
// return buf
// }
// } else {
// return strconv.AppendInt(buf, int64(v), 10)
// }
// }

func I64toa(buf []byte, v int64) ([]byte) {
buf = rt.GuardSlice2(buf, 32)
ret := native.I64toa((*byte)(rt.IndexByte(buf, len(buf))), v)
if ret > 0 {
return buf[:len(buf)+ret]
} else {
return buf
}
return strconv.AppendInt(buf, int64(v), 10)
}

func U64toa(buf []byte, v uint64) ([]byte) {
buf = rt.GuardSlice2(buf, 32)
ret := native.U64toa((*byte)(rt.IndexByte(buf, len(buf))), v)
if ret > 0 {
return buf[:len(buf)+ret]
} else {
return buf
}
return strconv.AppendUint(buf, v, 10)
}

6 changes: 6 additions & 0 deletions internal/encoder/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ func (self *Compiler) compileMap(p *ir.Program, sp int, vt reflect.Type) {
func (self *Compiler) compileMapBody(p *ir.Program, sp int, vt reflect.Type) {
p.Tag(sp + 1)
p.Int(ir.OP_byte, '{')
e := p.PC()
p.Add(ir.OP_is_zero_map)
p.Add(ir.OP_save)
p.Rtt(ir.OP_map_iter, vt)
p.Add(ir.OP_save)
Expand Down Expand Up @@ -271,6 +273,7 @@ func (self *Compiler) compileMapBody(p *ir.Program, sp int, vt reflect.Type) {
p.Pin(j)
p.Add(ir.OP_map_stop)
p.Add(ir.OP_drop_2)
p.Pin(e)
p.Int(ir.OP_byte, '}')
}

Expand Down Expand Up @@ -355,6 +358,8 @@ func (self *Compiler) compileSliceBody(p *ir.Program, sp int, vt reflect.Type) {
func (self *Compiler) compileSliceArray(p *ir.Program, sp int, vt reflect.Type) {
p.Tag(sp)
p.Int(ir.OP_byte, '[')
e := p.PC()
p.Add(ir.OP_is_nil)
p.Add(ir.OP_save)
p.Add(ir.OP_slice_len)
i := p.PC()
Expand All @@ -368,6 +373,7 @@ func (self *Compiler) compileSliceArray(p *ir.Program, sp int, vt reflect.Type)
p.Pin(i)
p.Pin(j)
p.Add(ir.OP_drop)
p.Pin(e)
p.Int(ir.OP_byte, ']')
}

Expand Down
120 changes: 47 additions & 73 deletions internal/encoder/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
pc++
op := ins.Op()

if vars.DebugSyncGC {
print_instr(buf, pc, op, ins)
}
// if vars.DebugSyncGC {
// print_instr(buf, pc, op, ins)
// }

switch op {
case ir.OP_goto:
Expand Down Expand Up @@ -124,15 +124,15 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
continue
}
case ir.OP_null:
buf = append(buf, "null"...)
buf = append(buf, 'n', 'u', 'l', 'l')
case ir.OP_str:
v := *(*string)(p)
buf = alg.Quote(buf, v, false)
case ir.OP_bool:
if *(*bool)(p) {
buf = append(buf, "true"...)
buf = append(buf, 't', 'r', 'u', 'e')
} else {
buf = append(buf, "false"...)
buf = append(buf, 'f', 'a', 'l', 's', 'e')
}
case ir.OP_i8:
v := *(*int8)(p)
Expand Down Expand Up @@ -226,6 +226,28 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
continue
}
p = it.It.K
case ir.OP_marshal_text:
vt, itab := ins.Vtab()
var it rt.GoIface
switch vt.Kind() {
case reflect.Interface :
if is_nil(p) {
buf = append(buf, 'n', 'u', 'l', 'l')
continue
}
it = rt.AssertI2I(_T_encoding_TextMarshaler, *(*rt.GoIface)(p))
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
default : it = convT2I(p, !vt.Indirect(), itab)
}
if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return err
}
case ir.OP_marshal_text_p:
_, itab := ins.Vtab()
it := convT2I(p, false, itab)
if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return err
}
case ir.OP_map_write_key:
if has_opts(flags, alg.BitSortMapKeys) {
v := *(*string)(p)
Expand Down Expand Up @@ -280,38 +302,36 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
}
case ir.OP_empty_arr:
if has_opts(flags, alg.BitNoNullSliceOrMap) {
buf = append(buf, "[]"...)
buf = append(buf, '[', ']')
} else {
buf = append(buf, "null"...)
buf = append(buf, 'n', 'u', 'l', 'l')
}
case ir.OP_empty_obj:
if has_opts(flags, alg.BitNoNullSliceOrMap) {
buf = append(buf, "{}"...)
buf = append(buf, '{', '}')
} else {
buf = append(buf, "null"...)
buf = append(buf, 'n', 'u', 'l', 'l')
}
case ir.OP_marshal:
vt, itab := ins.Vtab()
var err error
if buf, err = call_json_marshaler(buf, vt, itab, p, flags, false); err != nil {
return err
}
case ir.OP_marshal_p:
vt, itab := ins.Vtab()
var err error
if buf, err = call_json_marshaler(buf, vt, itab, p, flags, true); err != nil {
return err
var it rt.GoIface
switch vt.Kind() {
case reflect.Interface :
if is_nil(p) {
buf = append(buf, 'n', 'u', 'l', 'l')
continue
}
it = rt.AssertI2I(_T_json_Marshaler, *(*rt.GoIface)(p))
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
default : it = convT2I(p, !vt.Indirect(), itab)
}
case ir.OP_marshal_text:
vt, itab := ins.Vtab()
var err error
if buf, err = call_text_marshaler(buf, vt, itab, p, flags, false); err != nil {
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return err
}
case ir.OP_marshal_text_p:
vt, itab := ins.Vtab()
var err error
if buf, err = call_text_marshaler(buf, vt, itab, p, flags, true); err != nil {
case ir.OP_marshal_p:
_, itab := ins.Vtab()
it := convT2I(p, false, itab)
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return err
}
default:
Expand Down Expand Up @@ -348,49 +368,3 @@ func convT2I(ptr unsafe.Pointer, deref bool, itab *rt.GoItab) (rt.GoIface) {
Value: ptr,
}
}

func call_text_marshaler(buf []byte, vt *rt.GoType, itab *rt.GoItab, p unsafe.Pointer, flags uint64, pointer bool) ([]byte, error) {
var it rt.GoIface
if !pointer {
switch vt.Kind() {
case reflect.Interface :
if is_nil(p) {
buf = append(buf, "null"...)
return buf, nil
}
it = rt.AssertI2I(_T_encoding_TextMarshaler, *(*rt.GoIface)(p))
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
default : it = convT2I(p, !vt.Indirect(), itab)
}

} else {
it = convT2I(p, false, itab)
}
if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return buf, err
}
return buf, nil
}

func call_json_marshaler(buf []byte, vt *rt.GoType, itab *rt.GoItab, p unsafe.Pointer, flags uint64, pointer bool) ([]byte, error) {
var it rt.GoIface
if !pointer {
switch vt.Kind() {
case reflect.Interface :
if is_nil(p) {
buf = append(buf, "null"...)
return buf, nil
}
it = rt.AssertI2I(_T_json_Marshaler, *(*rt.GoIface)(p))
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
default : it = convT2I(p, !vt.Indirect(), itab)
}

} else {
it = convT2I(p, false, itab)
}
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
return buf, err
}
return buf, nil
}
11 changes: 7 additions & 4 deletions internal/native/neon/f32toa_arm64.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

TEXT ·__f32toa_entry__(SB), NOSPLIT, $16
NO_LOCAL_POINTERS
WORD $0x910083ff // add sp, sp, #32
JMP _f32toa
WORD $0x100000a0 // adr x0, .+20
MOVD R0, ret(FP)
RET
// .p2align 2, 0x00
_f32toa:
WORD $0xa9be7bfd // stp fp, lr, [sp, #-32]!
Expand Down Expand Up @@ -905,7 +906,7 @@ _Digits:
WORD $0x37393639 // .ascii 4, '96979899'
WORD $0x39393839 // .ascii 4, '9899'
WORD $0x00000000 // .p2align 3, 0x00
_LB_e80ea3d0: // _pow10_ceil_sig_f32.g
_LB_8f8a73de: // _pow10_ceil_sig_f32.g
WORD $0x4b43fcf5; WORD $0x81ceb32c // .quad -9093133594791772939
WORD $0x5e14fc32; WORD $0xa2425ff7 // .quad -6754730975062328270
WORD $0x359a3b3f; WORD $0xcad2f7f5 // .quad -3831727700400522433
Expand Down Expand Up @@ -997,7 +998,9 @@ _f32toa:
MOVD out+0(FP), R0
FMOVD val+8(FP), F0
WORD $0xf90007fc // str x28, [sp, #8]
CALL ·__f32toa_entry__(SB) // _f32toa
MOVD ·_subr__f32toa(SB), R11
WORD $0x1000005e // adr x30, .+8
JMP (R11)
WORD $0xf94007fc // ldr x28, [sp, #8]
MOVD R0, ret+16(FP)
RET
Expand Down
2 changes: 1 addition & 1 deletion internal/native/neon/f32toa_subr_arm64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions internal/native/neon/f64toa_arm64.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

TEXT ·__f64toa_entry__(SB), NOSPLIT, $16
NO_LOCAL_POINTERS
WORD $0x910083ff // add sp, sp, #32
JMP _f64toa
WORD $0x100000a0 // adr x0, .+20
MOVD R0, ret(FP)
RET
// .p2align 2, 0x00
_f64toa:
WORD $0xa9be7bfd // stp fp, lr, [sp, #-32]!
Expand Down Expand Up @@ -1221,7 +1222,7 @@ _Digits:
WORD $0x37393639 // .ascii 4, '96979899'
WORD $0x39393839 // .ascii 4, '9899'
// .p2align 3, 0x00
_LB_40c6cc40: // _pow10_ceil_sig.g
_LB_1c9f0ea5: // _pow10_ceil_sig.g
WORD $0xbebcdc4f; WORD $0xff77b1fc // .quad -38366372719436721
WORD $0x13bb0f7b; WORD $0x25e8e89c // .quad 2731688931043774331
WORD $0xf73609b1; WORD $0x9faacf3d // .quad -6941508010590729807
Expand Down Expand Up @@ -2470,7 +2471,9 @@ _f64toa:
MOVD out+0(FP), R0
FMOVD val+8(FP), F0
WORD $0xf90007fc // str x28, [sp, #8]
CALL ·__f64toa_entry__(SB) // _f64toa
MOVD ·_subr__f64toa(SB), R11
WORD $0x1000005e // adr x30, .+8
JMP (R11)
WORD $0xf94007fc // ldr x28, [sp, #8]
MOVD R0, ret+16(FP)
RET
Expand Down
2 changes: 1 addition & 1 deletion internal/native/neon/f64toa_subr_arm64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading