Skip to content

Commit

Permalink
opt: encoder VM (#593)
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY authored Feb 18, 2024
1 parent 820917d commit 14b90fc
Show file tree
Hide file tree
Showing 51 changed files with 283 additions and 223 deletions.
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

0 comments on commit 14b90fc

Please sign in to comment.