mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore]: Bump github.com/gin-contrib/gzip from 1.0.1 to 1.1.0 (#3639)
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.1 to 1.1.0. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
@ -14,15 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package encoder
|
||||
package alg
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/native"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
@ -32,8 +33,8 @@ type _MapPair struct {
|
||||
m [32]byte
|
||||
}
|
||||
|
||||
type _MapIterator struct {
|
||||
it rt.GoMapIterator // must be the first field
|
||||
type MapIterator struct {
|
||||
It rt.GoMapIterator // must be the first field
|
||||
kv rt.GoSlice // slice of _MapPair
|
||||
ki int
|
||||
}
|
||||
@ -44,43 +45,43 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
if unsafe.Offsetof(_MapIterator{}.it) != 0 {
|
||||
if unsafe.Offsetof(MapIterator{}.It) != 0 {
|
||||
panic("_MapIterator.it is not the first field")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func newIterator() *_MapIterator {
|
||||
func newIterator() *MapIterator {
|
||||
if v := iteratorPool.Get(); v == nil {
|
||||
return new(_MapIterator)
|
||||
return new(MapIterator)
|
||||
} else {
|
||||
return resetIterator(v.(*_MapIterator))
|
||||
return resetIterator(v.(*MapIterator))
|
||||
}
|
||||
}
|
||||
|
||||
func resetIterator(p *_MapIterator) *_MapIterator {
|
||||
func resetIterator(p *MapIterator) *MapIterator {
|
||||
p.ki = 0
|
||||
p.it = rt.GoMapIterator{}
|
||||
p.It = rt.GoMapIterator{}
|
||||
p.kv.Len = 0
|
||||
return p
|
||||
}
|
||||
|
||||
func (self *_MapIterator) at(i int) *_MapPair {
|
||||
func (self *MapIterator) at(i int) *_MapPair {
|
||||
return (*_MapPair)(unsafe.Pointer(uintptr(self.kv.Ptr) + uintptr(i) * unsafe.Sizeof(_MapPair{})))
|
||||
}
|
||||
|
||||
func (self *_MapIterator) add() (p *_MapPair) {
|
||||
func (self *MapIterator) add() (p *_MapPair) {
|
||||
p = self.at(self.kv.Len)
|
||||
self.kv.Len++
|
||||
return
|
||||
}
|
||||
|
||||
func (self *_MapIterator) data() (p []_MapPair) {
|
||||
func (self *MapIterator) data() (p []_MapPair) {
|
||||
*(*rt.GoSlice)(unsafe.Pointer(&p)) = self.kv
|
||||
return
|
||||
}
|
||||
|
||||
func (self *_MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointer) (err error) {
|
||||
func (self *MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointer) (err error) {
|
||||
p := self.add()
|
||||
p.v = v
|
||||
|
||||
@ -94,26 +95,26 @@ func (self *_MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointe
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *_MapIterator) appendGeneric(p *_MapPair, t *rt.GoType, v reflect.Kind, k unsafe.Pointer) error {
|
||||
func (self *MapIterator) appendGeneric(p *_MapPair, t *rt.GoType, v reflect.Kind, k unsafe.Pointer) error {
|
||||
switch v {
|
||||
case reflect.Int : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int)(k)))]) ; return nil
|
||||
case reflect.Int8 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int8)(k)))]) ; return nil
|
||||
case reflect.Int16 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int16)(k)))]) ; return nil
|
||||
case reflect.Int32 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int32)(k)))]) ; return nil
|
||||
case reflect.Int64 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], *(*int64)(k))]) ; return nil
|
||||
case reflect.Uint : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint)(k)))]) ; return nil
|
||||
case reflect.Uint8 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint8)(k)))]) ; return nil
|
||||
case reflect.Uint16 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint16)(k)))]) ; return nil
|
||||
case reflect.Uint32 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint32)(k)))]) ; return nil
|
||||
case reflect.Uint64 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], *(*uint64)(k))]) ; return nil
|
||||
case reflect.Uintptr : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uintptr)(k)))]) ; return nil
|
||||
case reflect.Int : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int)(k)), 10)) ; return nil
|
||||
case reflect.Int8 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int8)(k)), 10)) ; return nil
|
||||
case reflect.Int16 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int16)(k)), 10)) ; return nil
|
||||
case reflect.Int32 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int32)(k)), 10)) ; return nil
|
||||
case reflect.Int64 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int64)(k)), 10)) ; return nil
|
||||
case reflect.Uint : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint)(k)), 10)) ; return nil
|
||||
case reflect.Uint8 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint8)(k)), 10)) ; return nil
|
||||
case reflect.Uint16 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint16)(k)), 10)) ; return nil
|
||||
case reflect.Uint32 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint32)(k)), 10)) ; return nil
|
||||
case reflect.Uint64 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint64)(k)), 10)) ; return nil
|
||||
case reflect.Uintptr : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uintptr)(k)), 10)) ; return nil
|
||||
case reflect.Interface : return self.appendInterface(p, t, k)
|
||||
case reflect.Struct, reflect.Ptr : return self.appendConcrete(p, t, k)
|
||||
default : panic("unexpected map key type")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
||||
func (self *MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
||||
// compiler has already checked that the type implements the encoding.MarshalText interface
|
||||
if !t.Indirect() {
|
||||
k = *(*unsafe.Pointer)(k)
|
||||
@ -127,7 +128,7 @@ func (self *_MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Poi
|
||||
return
|
||||
}
|
||||
|
||||
func (self *_MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
||||
func (self *MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
||||
if len(rt.IfaceType(t).Methods) == 0 {
|
||||
panic("unexpected map key type")
|
||||
} else if p.k, err = asText(k); err == nil {
|
||||
@ -137,17 +138,17 @@ func (self *_MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Po
|
||||
}
|
||||
}
|
||||
|
||||
func iteratorStop(p *_MapIterator) {
|
||||
func IteratorStop(p *MapIterator) {
|
||||
iteratorPool.Put(p)
|
||||
}
|
||||
|
||||
func iteratorNext(p *_MapIterator) {
|
||||
func IteratorNext(p *MapIterator) {
|
||||
i := p.ki
|
||||
t := &p.it
|
||||
t := &p.It
|
||||
|
||||
/* check for unordered iteration */
|
||||
if i < 0 {
|
||||
mapiternext(t)
|
||||
rt.Mapiternext(t)
|
||||
return
|
||||
}
|
||||
|
||||
@ -164,25 +165,25 @@ func iteratorNext(p *_MapIterator) {
|
||||
p.ki++
|
||||
}
|
||||
|
||||
func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, error) {
|
||||
func IteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*MapIterator, error) {
|
||||
it := newIterator()
|
||||
mapiterinit(t, m, &it.it)
|
||||
rt.Mapiterinit(t, m, &it.It)
|
||||
|
||||
/* check for key-sorting, empty map don't need sorting */
|
||||
if m.Count == 0 || (fv & uint64(SortMapKeys)) == 0 {
|
||||
if m.Count == 0 || (fv & (1<<BitSortMapKeys)) == 0 {
|
||||
it.ki = -1
|
||||
return it, nil
|
||||
}
|
||||
|
||||
/* pre-allocate space if needed */
|
||||
if m.Count > it.kv.Cap {
|
||||
it.kv = growslice(iteratorPair, it.kv, m.Count)
|
||||
it.kv = rt.GrowSlice(iteratorPair, it.kv, m.Count)
|
||||
}
|
||||
|
||||
/* dump all the key-value pairs */
|
||||
for ; it.it.K != nil; mapiternext(&it.it) {
|
||||
if err := it.append(t.Key, it.it.K, it.it.V); err != nil {
|
||||
iteratorStop(it)
|
||||
for ; it.It.K != nil; rt.Mapiternext(&it.It) {
|
||||
if err := it.append(t.Key, it.It.K, it.It.V); err != nil {
|
||||
IteratorStop(it)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -193,7 +194,13 @@ func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, erro
|
||||
}
|
||||
|
||||
/* load the first pair into iterator */
|
||||
it.it.V = it.at(0).v
|
||||
it.it.K = unsafe.Pointer(&it.at(0).k)
|
||||
it.It.V = it.at(0).v
|
||||
it.It.K = unsafe.Pointer(&it.at(0).k)
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func asText(v unsafe.Pointer) (string, error) {
|
||||
text := rt.AssertI2I(rt.UnpackType(vars.EncodingTextMarshalerType), *(*rt.GoIface)(v))
|
||||
r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText()
|
||||
return rt.Mem2Str(r), e
|
||||
}
|
31
vendor/github.com/bytedance/sonic/internal/encoder/alg/opts.go
generated
vendored
Normal file
31
vendor/github.com/bytedance/sonic/internal/encoder/alg/opts.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright 2024 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 alg
|
||||
|
||||
const (
|
||||
BitSortMapKeys = iota
|
||||
BitEscapeHTML
|
||||
BitCompactMarshaler
|
||||
BitNoQuoteTextMarshaler
|
||||
BitNoNullSliceOrMap
|
||||
BitValidateString
|
||||
BitNoValidateJSONMarshaler
|
||||
BitNoEncoderNewline
|
||||
BitEncodeNullForInfOrNan
|
||||
|
||||
BitPointerValue = 63
|
||||
)
|
95
vendor/github.com/bytedance/sonic/internal/encoder/alg/primitives.go
generated
vendored
Normal file
95
vendor/github.com/bytedance/sonic/internal/encoder/alg/primitives.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright 2024 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 alg
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
func Compact(p *[]byte, v []byte) error {
|
||||
buf := vars.NewBuffer()
|
||||
err := json.Compact(buf, v)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* add to result */
|
||||
v = buf.Bytes()
|
||||
*p = append(*p, v...)
|
||||
|
||||
/* return the buffer into pool */
|
||||
vars.FreeBuffer(buf)
|
||||
return nil
|
||||
}
|
||||
|
||||
func EncodeNil(rb *[]byte) error {
|
||||
*rb = append(*rb, 'n', 'u', 'l', 'l')
|
||||
return nil
|
||||
}
|
||||
|
||||
// func Make_EncodeTypedPointer(computor func(*rt.GoType, ...interface{}) (interface{}, error)) func(*[]byte, *rt.GoType, *unsafe.Pointer, *vars.Stack, uint64) error {
|
||||
// return func(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error {
|
||||
// if vt == nil {
|
||||
// return EncodeNil(buf)
|
||||
// } else if fn, err := vars.FindOrCompile(vt, (fv&(1<<BitPointerValue)) != 0, computor); err != nil {
|
||||
// return err
|
||||
// } else if vt.Indirect() {
|
||||
// err := fn(buf, *vp, sb, fv)
|
||||
// return err
|
||||
// } else {
|
||||
// err := fn(buf, unsafe.Pointer(vp), sb, fv)
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
func EncodeJsonMarshaler(buf *[]byte, val json.Marshaler, opt uint64) error {
|
||||
if ret, err := val.MarshalJSON(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if opt&(1<<BitCompactMarshaler) != 0 {
|
||||
return Compact(buf, ret)
|
||||
}
|
||||
if opt&(1<<BitNoValidateJSONMarshaler) == 0 {
|
||||
if ok, s := Valid(ret); !ok {
|
||||
return vars.Error_marshaler(ret, s)
|
||||
}
|
||||
}
|
||||
*buf = append(*buf, ret...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func EncodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler, opt uint64) error {
|
||||
if ret, err := val.MarshalText(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if opt&(1<<BitNoQuoteTextMarshaler) != 0 {
|
||||
*buf = append(*buf, ret...)
|
||||
return nil
|
||||
}
|
||||
*buf = Quote(*buf, rt.Mem2Str(ret), false)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package encoder
|
||||
package alg
|
||||
|
||||
// Algorithm 3-way Radix Quicksort, d means the radix.
|
||||
// Reference: https://algs4.cs.princeton.edu/51radix/Quick3string.java.html
|
198
vendor/github.com/bytedance/sonic/internal/encoder/alg/spec.go
generated
vendored
Normal file
198
vendor/github.com/bytedance/sonic/internal/encoder/alg/spec.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
//go:build (amd64 && go1.16 && !go1.24) || (arm64 && go1.20 && !go1.24)
|
||||
// +build amd64,go1.16,!go1.24 arm64,go1.20,!go1.24
|
||||
|
||||
/**
|
||||
* Copyright 2024 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 alg
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/native"
|
||||
"github.com/bytedance/sonic/internal/native/types"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
// Valid validates json and returns first non-blank character position,
|
||||
// if it is only one valid json value.
|
||||
// Otherwise returns invalid character position using start.
|
||||
//
|
||||
// Note: it does not check for the invalid UTF-8 characters.
|
||||
func Valid(data []byte) (ok bool, start int) {
|
||||
n := len(data)
|
||||
if n == 0 {
|
||||
return false, -1
|
||||
}
|
||||
s := rt.Mem2Str(data)
|
||||
p := 0
|
||||
m := types.NewStateMachine()
|
||||
ret := native.ValidateOne(&s, &p, m, 0)
|
||||
types.FreeStateMachine(m)
|
||||
|
||||
if ret < 0 {
|
||||
return false, p-1
|
||||
}
|
||||
|
||||
/* check for trailing spaces */
|
||||
for ;p < n; p++ {
|
||||
if (types.SPACE_MASK & (1 << data[p])) == 0 {
|
||||
return false, p
|
||||
}
|
||||
}
|
||||
|
||||
return true, ret
|
||||
}
|
||||
|
||||
var typeByte = rt.UnpackEface(byte(0)).Type
|
||||
|
||||
//go:nocheckptr
|
||||
func Quote(buf []byte, val string, double bool) []byte {
|
||||
if len(val) == 0 {
|
||||
if double {
|
||||
return append(buf, `"\"\""`...)
|
||||
}
|
||||
return append(buf, `""`...)
|
||||
}
|
||||
|
||||
if double {
|
||||
buf = append(buf, `"\"`...)
|
||||
} else {
|
||||
buf = append(buf, `"`...)
|
||||
}
|
||||
sp := rt.IndexChar(val, 0)
|
||||
nb := len(val)
|
||||
b := (*rt.GoSlice)(unsafe.Pointer(&buf))
|
||||
|
||||
// input buffer
|
||||
for nb > 0 {
|
||||
// output buffer
|
||||
dp := unsafe.Pointer(uintptr(b.Ptr) + uintptr(b.Len))
|
||||
dn := b.Cap - b.Len
|
||||
// call native.Quote, dn is byte count it outputs
|
||||
opts := uint64(0)
|
||||
if double {
|
||||
opts = types.F_DOUBLE_UNQUOTE
|
||||
}
|
||||
ret := native.Quote(sp, nb, dp, &dn, opts)
|
||||
// update *buf length
|
||||
b.Len += dn
|
||||
|
||||
// no need more output
|
||||
if ret >= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// double buf size
|
||||
*b = rt.GrowSlice(typeByte, *b, b.Cap*2)
|
||||
// ret is the complement of consumed input
|
||||
ret = ^ret
|
||||
// update input buffer
|
||||
nb -= ret
|
||||
sp = unsafe.Pointer(uintptr(sp) + uintptr(ret))
|
||||
}
|
||||
|
||||
runtime.KeepAlive(buf)
|
||||
runtime.KeepAlive(sp)
|
||||
if double {
|
||||
buf = append(buf, `\""`...)
|
||||
} else {
|
||||
buf = append(buf, `"`...)
|
||||
}
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
func HtmlEscape(dst []byte, src []byte) []byte {
|
||||
var sidx int
|
||||
|
||||
dst = append(dst, src[:0]...) // avoid check nil dst
|
||||
sbuf := (*rt.GoSlice)(unsafe.Pointer(&src))
|
||||
dbuf := (*rt.GoSlice)(unsafe.Pointer(&dst))
|
||||
|
||||
/* grow dst if it is shorter */
|
||||
if cap(dst)-len(dst) < len(src)+types.BufPaddingSize {
|
||||
cap := len(src)*3/2 + types.BufPaddingSize
|
||||
*dbuf = rt.GrowSlice(typeByte, *dbuf, cap)
|
||||
}
|
||||
|
||||
for sidx < sbuf.Len {
|
||||
sp := rt.Add(sbuf.Ptr, uintptr(sidx))
|
||||
dp := rt.Add(dbuf.Ptr, uintptr(dbuf.Len))
|
||||
|
||||
sn := sbuf.Len - sidx
|
||||
dn := dbuf.Cap - dbuf.Len
|
||||
nb := native.HTMLEscape(sp, sn, dp, &dn)
|
||||
|
||||
/* check for errors */
|
||||
if dbuf.Len += dn; nb >= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
/* not enough space, grow the slice and try again */
|
||||
sidx += ^nb
|
||||
*dbuf = rt.GrowSlice(typeByte, *dbuf, dbuf.Cap*2)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
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 {
|
||||
return buf[:len(buf)+ret]
|
||||
} else {
|
||||
return buf
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return buf[:len(buf)+ret]
|
||||
} else {
|
||||
return buf
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
148
vendor/github.com/bytedance/sonic/internal/encoder/alg/spec_compat.go
generated
vendored
Normal file
148
vendor/github.com/bytedance/sonic/internal/encoder/alg/spec_compat.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
// +build !amd64,!arm64 go1.24 !go1.16 arm64,!go1.20
|
||||
|
||||
/**
|
||||
* Copyright 2024 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 alg
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
"unicode/utf8"
|
||||
"strconv"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
// Valid validates json and returns first non-blank character position,
|
||||
// if it is only one valid json value.
|
||||
// Otherwise returns invalid character position using start.
|
||||
//
|
||||
// Note: it does not check for the invalid UTF-8 characters.
|
||||
func Valid(data []byte) (ok bool, start int) {
|
||||
ok = json.Valid(data)
|
||||
return ok, 0
|
||||
}
|
||||
|
||||
var typeByte = rt.UnpackEface(byte(0)).Type
|
||||
|
||||
func Quote(e []byte, s string, double bool) []byte {
|
||||
if len(s) == 0 {
|
||||
if double {
|
||||
return append(e, `"\"\""`...)
|
||||
}
|
||||
return append(e, `""`...)
|
||||
}
|
||||
|
||||
b := e
|
||||
ss := len(e)
|
||||
e = append(e, '"')
|
||||
start := 0
|
||||
|
||||
for i := 0; i < len(s); {
|
||||
if b := s[i]; b < utf8.RuneSelf {
|
||||
if rt.SafeSet[b] {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if start < i {
|
||||
e = append(e, s[start:i]...)
|
||||
}
|
||||
e = append(e, '\\')
|
||||
switch b {
|
||||
case '\\', '"':
|
||||
e = append(e, b)
|
||||
case '\n':
|
||||
e = append(e, 'n')
|
||||
case '\r':
|
||||
e = append(e, 'r')
|
||||
case '\t':
|
||||
e = append(e, 't')
|
||||
default:
|
||||
// This encodes bytes < 0x20 except for \t, \n and \r.
|
||||
// If escapeHTML is set, it also escapes <, >, and &
|
||||
// because they can lead to security holes when
|
||||
// user-controlled strings are rendered into JSON
|
||||
// and served to some browsers.
|
||||
e = append(e, `u00`...)
|
||||
e = append(e, rt.Hex[b>>4])
|
||||
e = append(e, rt.Hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
c, size := utf8.DecodeRuneInString(s[i:])
|
||||
// if correct && c == utf8.RuneError && size == 1 {
|
||||
// if start < i {
|
||||
// e = append(e, s[start:i]...)
|
||||
// }
|
||||
// e = append(e, `\ufffd`...)
|
||||
// i += size
|
||||
// start = i
|
||||
// continue
|
||||
// }
|
||||
if c == '\u2028' || c == '\u2029' {
|
||||
if start < i {
|
||||
e = append(e, s[start:i]...)
|
||||
}
|
||||
e = append(e, `\u202`...)
|
||||
e = append(e, rt.Hex[c&0xF])
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
}
|
||||
|
||||
if start < len(s) {
|
||||
e = append(e, s[start:]...)
|
||||
}
|
||||
e = append(e, '"')
|
||||
|
||||
if double {
|
||||
return strconv.AppendQuote(b, string(e[ss:]))
|
||||
} else {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
func HtmlEscape(dst []byte, src []byte) []byte {
|
||||
buf := bytes.NewBuffer(dst)
|
||||
json.HTMLEscape(buf, src)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func F64toa(buf []byte, v float64) ([]byte) {
|
||||
bs := bytes.NewBuffer(buf)
|
||||
_ = json.NewEncoder(bs).Encode(v)
|
||||
return bs.Bytes()
|
||||
}
|
||||
|
||||
func F32toa(buf []byte, v float32) ([]byte) {
|
||||
bs := bytes.NewBuffer(buf)
|
||||
_ = json.NewEncoder(bs).Encode(v)
|
||||
return bs.Bytes()
|
||||
}
|
||||
|
||||
func I64toa(buf []byte, v int64) ([]byte) {
|
||||
return strconv.AppendInt(buf, int64(v), 10)
|
||||
}
|
||||
|
||||
func U64toa(buf []byte, v uint64) ([]byte) {
|
||||
return strconv.AppendUint(buf, v, 10)
|
||||
}
|
0
vendor/github.com/bytedance/sonic/internal/encoder/asm.s
generated
vendored
0
vendor/github.com/bytedance/sonic/internal/encoder/asm.s
generated
vendored
51
vendor/github.com/bytedance/sonic/internal/encoder/asm_stubs_amd64_go116.go
generated
vendored
51
vendor/github.com/bytedance/sonic/internal/encoder/asm_stubs_amd64_go116.go
generated
vendored
@ -1,51 +0,0 @@
|
||||
// +build go1.16,!go1.17
|
||||
|
||||
// Copyright 2023 CloudWeGo Authors
|
||||
//
|
||||
// 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 encoder
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
)
|
||||
|
||||
var (
|
||||
_V_writeBarrier = jit.Imm(int64(_runtime_writeBarrier))
|
||||
|
||||
_F_gcWriteBarrierAX = jit.Func(gcWriteBarrierAX)
|
||||
)
|
||||
|
||||
func (self *_Assembler) WritePtr(i int, ptr obj.Addr, rec obj.Addr) {
|
||||
if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
|
||||
panic("rec contains AX!")
|
||||
}
|
||||
self.Emit("MOVQ", _V_writeBarrier, _R10)
|
||||
self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0))
|
||||
self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Emit("MOVQ", ptr, _AX)
|
||||
self.xsave(_DI)
|
||||
self.Emit("LEAQ", rec, _DI)
|
||||
self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX
|
||||
self.Rjmp("CALL", _R10)
|
||||
self.xload(_DI)
|
||||
self.Sjmp("JMP", "_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Emit("MOVQ", ptr, rec)
|
||||
self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
}
|
||||
|
1176
vendor/github.com/bytedance/sonic/internal/encoder/assembler_regabi_amd64.go
generated
vendored
1176
vendor/github.com/bytedance/sonic/internal/encoder/assembler_regabi_amd64.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1175
vendor/github.com/bytedance/sonic/internal/encoder/assembler_stkabi_amd64.go
generated
vendored
1175
vendor/github.com/bytedance/sonic/internal/encoder/assembler_stkabi_amd64.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1379
vendor/github.com/bytedance/sonic/internal/encoder/compiler.go
generated
vendored
1379
vendor/github.com/bytedance/sonic/internal/encoder/compiler.go
generated
vendored
File diff suppressed because it is too large
Load Diff
205
vendor/github.com/bytedance/sonic/internal/encoder/debug_go117.go
generated
vendored
205
vendor/github.com/bytedance/sonic/internal/encoder/debug_go117.go
generated
vendored
@ -1,205 +0,0 @@
|
||||
// +build go1.17,!go1.23
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`os`
|
||||
`runtime`
|
||||
`strings`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
)
|
||||
|
||||
const _FP_debug = 128
|
||||
|
||||
var (
|
||||
debugSyncGC = os.Getenv("SONIC_SYNC_GC") != ""
|
||||
debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
|
||||
debugCheckPtr = os.Getenv("SONIC_CHECK_POINTER") != ""
|
||||
)
|
||||
|
||||
var (
|
||||
_Instr_End = newInsOp(_OP_is_nil)
|
||||
|
||||
_F_gc = jit.Func(gc)
|
||||
_F_println = jit.Func(println_wrapper)
|
||||
_F_print = jit.Func(print)
|
||||
)
|
||||
|
||||
func (self *_Assembler) dsave(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _FP_debug / 8 - 1 {
|
||||
panic("too many registers to save")
|
||||
} else {
|
||||
self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs + _FP_saves + _FP_locals + int64(i) * 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Assembler) dload(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _FP_debug / 8 - 1 {
|
||||
panic("too many registers to load")
|
||||
} else {
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs + _FP_saves + _FP_locals + int64(i) * 8), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func println_wrapper(i int, op1 int, op2 int){
|
||||
println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2])
|
||||
}
|
||||
|
||||
func print(i int){
|
||||
println(i)
|
||||
}
|
||||
|
||||
func gc() {
|
||||
if !debugSyncGC {
|
||||
return
|
||||
}
|
||||
runtime.GC()
|
||||
// debug.FreeOSMemory()
|
||||
}
|
||||
|
||||
func (self *_Assembler) dcall(fn obj.Addr) {
|
||||
self.Emit("MOVQ", fn, _R10) // MOVQ ${fn}, R10
|
||||
self.Rjmp("CALL", _R10) // CALL R10
|
||||
}
|
||||
|
||||
func (self *_Assembler) debug_gc() {
|
||||
if !debugSyncGC {
|
||||
return
|
||||
}
|
||||
self.dsave(_REG_debug...)
|
||||
self.dcall(_F_gc)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
||||
|
||||
func (self *_Assembler) debug_instr(i int, v *_Instr) {
|
||||
if debugSyncGC {
|
||||
if i+1 == len(self.p) {
|
||||
self.print_gc(i, v, &_Instr_End)
|
||||
} else {
|
||||
next := &(self.p[i+1])
|
||||
self.print_gc(i, v, next)
|
||||
name := _OpNames[next.op()]
|
||||
if strings.Contains(name, "save") {
|
||||
return
|
||||
}
|
||||
}
|
||||
// self.debug_gc()
|
||||
}
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
//go:linkname checkptrBase runtime.checkptrBase
|
||||
func checkptrBase(p unsafe.Pointer) uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname findObject runtime.findObject
|
||||
func findObject(p, refBase, refOff uintptr) (base uintptr, s unsafe.Pointer, objIndex uintptr)
|
||||
|
||||
var (
|
||||
_F_checkptr = jit.Func(checkptr)
|
||||
_F_printptr = jit.Func(printptr)
|
||||
)
|
||||
|
||||
var (
|
||||
_R10 = jit.Reg("R10")
|
||||
)
|
||||
var _REG_debug = []obj.Addr {
|
||||
jit.Reg("AX"),
|
||||
jit.Reg("BX"),
|
||||
jit.Reg("CX"),
|
||||
jit.Reg("DX"),
|
||||
jit.Reg("DI"),
|
||||
jit.Reg("SI"),
|
||||
jit.Reg("BP"),
|
||||
jit.Reg("SP"),
|
||||
jit.Reg("R8"),
|
||||
jit.Reg("R9"),
|
||||
jit.Reg("R10"),
|
||||
jit.Reg("R11"),
|
||||
jit.Reg("R12"),
|
||||
jit.Reg("R13"),
|
||||
jit.Reg("R14"),
|
||||
jit.Reg("R15"),
|
||||
}
|
||||
|
||||
func checkptr(ptr uintptr) {
|
||||
if ptr == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Printf("pointer: %x\n", ptr)
|
||||
f := checkptrBase(unsafe.Pointer(uintptr(ptr)))
|
||||
if f == 0 {
|
||||
fmt.Printf("! unknown-based pointer: %x\n", ptr)
|
||||
} else if f == 1 {
|
||||
fmt.Printf("! stack pointer: %x\n", ptr)
|
||||
} else {
|
||||
fmt.Printf("base: %x\n", f)
|
||||
}
|
||||
findobj(ptr)
|
||||
}
|
||||
|
||||
func findobj(ptr uintptr) {
|
||||
base, s, objIndex := findObject(ptr, 0, 0)
|
||||
if s != nil && base == 0 {
|
||||
fmt.Printf("! invalid pointer: %x\n", ptr)
|
||||
}
|
||||
fmt.Printf("objIndex: %d\n", objIndex)
|
||||
}
|
||||
|
||||
func (self *_Assembler) check_ptr(ptr obj.Addr, lea bool) {
|
||||
if !debugCheckPtr {
|
||||
return
|
||||
}
|
||||
|
||||
self.dsave(_REG_debug...)
|
||||
if lea {
|
||||
self.Emit("LEAQ", ptr, _R10)
|
||||
} else {
|
||||
self.Emit("MOVQ", ptr, _R10)
|
||||
}
|
||||
self.Emit("MOVQ", _R10, jit.Ptr(_SP, 0))
|
||||
self.dcall(_F_checkptr)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
||||
|
||||
func printptr(i int, ptr uintptr) {
|
||||
fmt.Printf("[%d] ptr: %x\n", i, ptr)
|
||||
}
|
||||
|
||||
func (self *_Assembler) print_ptr(i int, ptr obj.Addr, lea bool) {
|
||||
self.dsave(_REG_debug...)
|
||||
if lea {
|
||||
self.Emit("LEAQ", ptr, _R10)
|
||||
} else {
|
||||
self.Emit("MOVQ", ptr, _R10)
|
||||
}
|
||||
|
||||
self.Emit("MOVQ", jit.Imm(int64(i)), _AX)
|
||||
self.Emit("MOVQ", _R10, _BX)
|
||||
self.dcall(_F_printptr)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
24
vendor/github.com/bytedance/sonic/internal/encoder/encode_norace.go
generated
vendored
Normal file
24
vendor/github.com/bytedance/sonic/internal/encoder/encode_norace.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
//go:build !race
|
||||
// +build !race
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
func encodeIntoCheckRace(buf *[]byte, val interface{}, opts Options) error {
|
||||
return encodeInto(buf, val, opts)
|
||||
}
|
54
vendor/github.com/bytedance/sonic/internal/encoder/encode_race.go
generated
vendored
Normal file
54
vendor/github.com/bytedance/sonic/internal/encoder/encode_race.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
//go:build race
|
||||
// +build race
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
|
||||
func helpDetectDataRace(val interface{}) {
|
||||
var out []byte
|
||||
defer func() {
|
||||
if v := recover(); v != nil {
|
||||
// NOTICE: help user to locate where panic occurs
|
||||
println("panic when encoding on: ", truncate(out))
|
||||
panic(v)
|
||||
}
|
||||
}()
|
||||
out, _ = json.Marshal(val)
|
||||
}
|
||||
|
||||
func encodeIntoCheckRace(buf *[]byte, val interface{}, opts Options) error {
|
||||
err := encodeInto(buf, val, opts)
|
||||
/* put last to make the panic from sonic will always be caught at first */
|
||||
helpDetectDataRace(val)
|
||||
return err
|
||||
}
|
||||
|
||||
func truncate(json []byte) string {
|
||||
if len(json) <= 256 {
|
||||
return rt.Mem2Str(json)
|
||||
} else {
|
||||
return rt.Mem2Str(json[len(json)-256:])
|
||||
}
|
||||
}
|
169
vendor/github.com/bytedance/sonic/internal/encoder/encoder.go
generated
vendored
169
vendor/github.com/bytedance/sonic/internal/encoder/encoder.go
generated
vendored
@ -17,72 +17,62 @@
|
||||
package encoder
|
||||
|
||||
import (
|
||||
`bytes`
|
||||
`encoding/json`
|
||||
`reflect`
|
||||
`runtime`
|
||||
`unsafe`
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/bytedance/sonic/utf8`
|
||||
`github.com/bytedance/sonic/option`
|
||||
"github.com/bytedance/sonic/utf8"
|
||||
"github.com/bytedance/sonic/internal/encoder/alg"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/option"
|
||||
)
|
||||
|
||||
// Options is a set of encoding options.
|
||||
type Options uint64
|
||||
|
||||
const (
|
||||
bitSortMapKeys = iota
|
||||
bitEscapeHTML
|
||||
bitCompactMarshaler
|
||||
bitNoQuoteTextMarshaler
|
||||
bitNoNullSliceOrMap
|
||||
bitValidateString
|
||||
bitNoValidateJSONMarshaler
|
||||
bitNoEncoderNewline
|
||||
|
||||
// used for recursive compile
|
||||
bitPointerValue = 63
|
||||
)
|
||||
|
||||
const (
|
||||
// SortMapKeys indicates that the keys of a map needs to be sorted
|
||||
// before serializing into JSON.
|
||||
// WARNING: This hurts performance A LOT, USE WITH CARE.
|
||||
SortMapKeys Options = 1 << bitSortMapKeys
|
||||
SortMapKeys Options = 1 << alg.BitSortMapKeys
|
||||
|
||||
// EscapeHTML indicates encoder to escape all HTML characters
|
||||
// after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).
|
||||
// WARNING: This hurts performance A LOT, USE WITH CARE.
|
||||
EscapeHTML Options = 1 << bitEscapeHTML
|
||||
EscapeHTML Options = 1 << alg.BitEscapeHTML
|
||||
|
||||
// CompactMarshaler indicates that the output JSON from json.Marshaler
|
||||
// is always compact and needs no validation
|
||||
CompactMarshaler Options = 1 << bitCompactMarshaler
|
||||
CompactMarshaler Options = 1 << alg.BitCompactMarshaler
|
||||
|
||||
// NoQuoteTextMarshaler indicates that the output text from encoding.TextMarshaler
|
||||
// is always escaped string and needs no quoting
|
||||
NoQuoteTextMarshaler Options = 1 << bitNoQuoteTextMarshaler
|
||||
NoQuoteTextMarshaler Options = 1 << alg.BitNoQuoteTextMarshaler
|
||||
|
||||
// NoNullSliceOrMap indicates all empty Array or Object are encoded as '[]' or '{}',
|
||||
// instead of 'null'
|
||||
NoNullSliceOrMap Options = 1 << bitNoNullSliceOrMap
|
||||
// instead of 'null'.
|
||||
// NOTE: The priority of this option is lower than json tag `omitempty`.
|
||||
NoNullSliceOrMap Options = 1 << alg.BitNoNullSliceOrMap
|
||||
|
||||
// ValidateString indicates that encoder should validate the input string
|
||||
// before encoding it into JSON.
|
||||
ValidateString Options = 1 << bitValidateString
|
||||
ValidateString Options = 1 << alg.BitValidateString
|
||||
|
||||
// NoValidateJSONMarshaler indicates that the encoder should not validate the output string
|
||||
// after encoding the JSONMarshaler to JSON.
|
||||
NoValidateJSONMarshaler Options = 1 << bitNoValidateJSONMarshaler
|
||||
NoValidateJSONMarshaler Options = 1 << alg.BitNoValidateJSONMarshaler
|
||||
|
||||
// NoEncoderNewline indicates that the encoder should not add a newline after every message
|
||||
NoEncoderNewline Options = 1 << bitNoEncoderNewline
|
||||
NoEncoderNewline Options = 1 << alg.BitNoEncoderNewline
|
||||
|
||||
// CompatibleWithStd is used to be compatible with std encoder.
|
||||
CompatibleWithStd Options = SortMapKeys | EscapeHTML | CompactMarshaler
|
||||
|
||||
// Encode Infinity or Nan float into `null`, instead of returning an error.
|
||||
EncodeNullForInfOrNan Options = 1 << alg.BitEncodeNullForInfOrNan
|
||||
)
|
||||
|
||||
// Encoder represents a specific set of encoder configurations.
|
||||
@ -171,53 +161,45 @@ func (enc *Encoder) SetIndent(prefix, indent string) {
|
||||
|
||||
// Quote returns the JSON-quoted version of s.
|
||||
func Quote(s string) string {
|
||||
var n int
|
||||
var p []byte
|
||||
|
||||
/* check for empty string */
|
||||
if s == "" {
|
||||
return `""`
|
||||
}
|
||||
|
||||
/* allocate space for result */
|
||||
n = len(s) + 2
|
||||
p = make([]byte, 0, n)
|
||||
|
||||
/* call the encoder */
|
||||
_ = encodeString(&p, s)
|
||||
return rt.Mem2Str(p)
|
||||
buf := make([]byte, 0, len(s)+2)
|
||||
buf = alg.Quote(buf, s, false)
|
||||
return rt.Mem2Str(buf)
|
||||
}
|
||||
|
||||
// Encode returns the JSON encoding of val, encoded with opts.
|
||||
func Encode(val interface{}, opts Options) ([]byte, error) {
|
||||
var ret []byte
|
||||
|
||||
buf := newBytes()
|
||||
err := encodeInto(&buf, val, opts)
|
||||
buf := vars.NewBytes()
|
||||
err := encodeIntoCheckRace(buf, val, opts)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
freeBytes(buf)
|
||||
vars.FreeBytes(buf)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* htmlescape or correct UTF-8 if opts enable */
|
||||
old := buf
|
||||
buf = encodeFinish(old, opts)
|
||||
pbuf := ((*rt.GoSlice)(unsafe.Pointer(&buf))).Ptr
|
||||
pold := ((*rt.GoSlice)(unsafe.Pointer(&old))).Ptr
|
||||
*buf = encodeFinish(*old, opts)
|
||||
pbuf := ((*rt.GoSlice)(unsafe.Pointer(buf))).Ptr
|
||||
pold := ((*rt.GoSlice)(unsafe.Pointer(old))).Ptr
|
||||
|
||||
/* return when allocated a new buffer */
|
||||
if pbuf != pold {
|
||||
freeBytes(old)
|
||||
return buf, nil
|
||||
vars.FreeBytes(old)
|
||||
return *buf, nil
|
||||
}
|
||||
|
||||
/* make a copy of the result */
|
||||
ret = make([]byte, len(buf))
|
||||
copy(ret, buf)
|
||||
|
||||
freeBytes(buf)
|
||||
if rt.CanSizeResue(cap(*buf)) {
|
||||
ret = make([]byte, len(*buf))
|
||||
copy(ret, *buf)
|
||||
vars.FreeBytes(buf)
|
||||
} else {
|
||||
ret = *buf
|
||||
}
|
||||
|
||||
/* return the buffer into pool */
|
||||
return ret, nil
|
||||
}
|
||||
@ -225,7 +207,7 @@ func Encode(val interface{}, opts Options) ([]byte, error) {
|
||||
// EncodeInto is like Encode but uses a user-supplied buffer instead of allocating
|
||||
// a new one.
|
||||
func EncodeInto(buf *[]byte, val interface{}, opts Options) error {
|
||||
err := encodeInto(buf, val, opts)
|
||||
err := encodeIntoCheckRace(buf, val, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -234,15 +216,15 @@ func EncodeInto(buf *[]byte, val interface{}, opts Options) error {
|
||||
}
|
||||
|
||||
func encodeInto(buf *[]byte, val interface{}, opts Options) error {
|
||||
stk := newStack()
|
||||
stk := vars.NewStack()
|
||||
efv := rt.UnpackEface(val)
|
||||
err := encodeTypedPointer(buf, efv.Type, &efv.Value, stk, uint64(opts))
|
||||
|
||||
/* return the stack into pool */
|
||||
if err != nil {
|
||||
resetStack(stk)
|
||||
vars.ResetStack(stk)
|
||||
}
|
||||
freeStack(stk)
|
||||
vars.FreeStack(stk)
|
||||
|
||||
/* avoid GC ahead */
|
||||
runtime.KeepAlive(buf)
|
||||
@ -254,13 +236,12 @@ func encodeFinish(buf []byte, opts Options) []byte {
|
||||
if opts & EscapeHTML != 0 {
|
||||
buf = HTMLEscape(nil, buf)
|
||||
}
|
||||
if opts & ValidateString != 0 && !utf8.Validate(buf) {
|
||||
if (opts & ValidateString != 0) && !utf8.Validate(buf) {
|
||||
buf = utf8.CorrectWith(nil, buf, `\ufffd`)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
var typeByte = rt.UnpackType(reflect.TypeOf(byte(0)))
|
||||
|
||||
// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
|
||||
// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
|
||||
@ -269,7 +250,7 @@ var typeByte = rt.UnpackType(reflect.TypeOf(byte(0)))
|
||||
// escaping within <script> tags, so an alternative JSON encoding must
|
||||
// be used.
|
||||
func HTMLEscape(dst []byte, src []byte) []byte {
|
||||
return htmlEscape(dst, src)
|
||||
return alg.HtmlEscape(dst, src)
|
||||
}
|
||||
|
||||
// EncodeIndented is like Encode but applies Indent to format the output.
|
||||
@ -277,37 +258,40 @@ func HTMLEscape(dst []byte, src []byte) []byte {
|
||||
// followed by one or more copies of indent according to the indentation nesting.
|
||||
func EncodeIndented(val interface{}, prefix string, indent string, opts Options) ([]byte, error) {
|
||||
var err error
|
||||
var out []byte
|
||||
var buf *bytes.Buffer
|
||||
|
||||
/* encode into the buffer */
|
||||
out = newBytes()
|
||||
err = EncodeInto(&out, val, opts)
|
||||
out := vars.NewBytes()
|
||||
err = EncodeInto(out, val, opts)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
freeBytes(out)
|
||||
vars.FreeBytes(out)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* indent the JSON */
|
||||
buf = newBuffer()
|
||||
err = json.Indent(buf, out, prefix, indent)
|
||||
buf = vars.NewBuffer()
|
||||
err = json.Indent(buf, *out, prefix, indent)
|
||||
vars.FreeBytes(out)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
freeBytes(out)
|
||||
freeBuffer(buf)
|
||||
vars.FreeBuffer(buf)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* copy to the result buffer */
|
||||
ret := make([]byte, buf.Len())
|
||||
copy(ret, buf.Bytes())
|
||||
|
||||
/* return the buffers into pool */
|
||||
freeBytes(out)
|
||||
freeBuffer(buf)
|
||||
var ret []byte
|
||||
if rt.CanSizeResue(cap(buf.Bytes())) {
|
||||
ret = make([]byte, buf.Len())
|
||||
copy(ret, buf.Bytes())
|
||||
/* return the buffers into pool */
|
||||
vars.FreeBuffer(buf)
|
||||
} else {
|
||||
ret = buf.Bytes()
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@ -330,26 +314,5 @@ func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
|
||||
//
|
||||
// Note: it does not check for the invalid UTF-8 characters.
|
||||
func Valid(data []byte) (ok bool, start int) {
|
||||
n := len(data)
|
||||
if n == 0 {
|
||||
return false, -1
|
||||
}
|
||||
s := rt.Mem2Str(data)
|
||||
p := 0
|
||||
m := types.NewStateMachine()
|
||||
ret := native.ValidateOne(&s, &p, m, types.F_VALIDATE_STRING)
|
||||
types.FreeStateMachine(m)
|
||||
|
||||
if ret < 0 {
|
||||
return false, p-1
|
||||
}
|
||||
|
||||
/* check for trailing spaces */
|
||||
for ;p < n; p++ {
|
||||
if (types.SPACE_MASK & (1 << data[p])) == 0 {
|
||||
return false, p
|
||||
}
|
||||
}
|
||||
|
||||
return true, ret
|
||||
return alg.Valid(data)
|
||||
}
|
||||
|
473
vendor/github.com/bytedance/sonic/internal/encoder/ir/op.go
generated
vendored
Normal file
473
vendor/github.com/bytedance/sonic/internal/encoder/ir/op.go
generated
vendored
Normal file
@ -0,0 +1,473 @@
|
||||
/*
|
||||
* 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 ir
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type Op uint8
|
||||
|
||||
const (
|
||||
OP_null Op = iota + 1
|
||||
OP_empty_arr
|
||||
OP_empty_obj
|
||||
OP_bool
|
||||
OP_i8
|
||||
OP_i16
|
||||
OP_i32
|
||||
OP_i64
|
||||
OP_u8
|
||||
OP_u16
|
||||
OP_u32
|
||||
OP_u64
|
||||
OP_f32
|
||||
OP_f64
|
||||
OP_str
|
||||
OP_bin
|
||||
OP_quote
|
||||
OP_number
|
||||
OP_eface
|
||||
OP_iface
|
||||
OP_byte
|
||||
OP_text
|
||||
OP_deref
|
||||
OP_index
|
||||
OP_load
|
||||
OP_save
|
||||
OP_drop
|
||||
OP_drop_2
|
||||
OP_recurse
|
||||
OP_is_nil
|
||||
OP_is_nil_p1
|
||||
OP_is_zero_1
|
||||
OP_is_zero_2
|
||||
OP_is_zero_4
|
||||
OP_is_zero_8
|
||||
OP_is_zero_map
|
||||
OP_goto
|
||||
OP_map_iter
|
||||
OP_map_stop
|
||||
OP_map_check_key
|
||||
OP_map_write_key
|
||||
OP_map_value_next
|
||||
OP_slice_len
|
||||
OP_slice_next
|
||||
OP_marshal
|
||||
OP_marshal_p
|
||||
OP_marshal_text
|
||||
OP_marshal_text_p
|
||||
OP_cond_set
|
||||
OP_cond_testc
|
||||
)
|
||||
|
||||
const (
|
||||
_INT_SIZE = 32 << (^uint(0) >> 63)
|
||||
_PTR_SIZE = 32 << (^uintptr(0) >> 63)
|
||||
_PTR_BYTE = unsafe.Sizeof(uintptr(0))
|
||||
)
|
||||
|
||||
const OpSize = unsafe.Sizeof(NewInsOp(0))
|
||||
|
||||
var OpNames = [256]string{
|
||||
OP_null: "null",
|
||||
OP_empty_arr: "empty_arr",
|
||||
OP_empty_obj: "empty_obj",
|
||||
OP_bool: "bool",
|
||||
OP_i8: "i8",
|
||||
OP_i16: "i16",
|
||||
OP_i32: "i32",
|
||||
OP_i64: "i64",
|
||||
OP_u8: "u8",
|
||||
OP_u16: "u16",
|
||||
OP_u32: "u32",
|
||||
OP_u64: "u64",
|
||||
OP_f32: "f32",
|
||||
OP_f64: "f64",
|
||||
OP_str: "str",
|
||||
OP_bin: "bin",
|
||||
OP_quote: "quote",
|
||||
OP_number: "number",
|
||||
OP_eface: "eface",
|
||||
OP_iface: "iface",
|
||||
OP_byte: "byte",
|
||||
OP_text: "text",
|
||||
OP_deref: "deref",
|
||||
OP_index: "index",
|
||||
OP_load: "load",
|
||||
OP_save: "save",
|
||||
OP_drop: "drop",
|
||||
OP_drop_2: "drop_2",
|
||||
OP_recurse: "recurse",
|
||||
OP_is_nil: "is_nil",
|
||||
OP_is_nil_p1: "is_nil_p1",
|
||||
OP_is_zero_1: "is_zero_1",
|
||||
OP_is_zero_2: "is_zero_2",
|
||||
OP_is_zero_4: "is_zero_4",
|
||||
OP_is_zero_8: "is_zero_8",
|
||||
OP_is_zero_map: "is_zero_map",
|
||||
OP_goto: "goto",
|
||||
OP_map_iter: "map_iter",
|
||||
OP_map_stop: "map_stop",
|
||||
OP_map_check_key: "map_check_key",
|
||||
OP_map_write_key: "map_write_key",
|
||||
OP_map_value_next: "map_value_next",
|
||||
OP_slice_len: "slice_len",
|
||||
OP_slice_next: "slice_next",
|
||||
OP_marshal: "marshal",
|
||||
OP_marshal_p: "marshal_p",
|
||||
OP_marshal_text: "marshal_text",
|
||||
OP_marshal_text_p: "marshal_text_p",
|
||||
OP_cond_set: "cond_set",
|
||||
OP_cond_testc: "cond_testc",
|
||||
}
|
||||
|
||||
func (self Op) String() string {
|
||||
if ret := OpNames[self]; ret != "" {
|
||||
return ret
|
||||
} else {
|
||||
return "<invalid>"
|
||||
}
|
||||
}
|
||||
|
||||
func OP_int() Op {
|
||||
switch _INT_SIZE {
|
||||
case 32:
|
||||
return OP_i32
|
||||
case 64:
|
||||
return OP_i64
|
||||
default:
|
||||
panic("unsupported int size")
|
||||
}
|
||||
}
|
||||
|
||||
func OP_uint() Op {
|
||||
switch _INT_SIZE {
|
||||
case 32:
|
||||
return OP_u32
|
||||
case 64:
|
||||
return OP_u64
|
||||
default:
|
||||
panic("unsupported uint size")
|
||||
}
|
||||
}
|
||||
|
||||
func OP_uintptr() Op {
|
||||
switch _PTR_SIZE {
|
||||
case 32:
|
||||
return OP_u32
|
||||
case 64:
|
||||
return OP_u64
|
||||
default:
|
||||
panic("unsupported pointer size")
|
||||
}
|
||||
}
|
||||
|
||||
func OP_is_zero_ints() Op {
|
||||
switch _INT_SIZE {
|
||||
case 32:
|
||||
return OP_is_zero_4
|
||||
case 64:
|
||||
return OP_is_zero_8
|
||||
default:
|
||||
panic("unsupported integer size")
|
||||
}
|
||||
}
|
||||
|
||||
type Instr struct {
|
||||
o Op
|
||||
u int // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
|
||||
p unsafe.Pointer // maybe GoString.Ptr, or *GoType
|
||||
}
|
||||
|
||||
func NewInsOp(op Op) Instr {
|
||||
return Instr{o: op}
|
||||
}
|
||||
|
||||
func NewInsVi(op Op, vi int) Instr {
|
||||
return Instr{o: op, u: vi}
|
||||
}
|
||||
|
||||
func NewInsVs(op Op, vs string) Instr {
|
||||
return Instr{
|
||||
o: op,
|
||||
u: len(vs),
|
||||
p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInsVt(op Op, vt reflect.Type) Instr {
|
||||
return Instr{
|
||||
o: op,
|
||||
p: unsafe.Pointer(rt.UnpackType(vt)),
|
||||
}
|
||||
}
|
||||
|
||||
type typAndTab struct {
|
||||
vt *rt.GoType
|
||||
itab *rt.GoItab
|
||||
}
|
||||
|
||||
func NewInsVtab(op Op, vt reflect.Type, itab *rt.GoItab) Instr {
|
||||
return Instr{
|
||||
o: op,
|
||||
p: unsafe.Pointer(&typAndTab{
|
||||
vt: rt.UnpackType(vt),
|
||||
itab: itab,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func NewInsVp(op Op, vt reflect.Type, pv bool) Instr {
|
||||
i := 0
|
||||
if pv {
|
||||
i = 1
|
||||
}
|
||||
return Instr{
|
||||
o: op,
|
||||
u: i,
|
||||
p: unsafe.Pointer(rt.UnpackType(vt)),
|
||||
}
|
||||
}
|
||||
|
||||
func (self Instr) Op() Op {
|
||||
return Op(self.o)
|
||||
}
|
||||
|
||||
func (self Instr) Vi() int {
|
||||
return self.u
|
||||
}
|
||||
|
||||
func (self Instr) Vf() uint8 {
|
||||
return (*rt.GoType)(self.p).KindFlags
|
||||
}
|
||||
|
||||
func (self Instr) Vs() (v string) {
|
||||
(*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
|
||||
(*rt.GoString)(unsafe.Pointer(&v)).Len = self.Vi()
|
||||
return
|
||||
}
|
||||
|
||||
func (self Instr) Vk() reflect.Kind {
|
||||
return (*rt.GoType)(self.p).Kind()
|
||||
}
|
||||
|
||||
func (self Instr) Vt() reflect.Type {
|
||||
return (*rt.GoType)(self.p).Pack()
|
||||
}
|
||||
|
||||
func (self Instr) Vr() *rt.GoType {
|
||||
return (*rt.GoType)(self.p)
|
||||
}
|
||||
|
||||
func (self Instr) Vp() (vt reflect.Type, pv bool) {
|
||||
return (*rt.GoType)(self.p).Pack(), self.u == 1
|
||||
}
|
||||
|
||||
func (self Instr) Vtab() (vt *rt.GoType, itab *rt.GoItab) {
|
||||
tt := (*typAndTab)(self.p)
|
||||
return tt.vt, tt.itab
|
||||
}
|
||||
|
||||
func (self Instr) Vp2() (vt *rt.GoType, pv bool) {
|
||||
return (*rt.GoType)(self.p), self.u == 1
|
||||
}
|
||||
|
||||
func (self Instr) I64() int64 {
|
||||
return int64(self.Vi())
|
||||
}
|
||||
|
||||
func (self Instr) Byte() byte {
|
||||
return byte(self.Vi())
|
||||
}
|
||||
|
||||
func (self Instr) Vlen() int {
|
||||
return int((*rt.GoType)(self.p).Size)
|
||||
}
|
||||
|
||||
func (self Instr) isBranch() bool {
|
||||
switch self.Op() {
|
||||
case OP_goto:
|
||||
fallthrough
|
||||
case OP_is_nil:
|
||||
fallthrough
|
||||
case OP_is_nil_p1:
|
||||
fallthrough
|
||||
case OP_is_zero_1:
|
||||
fallthrough
|
||||
case OP_is_zero_2:
|
||||
fallthrough
|
||||
case OP_is_zero_4:
|
||||
fallthrough
|
||||
case OP_is_zero_8:
|
||||
fallthrough
|
||||
case OP_map_check_key:
|
||||
fallthrough
|
||||
case OP_map_write_key:
|
||||
fallthrough
|
||||
case OP_slice_next:
|
||||
fallthrough
|
||||
case OP_cond_testc:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self Instr) Disassemble() string {
|
||||
switch self.Op() {
|
||||
case OP_byte:
|
||||
return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.QuoteRune(rune(self.Vi())))
|
||||
case OP_text:
|
||||
return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.Quote(self.Vs()))
|
||||
case OP_index:
|
||||
return fmt.Sprintf("%-18s%d", self.Op().String(), self.Vi())
|
||||
case OP_recurse:
|
||||
fallthrough
|
||||
case OP_map_iter:
|
||||
return fmt.Sprintf("%-18s%s", self.Op().String(), self.Vt())
|
||||
case OP_marshal:
|
||||
fallthrough
|
||||
case OP_marshal_p:
|
||||
fallthrough
|
||||
case OP_marshal_text:
|
||||
fallthrough
|
||||
case OP_marshal_text_p:
|
||||
vt, _ := self.Vtab()
|
||||
return fmt.Sprintf("%-18s%s", self.Op().String(), vt.Pack())
|
||||
case OP_goto:
|
||||
fallthrough
|
||||
case OP_is_nil:
|
||||
fallthrough
|
||||
case OP_is_nil_p1:
|
||||
fallthrough
|
||||
case OP_is_zero_1:
|
||||
fallthrough
|
||||
case OP_is_zero_2:
|
||||
fallthrough
|
||||
case OP_is_zero_4:
|
||||
fallthrough
|
||||
case OP_is_zero_8:
|
||||
fallthrough
|
||||
case OP_is_zero_map:
|
||||
fallthrough
|
||||
case OP_cond_testc:
|
||||
fallthrough
|
||||
case OP_map_check_key:
|
||||
fallthrough
|
||||
case OP_map_write_key:
|
||||
return fmt.Sprintf("%-18sL_%d", self.Op().String(), self.Vi())
|
||||
case OP_slice_next:
|
||||
return fmt.Sprintf("%-18sL_%d, %s", self.Op().String(), self.Vi(), self.Vt())
|
||||
default:
|
||||
return fmt.Sprintf("%#v", self)
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
Program []Instr
|
||||
)
|
||||
|
||||
func (self Program) PC() int {
|
||||
return len(self)
|
||||
}
|
||||
|
||||
func (self Program) Tag(n int) {
|
||||
if n >= vars.MaxStack {
|
||||
panic("type nesting too deep")
|
||||
}
|
||||
}
|
||||
|
||||
func (self Program) Pin(i int) {
|
||||
v := &self[i]
|
||||
v.u = self.PC()
|
||||
}
|
||||
|
||||
func (self Program) Rel(v []int) {
|
||||
for _, i := range v {
|
||||
self.Pin(i)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Program) Add(op Op) {
|
||||
*self = append(*self, NewInsOp(op))
|
||||
}
|
||||
|
||||
func (self *Program) Key(op Op) {
|
||||
*self = append(*self,
|
||||
NewInsVi(OP_byte, '"'),
|
||||
NewInsOp(op),
|
||||
NewInsVi(OP_byte, '"'),
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Program) Int(op Op, vi int) {
|
||||
*self = append(*self, NewInsVi(op, vi))
|
||||
}
|
||||
|
||||
func (self *Program) Str(op Op, vs string) {
|
||||
*self = append(*self, NewInsVs(op, vs))
|
||||
}
|
||||
|
||||
func (self *Program) Rtt(op Op, vt reflect.Type) {
|
||||
*self = append(*self, NewInsVt(op, vt))
|
||||
}
|
||||
|
||||
func (self *Program) Vp(op Op, vt reflect.Type, pv bool) {
|
||||
*self = append(*self, NewInsVp(op, vt, pv))
|
||||
}
|
||||
|
||||
func (self *Program) Vtab(op Op, vt reflect.Type, itab *rt.GoItab) {
|
||||
*self = append(*self, NewInsVtab(op, vt, itab))
|
||||
}
|
||||
|
||||
func (self Program) Disassemble() string {
|
||||
nb := len(self)
|
||||
tab := make([]bool, nb+1)
|
||||
ret := make([]string, 0, nb+1)
|
||||
|
||||
/* prescan to get all the labels */
|
||||
for _, ins := range self {
|
||||
if ins.isBranch() {
|
||||
tab[ins.Vi()] = true
|
||||
}
|
||||
}
|
||||
|
||||
/* disassemble each instruction */
|
||||
for i, ins := range self {
|
||||
if !tab[i] {
|
||||
ret = append(ret, "\t"+ins.Disassemble())
|
||||
} else {
|
||||
ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.Disassemble()))
|
||||
}
|
||||
}
|
||||
|
||||
/* add the last label, if needed */
|
||||
if tab[nb] {
|
||||
ret = append(ret, fmt.Sprintf("L_%d:", nb))
|
||||
}
|
||||
|
||||
/* add an "end" indicator, and join all the strings */
|
||||
return strings.Join(append(ret, "\tend"), "\n")
|
||||
}
|
193
vendor/github.com/bytedance/sonic/internal/encoder/pools.go
generated
vendored
193
vendor/github.com/bytedance/sonic/internal/encoder/pools.go
generated
vendored
@ -1,193 +0,0 @@
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`bytes`
|
||||
`sync`
|
||||
`unsafe`
|
||||
`errors`
|
||||
`reflect`
|
||||
|
||||
`github.com/bytedance/sonic/internal/caching`
|
||||
`github.com/bytedance/sonic/option`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
const (
|
||||
_MaxStack = 4096 // 4k states
|
||||
|
||||
_StackSize = unsafe.Sizeof(_Stack{})
|
||||
)
|
||||
|
||||
var (
|
||||
bytesPool = sync.Pool{}
|
||||
stackPool = sync.Pool{}
|
||||
bufferPool = sync.Pool{}
|
||||
programCache = caching.CreateProgramCache()
|
||||
)
|
||||
|
||||
type _State struct {
|
||||
x int
|
||||
f uint64
|
||||
p unsafe.Pointer
|
||||
q unsafe.Pointer
|
||||
}
|
||||
|
||||
type _Stack struct {
|
||||
sp uint64
|
||||
sb [_MaxStack]_State
|
||||
}
|
||||
|
||||
type _Encoder func(
|
||||
rb *[]byte,
|
||||
vp unsafe.Pointer,
|
||||
sb *_Stack,
|
||||
fv uint64,
|
||||
) error
|
||||
|
||||
var _KeepAlive struct {
|
||||
rb *[]byte
|
||||
vp unsafe.Pointer
|
||||
sb *_Stack
|
||||
fv uint64
|
||||
err error
|
||||
frame [_FP_offs]byte
|
||||
}
|
||||
|
||||
var errCallShadow = errors.New("DON'T CALL THIS!")
|
||||
|
||||
// Faker func of _Encoder, used to export its stackmap as _Encoder's
|
||||
func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) (err error) {
|
||||
// align to assembler_amd64.go: _FP_offs
|
||||
var frame [_FP_offs]byte
|
||||
|
||||
// must keep all args and frames noticeable to GC
|
||||
_KeepAlive.rb = rb
|
||||
_KeepAlive.vp = vp
|
||||
_KeepAlive.sb = sb
|
||||
_KeepAlive.fv = fv
|
||||
_KeepAlive.err = err
|
||||
_KeepAlive.frame = frame
|
||||
|
||||
return errCallShadow
|
||||
}
|
||||
|
||||
func newBytes() []byte {
|
||||
if ret := bytesPool.Get(); ret != nil {
|
||||
return ret.([]byte)
|
||||
} else {
|
||||
return make([]byte, 0, option.DefaultEncoderBufferSize)
|
||||
}
|
||||
}
|
||||
|
||||
func newStack() *_Stack {
|
||||
if ret := stackPool.Get(); ret == nil {
|
||||
return new(_Stack)
|
||||
} else {
|
||||
return ret.(*_Stack)
|
||||
}
|
||||
}
|
||||
|
||||
func resetStack(p *_Stack) {
|
||||
memclrNoHeapPointers(unsafe.Pointer(p), _StackSize)
|
||||
}
|
||||
|
||||
func newBuffer() *bytes.Buffer {
|
||||
if ret := bufferPool.Get(); ret != nil {
|
||||
return ret.(*bytes.Buffer)
|
||||
} else {
|
||||
return bytes.NewBuffer(make([]byte, 0, option.DefaultEncoderBufferSize))
|
||||
}
|
||||
}
|
||||
|
||||
func freeBytes(p []byte) {
|
||||
p = p[:0]
|
||||
bytesPool.Put(p)
|
||||
}
|
||||
|
||||
func freeStack(p *_Stack) {
|
||||
p.sp = 0
|
||||
stackPool.Put(p)
|
||||
}
|
||||
|
||||
func freeBuffer(p *bytes.Buffer) {
|
||||
p.Reset()
|
||||
bufferPool.Put(p)
|
||||
}
|
||||
|
||||
func makeEncoder(vt *rt.GoType, ex ...interface{}) (interface{}, error) {
|
||||
if pp, err := newCompiler().compile(vt.Pack(), ex[0].(bool)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
as := newAssembler(pp)
|
||||
as.name = vt.String()
|
||||
return as.Load(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func findOrCompile(vt *rt.GoType, pv bool) (_Encoder, error) {
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return val.(_Encoder), nil
|
||||
} else if ret, err := programCache.Compute(vt, makeEncoder, pv); err == nil {
|
||||
return ret.(_Encoder), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func pretouchType(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error) {
|
||||
/* compile function */
|
||||
compiler := newCompiler().apply(opts)
|
||||
encoder := func(vt *rt.GoType, ex ...interface{}) (interface{}, error) {
|
||||
if pp, err := compiler.compile(_vt, ex[0].(bool)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
as := newAssembler(pp)
|
||||
as.name = vt.String()
|
||||
return as.Load(), nil
|
||||
}
|
||||
}
|
||||
|
||||
/* find or compile */
|
||||
vt := rt.UnpackType(_vt)
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return nil, nil
|
||||
} else if _, err := programCache.Compute(vt, encoder, v == 1); err == nil {
|
||||
return compiler.rec, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func pretouchRec(vtm map[reflect.Type]uint8, opts option.CompileOptions) error {
|
||||
if opts.RecursiveDepth < 0 || len(vtm) == 0 {
|
||||
return nil
|
||||
}
|
||||
next := make(map[reflect.Type]uint8)
|
||||
for vt, v := range vtm {
|
||||
sub, err := pretouchType(vt, opts, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for svt, v := range sub {
|
||||
next[svt] = v
|
||||
}
|
||||
}
|
||||
opts.RecursiveDepth -= 1
|
||||
return pretouchRec(next, opts)
|
||||
}
|
97
vendor/github.com/bytedance/sonic/internal/encoder/pools_amd64.go
generated
vendored
Normal file
97
vendor/github.com/bytedance/sonic/internal/encoder/pools_amd64.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/encoder/x86"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/option"
|
||||
)
|
||||
|
||||
|
||||
func ForceUseJit() {
|
||||
x86.SetCompiler(makeEncoderX86)
|
||||
pretouchType = pretouchTypeX86
|
||||
encodeTypedPointer = x86.EncodeTypedPointer
|
||||
vars.UseVM = false
|
||||
}
|
||||
|
||||
func init() {
|
||||
if vars.UseVM {
|
||||
ForceUseVM()
|
||||
} else {
|
||||
ForceUseJit()
|
||||
}
|
||||
}
|
||||
|
||||
var _KeepAlive struct {
|
||||
rb *[]byte
|
||||
vp unsafe.Pointer
|
||||
sb *vars.Stack
|
||||
fv uint64
|
||||
err error
|
||||
frame [x86.FP_offs]byte
|
||||
}
|
||||
|
||||
var errCallShadow = errors.New("DON'T CALL THIS!")
|
||||
|
||||
// Faker func of _Encoder, used to export its stackmap as _Encoder's
|
||||
func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *vars.Stack, fv uint64) (err error) {
|
||||
// align to assembler_amd64.go: x86.FP_offs
|
||||
var frame [x86.FP_offs]byte
|
||||
|
||||
// must keep all args and frames noticeable to GC
|
||||
_KeepAlive.rb = rb
|
||||
_KeepAlive.vp = vp
|
||||
_KeepAlive.sb = sb
|
||||
_KeepAlive.fv = fv
|
||||
_KeepAlive.err = err
|
||||
_KeepAlive.frame = frame
|
||||
|
||||
return errCallShadow
|
||||
}
|
||||
|
||||
func makeEncoderX86(vt *rt.GoType, ex ...interface{}) (interface{}, error) {
|
||||
pp, err := NewCompiler().Compile(vt.Pack(), ex[0].(bool))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
as := x86.NewAssembler(pp)
|
||||
as.Name = vt.String()
|
||||
return as.Load(), nil
|
||||
}
|
||||
|
||||
func pretouchTypeX86(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error) {
|
||||
/* compile function */
|
||||
compiler := NewCompiler().apply(opts)
|
||||
|
||||
/* find or compile */
|
||||
vt := rt.UnpackType(_vt)
|
||||
if val := vars.GetProgram(vt); val != nil {
|
||||
return nil, nil
|
||||
} else if _, err := vars.ComputeProgram(vt, makeEncoderX86, v == 1); err == nil {
|
||||
return compiler.rec, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
24
vendor/github.com/bytedance/sonic/internal/encoder/pools_compt.go
generated
vendored
Normal file
24
vendor/github.com/bytedance/sonic/internal/encoder/pools_compt.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
//go:build !amd64
|
||||
// +build !amd64
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
func init() {
|
||||
ForceUseVM()
|
||||
}
|
167
vendor/github.com/bytedance/sonic/internal/encoder/primitives.go
generated
vendored
167
vendor/github.com/bytedance/sonic/internal/encoder/primitives.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`encoding`
|
||||
`encoding/json`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
/** Encoder Primitives **/
|
||||
|
||||
func encodeNil(rb *[]byte) error {
|
||||
*rb = append(*rb, 'n', 'u', 'l', 'l')
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeString(buf *[]byte, val string) error {
|
||||
var sidx int
|
||||
var pbuf *rt.GoSlice
|
||||
var pstr *rt.GoString
|
||||
|
||||
/* opening quote */
|
||||
*buf = append(*buf, '"')
|
||||
pbuf = (*rt.GoSlice)(unsafe.Pointer(buf))
|
||||
pstr = (*rt.GoString)(unsafe.Pointer(&val))
|
||||
|
||||
/* encode with native library */
|
||||
for sidx < pstr.Len {
|
||||
sn := pstr.Len - sidx
|
||||
dn := pbuf.Cap - pbuf.Len
|
||||
sp := padd(pstr.Ptr, sidx)
|
||||
dp := padd(pbuf.Ptr, pbuf.Len)
|
||||
nb := native.Quote(sp, sn, dp, &dn, 0)
|
||||
|
||||
/* check for errors */
|
||||
if pbuf.Len += dn; nb >= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
/* not enough space, grow the slice and try again */
|
||||
sidx += ^nb
|
||||
*pbuf = growslice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2)
|
||||
}
|
||||
|
||||
/* closing quote */
|
||||
*buf = append(*buf, '"')
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *_Stack, fv uint64) error {
|
||||
if vt == nil {
|
||||
return encodeNil(buf)
|
||||
} else if fn, err := findOrCompile(vt, (fv&(1<<bitPointerValue)) != 0); err != nil {
|
||||
return err
|
||||
} else if vt.Indirect() {
|
||||
rt.MoreStack(_FP_size + native.MaxFrameSize)
|
||||
err := fn(buf, *vp, sb, fv)
|
||||
return err
|
||||
} else {
|
||||
rt.MoreStack(_FP_size + native.MaxFrameSize)
|
||||
err := fn(buf, unsafe.Pointer(vp), sb, fv)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func encodeJsonMarshaler(buf *[]byte, val json.Marshaler, opt Options) error {
|
||||
if ret, err := val.MarshalJSON(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if opt & CompactMarshaler != 0 {
|
||||
return compact(buf, ret)
|
||||
}
|
||||
if opt & NoValidateJSONMarshaler == 0 {
|
||||
if ok, s := Valid(ret); !ok {
|
||||
return error_marshaler(ret, s)
|
||||
}
|
||||
}
|
||||
*buf = append(*buf, ret...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func encodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler, opt Options) error {
|
||||
if ret, err := val.MarshalText(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if opt & NoQuoteTextMarshaler != 0 {
|
||||
*buf = append(*buf, ret...)
|
||||
return nil
|
||||
}
|
||||
return encodeString(buf, rt.Mem2Str(ret) )
|
||||
}
|
||||
}
|
||||
|
||||
func htmlEscape(dst []byte, src []byte) []byte {
|
||||
var sidx int
|
||||
|
||||
dst = append(dst, src[:0]...) // avoid check nil dst
|
||||
sbuf := (*rt.GoSlice)(unsafe.Pointer(&src))
|
||||
dbuf := (*rt.GoSlice)(unsafe.Pointer(&dst))
|
||||
|
||||
/* grow dst if it is shorter */
|
||||
if cap(dst) - len(dst) < len(src) + types.BufPaddingSize {
|
||||
cap := len(src) * 3 / 2 + types.BufPaddingSize
|
||||
*dbuf = growslice(typeByte, *dbuf, cap)
|
||||
}
|
||||
|
||||
for sidx < sbuf.Len {
|
||||
sp := padd(sbuf.Ptr, sidx)
|
||||
dp := padd(dbuf.Ptr, dbuf.Len)
|
||||
|
||||
sn := sbuf.Len - sidx
|
||||
dn := dbuf.Cap - dbuf.Len
|
||||
nb := native.HTMLEscape(sp, sn, dp, &dn)
|
||||
|
||||
/* check for errors */
|
||||
if dbuf.Len += dn; nb >= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
/* not enough space, grow the slice and try again */
|
||||
sidx += ^nb
|
||||
*dbuf = growslice(typeByte, *dbuf, dbuf.Cap * 2)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
var (
|
||||
argPtrs = []bool { true, true, true, false }
|
||||
localPtrs = []bool{}
|
||||
)
|
||||
|
||||
var (
|
||||
_F_assertI2I = jit.Func(rt.AssertI2I2)
|
||||
)
|
||||
|
||||
func asText(v unsafe.Pointer) (string, error) {
|
||||
text := rt.AssertI2I2(_T_encoding_TextMarshaler, *(*rt.GoIface)(v))
|
||||
r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText()
|
||||
return rt.Mem2Str(r), e
|
||||
}
|
||||
|
||||
func asJson(v unsafe.Pointer) (string, error) {
|
||||
text := rt.AssertI2I2(_T_json_Marshaler, *(*rt.GoIface)(v))
|
||||
r, e := (*(*json.Marshaler)(unsafe.Pointer(&text))).MarshalJSON()
|
||||
return rt.Mem2Str(r), e
|
||||
}
|
28
vendor/github.com/bytedance/sonic/internal/encoder/stream.go
generated
vendored
28
vendor/github.com/bytedance/sonic/internal/encoder/stream.go
generated
vendored
@ -17,8 +17,10 @@
|
||||
package encoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`io`
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
)
|
||||
|
||||
// StreamEncoder uses io.Writer as input.
|
||||
@ -36,21 +38,20 @@ func NewStreamEncoder(w io.Writer) *StreamEncoder {
|
||||
|
||||
// Encode encodes interface{} as JSON to io.Writer
|
||||
func (enc *StreamEncoder) Encode(val interface{}) (err error) {
|
||||
buf := newBytes()
|
||||
out := buf
|
||||
out := vars.NewBytes()
|
||||
|
||||
/* encode into the buffer */
|
||||
err = EncodeInto(&out, val, enc.Opts)
|
||||
err = EncodeInto(out, val, enc.Opts)
|
||||
if err != nil {
|
||||
goto free_bytes
|
||||
}
|
||||
|
||||
if enc.indent != "" || enc.prefix != "" {
|
||||
/* indent the JSON */
|
||||
buf := newBuffer()
|
||||
err = json.Indent(buf, out, enc.prefix, enc.indent)
|
||||
buf := vars.NewBuffer()
|
||||
err = json.Indent(buf, *out, enc.prefix, enc.indent)
|
||||
if err != nil {
|
||||
freeBuffer(buf)
|
||||
vars.FreeBuffer(buf)
|
||||
goto free_bytes
|
||||
}
|
||||
|
||||
@ -62,16 +63,17 @@ func (enc *StreamEncoder) Encode(val interface{}) (err error) {
|
||||
/* copy into io.Writer */
|
||||
_, err = io.Copy(enc.w, buf)
|
||||
if err != nil {
|
||||
freeBuffer(buf)
|
||||
vars.FreeBuffer(buf)
|
||||
goto free_bytes
|
||||
}
|
||||
|
||||
} else {
|
||||
/* copy into io.Writer */
|
||||
var n int
|
||||
for len(out) > 0 {
|
||||
n, err = enc.w.Write(out)
|
||||
out = out[n:]
|
||||
buf := *out
|
||||
for len(buf) > 0 {
|
||||
n, err = enc.w.Write(buf)
|
||||
buf = buf[n:]
|
||||
if err != nil {
|
||||
goto free_bytes
|
||||
}
|
||||
@ -84,6 +86,6 @@ func (enc *StreamEncoder) Encode(val interface{}) (err error) {
|
||||
}
|
||||
|
||||
free_bytes:
|
||||
freeBytes(buf)
|
||||
vars.FreeBytes(out)
|
||||
return err
|
||||
}
|
||||
|
61
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go116.go
generated
vendored
61
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go116.go
generated
vendored
@ -1,61 +0,0 @@
|
||||
// +build go1.16,!go1.17
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
_ `github.com/cloudwego/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/cloudwego/base64x._subr__b64encode
|
||||
var _subr__b64encode uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname growslice runtime.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname mapiternext runtime.mapiternext
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiternext(it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname mapiterinit runtime.mapiterinit
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiterinit(t *rt.GoMapType, m *rt.GoMap, it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname isValidNumber encoding/json.isValidNumber
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func isValidNumber(s string) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
var _runtime_writeBarrier uintptr = rt.GcwbAddr()
|
||||
|
||||
//go:linkname gcWriteBarrierAX runtime.gcWriteBarrier
|
||||
func gcWriteBarrierAX()
|
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go117.go
generated
vendored
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go117.go
generated
vendored
@ -1,62 +0,0 @@
|
||||
// +build go1.17,!go1.20
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
_ `github.com/cloudwego/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/cloudwego/base64x._subr__b64encode
|
||||
var _subr__b64encode uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname growslice runtime.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname mapiternext runtime.mapiternext
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiternext(it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname mapiterinit runtime.mapiterinit
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiterinit(t *rt.GoMapType, m *rt.GoMap, it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname isValidNumber encoding/json.isValidNumber
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func isValidNumber(s string) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname _runtime_writeBarrier runtime.writeBarrier
|
||||
var _runtime_writeBarrier uintptr
|
||||
|
||||
//go:linkname gcWriteBarrierAX runtime.gcWriteBarrier
|
||||
func gcWriteBarrierAX()
|
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go120.go
generated
vendored
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go120.go
generated
vendored
@ -1,62 +0,0 @@
|
||||
// +build go1.20,!go1.21
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
_ `github.com/cloudwego/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/cloudwego/base64x._subr__b64encode
|
||||
var _subr__b64encode uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname growslice reflect.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname mapiternext runtime.mapiternext
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiternext(it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname mapiterinit runtime.mapiterinit
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiterinit(t *rt.GoMapType, m *rt.GoMap, it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname isValidNumber encoding/json.isValidNumber
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func isValidNumber(s string) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname _runtime_writeBarrier runtime.writeBarrier
|
||||
var _runtime_writeBarrier uintptr
|
||||
|
||||
//go:linkname gcWriteBarrierAX runtime.gcWriteBarrier
|
||||
func gcWriteBarrierAX()
|
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go121.go
generated
vendored
62
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go121.go
generated
vendored
@ -1,62 +0,0 @@
|
||||
// +build go1.21
|
||||
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
_ `github.com/cloudwego/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/cloudwego/base64x._subr__b64encode
|
||||
var _subr__b64encode uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname growslice reflect.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname mapiternext runtime.mapiternext
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiternext(it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname mapiterinit runtime.mapiterinit
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapiterinit(t *rt.GoMapType, m *rt.GoMap, it *rt.GoMapIterator)
|
||||
|
||||
//go:linkname isValidNumber encoding/json.isValidNumber
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func isValidNumber(s string) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname _runtime_writeBarrier runtime.writeBarrier
|
||||
var _runtime_writeBarrier uintptr
|
||||
|
||||
//go:linkname gcWriteBarrier2 runtime.gcWriteBarrier2
|
||||
func gcWriteBarrier2()
|
52
vendor/github.com/bytedance/sonic/internal/encoder/utils.go
generated
vendored
52
vendor/github.com/bytedance/sonic/internal/encoder/utils.go
generated
vendored
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 encoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/loader`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
func padd(p unsafe.Pointer, v int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(p) + uintptr(v))
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func ptoenc(p loader.Function) _Encoder {
|
||||
return *(*_Encoder)(unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
func compact(p *[]byte, v []byte) error {
|
||||
buf := newBuffer()
|
||||
err := json.Compact(buf, v)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* add to result */
|
||||
v = buf.Bytes()
|
||||
*p = append(*p, v...)
|
||||
|
||||
/* return the buffer into pool */
|
||||
freeBuffer(buf)
|
||||
return nil
|
||||
}
|
48
vendor/github.com/bytedance/sonic/internal/encoder/vars/cache.go
generated
vendored
Normal file
48
vendor/github.com/bytedance/sonic/internal/encoder/vars/cache.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 vars
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type Encoder func(
|
||||
rb *[]byte,
|
||||
vp unsafe.Pointer,
|
||||
sb *Stack,
|
||||
fv uint64,
|
||||
) error
|
||||
|
||||
func FindOrCompile(vt *rt.GoType, pv bool, compiler func(*rt.GoType, ... interface{}) (interface{}, error)) (interface{}, error) {
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return val, nil
|
||||
} else if ret, err := programCache.Compute(vt, compiler, pv); err == nil {
|
||||
return ret, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetProgram(vt *rt.GoType) (interface{}) {
|
||||
return programCache.Get(vt)
|
||||
}
|
||||
|
||||
func ComputeProgram(vt *rt.GoType, compute func(*rt.GoType, ... interface{}) (interface{}, error), pv bool) (interface{}, error) {
|
||||
return programCache.Compute(vt, compute, pv)
|
||||
}
|
42
vendor/github.com/bytedance/sonic/internal/encoder/vars/const.go
generated
vendored
Normal file
42
vendor/github.com/bytedance/sonic/internal/encoder/vars/const.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2024 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 vars
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxStack = 4096 // 4k states
|
||||
StackSize = unsafe.Sizeof(Stack{})
|
||||
StateSize = int64(unsafe.Sizeof(State{}))
|
||||
StackLimit = MaxStack * StateSize
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_ILBUF = 100000 // cutoff at 100k of IL instructions
|
||||
MAX_FIELDS = 50 // cutoff at 50 fields struct
|
||||
)
|
||||
|
||||
var (
|
||||
DebugSyncGC = os.Getenv("SONIC_SYNC_GC") != ""
|
||||
DebugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
|
||||
DebugCheckPtr = os.Getenv("SONIC_CHECK_POINTER") != ""
|
||||
)
|
||||
|
||||
var UseVM = os.Getenv("SONIC_ENCODER_USE_VM") != ""
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package encoder
|
||||
package vars
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
@ -26,39 +26,39 @@ import (
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
var _ERR_too_deep = &json.UnsupportedValueError {
|
||||
var ERR_too_deep = &json.UnsupportedValueError {
|
||||
Str : "Value nesting too deep",
|
||||
Value : reflect.ValueOf("..."),
|
||||
}
|
||||
|
||||
var _ERR_nan_or_infinite = &json.UnsupportedValueError {
|
||||
var ERR_nan_or_infinite = &json.UnsupportedValueError {
|
||||
Str : "NaN or ±Infinite",
|
||||
Value : reflect.ValueOf("NaN or ±Infinite"),
|
||||
}
|
||||
|
||||
func error_type(vtype reflect.Type) error {
|
||||
func Error_type(vtype reflect.Type) error {
|
||||
return &json.UnsupportedTypeError{Type: vtype}
|
||||
}
|
||||
|
||||
func error_number(number json.Number) error {
|
||||
func Error_number(number json.Number) error {
|
||||
return &json.UnsupportedValueError {
|
||||
Str : "invalid number literal: " + strconv.Quote(string(number)),
|
||||
Value : reflect.ValueOf(number),
|
||||
}
|
||||
}
|
||||
|
||||
func error_marshaler(ret []byte, pos int) error {
|
||||
func Error_marshaler(ret []byte, pos int) error {
|
||||
return fmt.Errorf("invalid Marshaler output json syntax at %d: %q", pos, ret)
|
||||
}
|
||||
|
||||
const (
|
||||
panicNilPointerOfNonEmptyString int = 1 + iota
|
||||
PanicNilPointerOfNonEmptyString int = 1 + iota
|
||||
)
|
||||
|
||||
func goPanic(code int, val unsafe.Pointer) {
|
||||
func GoPanic(code int, val unsafe.Pointer) {
|
||||
switch(code){
|
||||
case panicNilPointerOfNonEmptyString:
|
||||
panic(fmt.Sprintf("val: %#v has nil pointer while its length is not zero!", (*rt.GoString)(val)))
|
||||
case PanicNilPointerOfNonEmptyString:
|
||||
panic(fmt.Sprintf("val: %#v has nil pointer while its length is not zero!\nThis is a nil pointer exception (NPE) problem. There might be a data race issue. It is recommended to execute the tests related to the code with the `-race` compile flag to detect the problem.", (*rt.GoString)(val)))
|
||||
default:
|
||||
panic("encoder error!")
|
||||
}
|
146
vendor/github.com/bytedance/sonic/internal/encoder/vars/stack.go
generated
vendored
Normal file
146
vendor/github.com/bytedance/sonic/internal/encoder/vars/stack.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Copyright 2024 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 vars
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/caching"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/option"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
x int
|
||||
f uint64
|
||||
p unsafe.Pointer
|
||||
q unsafe.Pointer
|
||||
}
|
||||
|
||||
type Stack struct {
|
||||
sp uintptr
|
||||
sb [MaxStack]State
|
||||
}
|
||||
|
||||
var (
|
||||
bytesPool = sync.Pool{}
|
||||
stackPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Stack{}
|
||||
},
|
||||
}
|
||||
bufferPool = sync.Pool{}
|
||||
programCache = caching.CreateProgramCache()
|
||||
)
|
||||
|
||||
func NewBytes() *[]byte {
|
||||
if ret := bytesPool.Get(); ret != nil {
|
||||
return ret.(*[]byte)
|
||||
} else {
|
||||
ret := make([]byte, 0, option.DefaultEncoderBufferSize)
|
||||
return &ret
|
||||
}
|
||||
}
|
||||
|
||||
func NewStack() *Stack {
|
||||
ret := stackPool.Get().(*Stack)
|
||||
ret.sp = 0
|
||||
return ret
|
||||
}
|
||||
|
||||
func ResetStack(p *Stack) {
|
||||
rt.MemclrNoHeapPointers(unsafe.Pointer(p), StackSize)
|
||||
}
|
||||
|
||||
func (s *Stack) Top() *State {
|
||||
return (*State)(rt.Add(unsafe.Pointer(&s.sb[0]), s.sp))
|
||||
}
|
||||
|
||||
func (s *Stack) Cur() *State {
|
||||
return (*State)(rt.Add(unsafe.Pointer(&s.sb[0]), s.sp - uintptr(StateSize)))
|
||||
}
|
||||
|
||||
const _MaxStackSP = uintptr(MaxStack * StateSize)
|
||||
|
||||
func (s *Stack) Push(v State) bool {
|
||||
if uintptr(s.sp) >= _MaxStackSP {
|
||||
return false
|
||||
}
|
||||
st := s.Top()
|
||||
*st = v
|
||||
s.sp += uintptr(StateSize)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Stack) Pop() State {
|
||||
s.sp -= uintptr(StateSize)
|
||||
st := s.Top()
|
||||
ret := *st
|
||||
*st = State{}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *Stack) Load() (int, uint64, unsafe.Pointer, unsafe.Pointer) {
|
||||
st := s.Cur()
|
||||
return st.x, st.f, st.p, st.q
|
||||
}
|
||||
|
||||
func (s *Stack) Save(x int, f uint64, p unsafe.Pointer, q unsafe.Pointer) bool {
|
||||
return s.Push(State{x: x, f:f, p: p, q: q})
|
||||
}
|
||||
|
||||
func (s *Stack) Drop() (int, uint64, unsafe.Pointer, unsafe.Pointer) {
|
||||
st := s.Pop()
|
||||
return st.x, st.f, st.p, st.q
|
||||
}
|
||||
|
||||
func NewBuffer() *bytes.Buffer {
|
||||
if ret := bufferPool.Get(); ret != nil {
|
||||
return ret.(*bytes.Buffer)
|
||||
} else {
|
||||
return bytes.NewBuffer(make([]byte, 0, option.DefaultEncoderBufferSize))
|
||||
}
|
||||
}
|
||||
|
||||
func FreeBytes(p *[]byte) {
|
||||
if rt.CanSizeResue(cap(*p)) {
|
||||
(*p) = (*p)[:0]
|
||||
bytesPool.Put(p)
|
||||
}
|
||||
}
|
||||
|
||||
func FreeStack(p *Stack) {
|
||||
p.sp = 0
|
||||
stackPool.Put(p)
|
||||
}
|
||||
|
||||
func FreeBuffer(p *bytes.Buffer) {
|
||||
if rt.CanSizeResue(cap(p.Bytes())) {
|
||||
p.Reset()
|
||||
bufferPool.Put(p)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
ArgPtrs = []bool{true, true, true, false}
|
||||
LocalPtrs = []bool{}
|
||||
|
||||
ArgPtrs_generic = []bool{true}
|
||||
LocalPtrs_generic = []bool{}
|
||||
)
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package encoder
|
||||
package vars
|
||||
|
||||
import (
|
||||
`encoding`
|
||||
@ -23,19 +23,19 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
byteType = reflect.TypeOf(byte(0))
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
jsonUnsupportedValueType = reflect.TypeOf(new(json.UnsupportedValueError))
|
||||
ByteType = reflect.TypeOf(byte(0))
|
||||
JsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
JsonUnsupportedValueType = reflect.TypeOf(new(json.UnsupportedValueError))
|
||||
)
|
||||
|
||||
var (
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
jsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
encodingTextMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
ErrorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
JsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
EncodingTextMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
func isSimpleByte(vt reflect.Type) bool {
|
||||
if vt.Kind() != byteType.Kind() {
|
||||
func IsSimpleByte(vt reflect.Type) bool {
|
||||
if vt.Kind() != ByteType.Kind() {
|
||||
return false
|
||||
} else {
|
||||
return !isEitherMarshaler(vt) && !isEitherMarshaler(reflect.PtrTo(vt))
|
||||
@ -43,5 +43,5 @@ func isSimpleByte(vt reflect.Type) bool {
|
||||
}
|
||||
|
||||
func isEitherMarshaler(vt reflect.Type) bool {
|
||||
return vt.Implements(jsonMarshalerType) || vt.Implements(encodingTextMarshalerType)
|
||||
return vt.Implements(JsonMarshalerType) || vt.Implements(EncodingTextMarshalerType)
|
||||
}
|
45
vendor/github.com/bytedance/sonic/internal/encoder/vm/stbus.go
generated
vendored
Normal file
45
vendor/github.com/bytedance/sonic/internal/encoder/vm/stbus.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright 2024 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 vm
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/alg"
|
||||
"github.com/bytedance/sonic/internal/encoder/ir"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
func EncodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error {
|
||||
if vt == nil {
|
||||
return alg.EncodeNil(buf)
|
||||
} else if pp, err := vars.FindOrCompile(vt, (fv&(1<<alg.BitPointerValue)) != 0, compiler); err != nil {
|
||||
return err
|
||||
} else if vt.Indirect() {
|
||||
return Execute(buf, *vp, sb, fv, pp.(*ir.Program))
|
||||
} else {
|
||||
return Execute(buf, unsafe.Pointer(vp), sb, fv, pp.(*ir.Program))
|
||||
}
|
||||
}
|
||||
|
||||
var compiler func(*rt.GoType, ... interface{}) (interface{}, error)
|
||||
|
||||
func SetCompiler(c func(*rt.GoType, ... interface{}) (interface{}, error)) {
|
||||
compiler = c
|
||||
}
|
374
vendor/github.com/bytedance/sonic/internal/encoder/vm/vm.go
generated
vendored
Normal file
374
vendor/github.com/bytedance/sonic/internal/encoder/vm/vm.go
generated
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
// Copyright 2024 CloudWeGo Authors
|
||||
//
|
||||
// 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 vm
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/alg"
|
||||
"github.com/bytedance/sonic/internal/encoder/ir"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/internal/base64"
|
||||
)
|
||||
|
||||
const (
|
||||
_S_cond = iota
|
||||
_S_init
|
||||
)
|
||||
|
||||
var (
|
||||
_T_json_Marshaler = rt.UnpackType(vars.JsonMarshalerType)
|
||||
_T_encoding_TextMarshaler = rt.UnpackType(vars.EncodingTextMarshalerType)
|
||||
)
|
||||
|
||||
func print_instr(buf []byte, pc int, op ir.Op, ins *ir.Instr, p unsafe.Pointer) {
|
||||
if len(buf) > 20 {
|
||||
fmt.Println(string(buf[len(buf)-20:]))
|
||||
} else {
|
||||
fmt.Println(string(buf))
|
||||
}
|
||||
fmt.Printf("pc %04d, op %v, ins %#v, ptr: %x\n", pc, op, ins.Disassemble(), p)
|
||||
}
|
||||
|
||||
func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.Program) (error) {
|
||||
pl := len(*prog)
|
||||
if pl <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf = *b
|
||||
var x int
|
||||
var q unsafe.Pointer
|
||||
var f uint64
|
||||
|
||||
var pro = &(*prog)[0]
|
||||
for pc := 0; pc < pl; {
|
||||
ins := (*ir.Instr)(rt.Add(unsafe.Pointer(pro), ir.OpSize*uintptr(pc)))
|
||||
pc++
|
||||
op := ins.Op()
|
||||
|
||||
switch op {
|
||||
case ir.OP_goto:
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
case ir.OP_byte:
|
||||
v := ins.Byte()
|
||||
buf = append(buf, v)
|
||||
case ir.OP_text:
|
||||
v := ins.Vs()
|
||||
buf = append(buf, v...)
|
||||
case ir.OP_deref:
|
||||
p = *(*unsafe.Pointer)(p)
|
||||
case ir.OP_index:
|
||||
p = rt.Add(p, uintptr(ins.I64()))
|
||||
case ir.OP_load:
|
||||
// NOTICE: load CANNOT change f!
|
||||
x, _, p, q = s.Load()
|
||||
case ir.OP_save:
|
||||
if !s.Save(x, f, p, q) {
|
||||
return vars.ERR_too_deep
|
||||
}
|
||||
case ir.OP_drop:
|
||||
x, f, p, q = s.Drop()
|
||||
case ir.OP_drop_2:
|
||||
s.Drop()
|
||||
x, f, p, q = s.Drop()
|
||||
case ir.OP_recurse:
|
||||
vt, pv := ins.Vp2()
|
||||
f := flags
|
||||
if pv {
|
||||
f |= (1 << alg.BitPointerValue)
|
||||
}
|
||||
*b = buf
|
||||
if vt.Indirect() {
|
||||
if err := EncodeTypedPointer(b, vt, (*unsafe.Pointer)(rt.NoEscape(unsafe.Pointer(&p))), s, f); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
vp := (*unsafe.Pointer)(p)
|
||||
if err := EncodeTypedPointer(b, vt, vp, s, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
buf = *b
|
||||
case ir.OP_is_nil:
|
||||
if is_nil(p) {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_is_nil_p1:
|
||||
if (*rt.GoEface)(p).Value == nil {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_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, 't', 'r', 'u', 'e')
|
||||
} else {
|
||||
buf = append(buf, 'f', 'a', 'l', 's', 'e')
|
||||
}
|
||||
case ir.OP_i8:
|
||||
v := *(*int8)(p)
|
||||
buf = alg.I64toa(buf, int64(v))
|
||||
case ir.OP_i16:
|
||||
v := *(*int16)(p)
|
||||
buf = alg.I64toa(buf, int64(v))
|
||||
case ir.OP_i32:
|
||||
v := *(*int32)(p)
|
||||
buf = alg.I64toa(buf, int64(v))
|
||||
case ir.OP_i64:
|
||||
v := *(*int64)(p)
|
||||
buf = alg.I64toa(buf, int64(v))
|
||||
case ir.OP_u8:
|
||||
v := *(*uint8)(p)
|
||||
buf = alg.U64toa(buf, uint64(v))
|
||||
case ir.OP_u16:
|
||||
v := *(*uint16)(p)
|
||||
buf = alg.U64toa(buf, uint64(v))
|
||||
case ir.OP_u32:
|
||||
v := *(*uint32)(p)
|
||||
buf = alg.U64toa(buf, uint64(v))
|
||||
case ir.OP_u64:
|
||||
v := *(*uint64)(p)
|
||||
buf = alg.U64toa(buf, uint64(v))
|
||||
case ir.OP_f32:
|
||||
v := *(*float32)(p)
|
||||
if math.IsNaN(float64(v)) || math.IsInf(float64(v), 0) {
|
||||
if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
|
||||
buf = append(buf, 'n', 'u', 'l', 'l')
|
||||
continue
|
||||
}
|
||||
return vars.ERR_nan_or_infinite
|
||||
}
|
||||
buf = alg.F32toa(buf, v)
|
||||
case ir.OP_f64:
|
||||
v := *(*float64)(p)
|
||||
if math.IsNaN(v) || math.IsInf(v, 0) {
|
||||
if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
|
||||
buf = append(buf, 'n', 'u', 'l', 'l')
|
||||
continue
|
||||
}
|
||||
return vars.ERR_nan_or_infinite
|
||||
}
|
||||
buf = alg.F64toa(buf, v)
|
||||
case ir.OP_bin:
|
||||
v := *(*[]byte)(p)
|
||||
buf = base64.EncodeBase64(buf, v)
|
||||
case ir.OP_quote:
|
||||
v := *(*string)(p)
|
||||
buf = alg.Quote(buf, v, true)
|
||||
case ir.OP_number:
|
||||
v := *(*json.Number)(p)
|
||||
if v == "" {
|
||||
buf = append(buf, '0')
|
||||
} else if !rt.IsValidNumber(string(v)) {
|
||||
return vars.Error_number(v)
|
||||
} else {
|
||||
buf = append(buf, v...)
|
||||
}
|
||||
case ir.OP_eface:
|
||||
*b = buf
|
||||
if err := EncodeTypedPointer(b, *(**rt.GoType)(p), (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
|
||||
return err
|
||||
}
|
||||
buf = *b
|
||||
case ir.OP_iface:
|
||||
*b = buf
|
||||
if err := EncodeTypedPointer(b, (*(**rt.GoItab)(p)).Vt, (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
|
||||
return err
|
||||
}
|
||||
buf = *b
|
||||
case ir.OP_is_zero_map:
|
||||
v := *(**rt.GoMap)(p)
|
||||
if v == nil || v.Count == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_map_iter:
|
||||
v := *(**rt.GoMap)(p)
|
||||
vt := ins.Vr()
|
||||
it, err := alg.IteratorStart(rt.MapType(vt), v, flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q = unsafe.Pointer(it)
|
||||
case ir.OP_map_stop:
|
||||
it := (*alg.MapIterator)(q)
|
||||
alg.IteratorStop(it)
|
||||
q = nil
|
||||
case ir.OP_map_value_next:
|
||||
it := (*alg.MapIterator)(q)
|
||||
p = it.It.V
|
||||
alg.IteratorNext(it)
|
||||
case ir.OP_map_check_key:
|
||||
it := (*alg.MapIterator)(q)
|
||||
if it.It.K == nil {
|
||||
pc = ins.Vi()
|
||||
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)
|
||||
buf = alg.Quote(buf, v, false)
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_slice_len:
|
||||
v := (*rt.GoSlice)(p)
|
||||
x = v.Len
|
||||
p = v.Ptr
|
||||
//TODO: why?
|
||||
f |= 1<<_S_init
|
||||
case ir.OP_slice_next:
|
||||
if x == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
x--
|
||||
if has_opts(f, _S_init) {
|
||||
f &= ^uint64(1 << _S_init)
|
||||
} else {
|
||||
p = rt.Add(p, uintptr(ins.Vlen()))
|
||||
}
|
||||
case ir.OP_cond_set:
|
||||
f |= 1<<_S_cond
|
||||
case ir.OP_cond_testc:
|
||||
if has_opts(f, _S_cond) {
|
||||
f &= ^uint64(1 << _S_cond)
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_is_zero_1:
|
||||
if *(*uint8)(p) == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_is_zero_2:
|
||||
if *(*uint16)(p) == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_is_zero_4:
|
||||
if *(*uint32)(p) == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_is_zero_8:
|
||||
if *(*uint64)(p) == 0 {
|
||||
pc = ins.Vi()
|
||||
continue
|
||||
}
|
||||
case ir.OP_empty_arr:
|
||||
if has_opts(flags, alg.BitNoNullSliceOrMap) {
|
||||
buf = append(buf, '[', ']')
|
||||
} else {
|
||||
buf = append(buf, 'n', 'u', 'l', 'l')
|
||||
}
|
||||
case ir.OP_empty_obj:
|
||||
if has_opts(flags, alg.BitNoNullSliceOrMap) {
|
||||
buf = append(buf, '{', '}')
|
||||
} else {
|
||||
buf = append(buf, 'n', 'u', 'l', 'l')
|
||||
}
|
||||
case ir.OP_marshal:
|
||||
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_json_Marshaler, *(*rt.GoIface)(p))
|
||||
case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
|
||||
default : it = convT2I(p, !vt.Indirect(), itab)
|
||||
}
|
||||
if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
|
||||
return err
|
||||
}
|
||||
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:
|
||||
panic(fmt.Sprintf("not implement %s at %d", ins.Op().String(), pc))
|
||||
}
|
||||
}
|
||||
|
||||
*b = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
// func to_buf(w unsafe.Pointer, l int, c int) []byte {
|
||||
// return rt.BytesFrom(unsafe.Pointer(uintptr(w)-uintptr(l)), l, c)
|
||||
// }
|
||||
|
||||
// func from_buf(buf []byte) (unsafe.Pointer, int, int) {
|
||||
// return rt.IndexByte(buf, len(buf)), len(buf), cap(buf)
|
||||
// }
|
||||
|
||||
func has_opts(opts uint64, bit int) bool {
|
||||
return opts & (1<<bit) != 0
|
||||
}
|
||||
|
||||
func is_nil(p unsafe.Pointer) bool {
|
||||
return *(*unsafe.Pointer)(p) == nil
|
||||
}
|
||||
|
||||
func convT2I(ptr unsafe.Pointer, deref bool, itab *rt.GoItab) (rt.GoIface) {
|
||||
if deref {
|
||||
ptr = *(*unsafe.Pointer)(ptr)
|
||||
}
|
||||
return rt.GoIface{
|
||||
Itab: itab,
|
||||
Value: ptr,
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
//go:build go1.17 && !go1.21
|
||||
// +build go1.17,!go1.21
|
||||
|
||||
// Copyright 2023 CloudWeGo Authors
|
||||
@ -14,24 +15,25 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoder
|
||||
package x86
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
`unsafe`
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
"github.com/bytedance/sonic/internal/jit"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"github.com/twitchyliquid64/golang-asm/obj/x86"
|
||||
)
|
||||
|
||||
var (
|
||||
_V_writeBarrier = jit.Imm(int64(uintptr(unsafe.Pointer(&_runtime_writeBarrier))))
|
||||
_V_writeBarrier = jit.Imm(int64(uintptr(unsafe.Pointer(&rt.RuntimeWriteBarrier))))
|
||||
|
||||
_F_gcWriteBarrierAX = jit.Func(gcWriteBarrierAX)
|
||||
_F_gcWriteBarrierAX = jit.Func(rt.GcWriteBarrierAX)
|
||||
)
|
||||
|
||||
func (self *_Assembler) WritePtr(i int, ptr obj.Addr, rec obj.Addr) {
|
||||
func (self *Assembler) WritePtr(i int, ptr obj.Addr, rec obj.Addr) {
|
||||
if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
|
||||
panic("rec contains AX!")
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// +build go1.21,!go1.23
|
||||
//go:build go1.21 && !go1.24
|
||||
// +build go1.21,!go1.24
|
||||
|
||||
// Copyright 2023 CloudWeGo Authors
|
||||
//
|
||||
@ -14,24 +15,25 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package encoder
|
||||
package x86
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
`unsafe`
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
"github.com/bytedance/sonic/internal/jit"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"github.com/twitchyliquid64/golang-asm/obj/x86"
|
||||
)
|
||||
|
||||
var (
|
||||
_V_writeBarrier = jit.Imm(int64(uintptr(unsafe.Pointer(&_runtime_writeBarrier))))
|
||||
_V_writeBarrier = jit.Imm(int64(uintptr(unsafe.Pointer(&rt.RuntimeWriteBarrier))))
|
||||
|
||||
_F_gcWriteBarrier2 = jit.Func(gcWriteBarrier2)
|
||||
_F_gcWriteBarrier2 = jit.Func(rt.GcWriteBarrier2)
|
||||
)
|
||||
|
||||
func (self *_Assembler) WritePtr(i int, ptr obj.Addr, old obj.Addr) {
|
||||
func (self *Assembler) WritePtr(i int, ptr obj.Addr, old obj.Addr) {
|
||||
if old.Reg == x86.REG_AX || old.Index == x86.REG_AX {
|
||||
panic("rec contains AX!")
|
||||
}
|
1195
vendor/github.com/bytedance/sonic/internal/encoder/x86/assembler_regabi_amd64.go
generated
vendored
Normal file
1195
vendor/github.com/bytedance/sonic/internal/encoder/x86/assembler_regabi_amd64.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
// +build go1.16,!go1.17
|
||||
// +build go1.17,!go1.17
|
||||
|
||||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package encoder
|
||||
package x86
|
||||
|
||||
import (
|
||||
`os`
|
201
vendor/github.com/bytedance/sonic/internal/encoder/x86/debug_go117.go
generated
vendored
Normal file
201
vendor/github.com/bytedance/sonic/internal/encoder/x86/debug_go117.go
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
//go:build go1.17 && !go1.24
|
||||
// +build go1.17,!go1.24
|
||||
|
||||
/*
|
||||
* 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 x86
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/ir"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/jit"
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
)
|
||||
|
||||
const _FP_debug = 128
|
||||
|
||||
var (
|
||||
_Instr_End = ir.NewInsOp(ir.OP_is_nil)
|
||||
|
||||
_F_gc = jit.Func(gc)
|
||||
_F_println = jit.Func(println_wrapper)
|
||||
_F_print = jit.Func(print)
|
||||
)
|
||||
|
||||
func (self *Assembler) dsave(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _FP_debug/8-1 {
|
||||
panic("too many registers to save")
|
||||
} else {
|
||||
self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Assembler) dload(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _FP_debug/8-1 {
|
||||
panic("too many registers to load")
|
||||
} else {
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func println_wrapper(i int, op1 int, op2 int) {
|
||||
println(i, " Intrs ", op1, ir.OpNames[op1], "next: ", op2, ir.OpNames[op2])
|
||||
}
|
||||
|
||||
func print(i int) {
|
||||
println(i)
|
||||
}
|
||||
|
||||
func gc() {
|
||||
if !vars.DebugSyncGC {
|
||||
return
|
||||
}
|
||||
runtime.GC()
|
||||
// debug.FreeOSMemory()
|
||||
}
|
||||
|
||||
func (self *Assembler) dcall(fn obj.Addr) {
|
||||
self.Emit("MOVQ", fn, _R10) // MOVQ ${fn}, R10
|
||||
self.Rjmp("CALL", _R10) // CALL R10
|
||||
}
|
||||
|
||||
func (self *Assembler) debug_gc() {
|
||||
if !vars.DebugSyncGC {
|
||||
return
|
||||
}
|
||||
self.dsave(_REG_debug...)
|
||||
self.dcall(_F_gc)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
||||
|
||||
func (self *Assembler) debug_instr(i int, v *ir.Instr) {
|
||||
if vars.DebugSyncGC {
|
||||
if i+1 == len(self.p) {
|
||||
self.print_gc(i, v, &_Instr_End)
|
||||
} else {
|
||||
next := &(self.p[i+1])
|
||||
self.print_gc(i, v, next)
|
||||
name := ir.OpNames[next.Op()]
|
||||
if strings.Contains(name, "save") {
|
||||
return
|
||||
}
|
||||
}
|
||||
// self.debug_gc()
|
||||
}
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
//go:linkname checkptrBase runtime.checkptrBase
|
||||
func checkptrBase(p unsafe.Pointer) uintptr
|
||||
|
||||
//go:noescape
|
||||
//go:linkname findObject runtime.findObject
|
||||
func findObject(p, refBase, refOff uintptr) (base uintptr, s unsafe.Pointer, objIndex uintptr)
|
||||
|
||||
var (
|
||||
_F_checkptr = jit.Func(checkptr)
|
||||
_F_printptr = jit.Func(printptr)
|
||||
)
|
||||
|
||||
var (
|
||||
_R10 = jit.Reg("R10")
|
||||
)
|
||||
var _REG_debug = []obj.Addr{
|
||||
jit.Reg("AX"),
|
||||
jit.Reg("BX"),
|
||||
jit.Reg("CX"),
|
||||
jit.Reg("DX"),
|
||||
jit.Reg("DI"),
|
||||
jit.Reg("SI"),
|
||||
jit.Reg("BP"),
|
||||
jit.Reg("SP"),
|
||||
jit.Reg("R8"),
|
||||
jit.Reg("R9"),
|
||||
jit.Reg("R10"),
|
||||
jit.Reg("R11"),
|
||||
jit.Reg("R12"),
|
||||
jit.Reg("R13"),
|
||||
jit.Reg("R14"),
|
||||
jit.Reg("R15"),
|
||||
}
|
||||
|
||||
func checkptr(ptr uintptr) {
|
||||
if ptr == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Printf("pointer: %x\n", ptr)
|
||||
f := checkptrBase(unsafe.Pointer(uintptr(ptr)))
|
||||
if f == 0 {
|
||||
fmt.Printf("! unknown-based pointer: %x\n", ptr)
|
||||
} else if f == 1 {
|
||||
fmt.Printf("! stack pointer: %x\n", ptr)
|
||||
} else {
|
||||
fmt.Printf("base: %x\n", f)
|
||||
}
|
||||
findobj(ptr)
|
||||
}
|
||||
|
||||
func findobj(ptr uintptr) {
|
||||
base, s, objIndex := findObject(ptr, 0, 0)
|
||||
if s != nil && base == 0 {
|
||||
fmt.Printf("! invalid pointer: %x\n", ptr)
|
||||
}
|
||||
fmt.Printf("objIndex: %d\n", objIndex)
|
||||
}
|
||||
|
||||
func (self *Assembler) check_ptr(ptr obj.Addr, lea bool) {
|
||||
if !vars.DebugCheckPtr {
|
||||
return
|
||||
}
|
||||
|
||||
self.dsave(_REG_debug...)
|
||||
if lea {
|
||||
self.Emit("LEAQ", ptr, _R10)
|
||||
} else {
|
||||
self.Emit("MOVQ", ptr, _R10)
|
||||
}
|
||||
self.Emit("MOVQ", _R10, jit.Ptr(_SP, 0))
|
||||
self.dcall(_F_checkptr)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
||||
|
||||
func printptr(i int, ptr uintptr) {
|
||||
fmt.Printf("[%d] ptr: %x\n", i, ptr)
|
||||
}
|
||||
|
||||
func (self *Assembler) print_ptr(i int, ptr obj.Addr, lea bool) {
|
||||
self.dsave(_REG_debug...)
|
||||
if lea {
|
||||
self.Emit("LEAQ", ptr, _R10)
|
||||
} else {
|
||||
self.Emit("MOVQ", ptr, _R10)
|
||||
}
|
||||
|
||||
self.Emit("MOVQ", jit.Imm(int64(i)), _AX)
|
||||
self.Emit("MOVQ", _R10, _BX)
|
||||
self.dcall(_F_printptr)
|
||||
self.dload(_REG_debug...)
|
||||
}
|
54
vendor/github.com/bytedance/sonic/internal/encoder/x86/stbus.go
generated
vendored
Normal file
54
vendor/github.com/bytedance/sonic/internal/encoder/x86/stbus.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright 2024 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 x86
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/alg"
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/bytedance/sonic/loader"
|
||||
_ "github.com/cloudwego/base64x"
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/cloudwego/base64x._subr__b64encode
|
||||
var _subr__b64encode uintptr
|
||||
|
||||
var compiler func(*rt.GoType, ... interface{}) (interface{}, error)
|
||||
|
||||
func SetCompiler(c func(*rt.GoType, ... interface{}) (interface{}, error)) {
|
||||
compiler = c
|
||||
}
|
||||
|
||||
func ptoenc(p loader.Function) vars.Encoder {
|
||||
return *(*vars.Encoder)(unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
func EncodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error {
|
||||
if vt == nil {
|
||||
return alg.EncodeNil(buf)
|
||||
} else if fn, err := vars.FindOrCompile(vt, (fv&(1<<alg.BitPointerValue)) != 0, compiler); err != nil {
|
||||
return err
|
||||
} else if vt.Indirect() {
|
||||
return fn.(vars.Encoder)(buf, *vp, sb, fv)
|
||||
} else {
|
||||
return fn.(vars.Encoder)(buf, unsafe.Pointer(vp), sb, fv)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user