mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-01 21:12:25 -05:00
[chore]: Bump github.com/gin-gonic/gin from 1.9.0 to 1.9.1 (#1855)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
23705b31e4
commit
55aacaf4b0
138 changed files with 27543 additions and 25484 deletions
0
vendor/github.com/bytedance/sonic/internal/decoder/asm.s
generated
vendored
Normal file
0
vendor/github.com/bytedance/sonic/internal/decoder/asm.s
generated
vendored
Normal file
2013
vendor/github.com/bytedance/sonic/internal/decoder/assembler_amd64_go116.go
generated
vendored
Normal file
2013
vendor/github.com/bytedance/sonic/internal/decoder/assembler_amd64_go116.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1992
vendor/github.com/bytedance/sonic/internal/decoder/assembler_amd64_go117.go
generated
vendored
Normal file
1992
vendor/github.com/bytedance/sonic/internal/decoder/assembler_amd64_go117.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1155
vendor/github.com/bytedance/sonic/internal/decoder/compiler.go
generated
vendored
Normal file
1155
vendor/github.com/bytedance/sonic/internal/decoder/compiler.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
70
vendor/github.com/bytedance/sonic/internal/decoder/debug.go
generated
vendored
Normal file
70
vendor/github.com/bytedance/sonic/internal/decoder/debug.go
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`os`
|
||||
`runtime`
|
||||
`runtime/debug`
|
||||
`strings`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
)
|
||||
|
||||
|
||||
var (
|
||||
debugSyncGC = os.Getenv("SONIC_SYNC_GC") != ""
|
||||
debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
|
||||
)
|
||||
|
||||
var (
|
||||
_Instr_End _Instr = newInsOp(_OP_nil_1)
|
||||
|
||||
_F_gc = jit.Func(runtime.GC)
|
||||
_F_force_gc = jit.Func(debug.FreeOSMemory)
|
||||
_F_println = jit.Func(println_wrapper)
|
||||
_F_print = jit.Func(print)
|
||||
)
|
||||
|
||||
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 (self *_Assembler) force_gc() {
|
||||
self.call_go(_F_gc)
|
||||
self.call_go(_F_force_gc)
|
||||
}
|
||||
|
||||
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.force_gc()
|
||||
}
|
||||
}
|
||||
255
vendor/github.com/bytedance/sonic/internal/decoder/decoder.go
generated
vendored
Normal file
255
vendor/github.com/bytedance/sonic/internal/decoder/decoder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
`encoding/json`
|
||||
`reflect`
|
||||
`runtime`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/bytedance/sonic/option`
|
||||
`github.com/bytedance/sonic/utf8`
|
||||
)
|
||||
|
||||
const (
|
||||
_F_use_int64 = iota
|
||||
_F_use_number
|
||||
_F_disable_urc
|
||||
_F_disable_unknown
|
||||
_F_copy_string
|
||||
_F_validate_string
|
||||
|
||||
_F_allow_control = 31
|
||||
)
|
||||
|
||||
type Options uint64
|
||||
|
||||
const (
|
||||
OptionUseInt64 Options = 1 << _F_use_int64
|
||||
OptionUseNumber Options = 1 << _F_use_number
|
||||
OptionUseUnicodeErrors Options = 1 << _F_disable_urc
|
||||
OptionDisableUnknown Options = 1 << _F_disable_unknown
|
||||
OptionCopyString Options = 1 << _F_copy_string
|
||||
OptionValidateString Options = 1 << _F_validate_string
|
||||
)
|
||||
|
||||
func (self *Decoder) SetOptions(opts Options) {
|
||||
if (opts & OptionUseNumber != 0) && (opts & OptionUseInt64 != 0) {
|
||||
panic("can't set OptionUseInt64 and OptionUseNumber both!")
|
||||
}
|
||||
self.f = uint64(opts)
|
||||
}
|
||||
|
||||
|
||||
// Decoder is the decoder context object
|
||||
type Decoder struct {
|
||||
i int
|
||||
f uint64
|
||||
s string
|
||||
}
|
||||
|
||||
// NewDecoder creates a new decoder instance.
|
||||
func NewDecoder(s string) *Decoder {
|
||||
return &Decoder{s: s}
|
||||
}
|
||||
|
||||
// Pos returns the current decoding position.
|
||||
func (self *Decoder) Pos() int {
|
||||
return self.i
|
||||
}
|
||||
|
||||
func (self *Decoder) Reset(s string) {
|
||||
self.s = s
|
||||
self.i = 0
|
||||
// self.f = 0
|
||||
}
|
||||
|
||||
func (self *Decoder) CheckTrailings() error {
|
||||
pos := self.i
|
||||
buf := self.s
|
||||
/* skip all the trailing spaces */
|
||||
if pos != len(buf) {
|
||||
for pos < len(buf) && (types.SPACE_MASK & (1 << buf[pos])) != 0 {
|
||||
pos++
|
||||
}
|
||||
}
|
||||
|
||||
/* then it must be at EOF */
|
||||
if pos == len(buf) {
|
||||
return nil
|
||||
}
|
||||
|
||||
/* junk after JSON value */
|
||||
return SyntaxError {
|
||||
Src : buf,
|
||||
Pos : pos,
|
||||
Code : types.ERR_INVALID_CHAR,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Decode parses the JSON-encoded data from current position and stores the result
|
||||
// in the value pointed to by val.
|
||||
func (self *Decoder) Decode(val interface{}) error {
|
||||
/* validate json if needed */
|
||||
if (self.f & (1 << _F_validate_string)) != 0 && !utf8.ValidateString(self.s){
|
||||
dbuf := utf8.CorrectWith(nil, rt.Str2Mem(self.s), "\ufffd")
|
||||
self.s = rt.Mem2Str(dbuf)
|
||||
}
|
||||
|
||||
vv := rt.UnpackEface(val)
|
||||
vp := vv.Value
|
||||
|
||||
/* check for nil type */
|
||||
if vv.Type == nil {
|
||||
return &json.InvalidUnmarshalError{}
|
||||
}
|
||||
|
||||
/* must be a non-nil pointer */
|
||||
if vp == nil || vv.Type.Kind() != reflect.Ptr {
|
||||
return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
|
||||
}
|
||||
|
||||
etp := rt.PtrElem(vv.Type)
|
||||
|
||||
/* check the defined pointer type for issue 379 */
|
||||
if vv.Type.IsNamed() {
|
||||
newp := vp
|
||||
etp = vv.Type
|
||||
vp = unsafe.Pointer(&newp)
|
||||
}
|
||||
|
||||
/* create a new stack, and call the decoder */
|
||||
sb := newStack()
|
||||
nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)
|
||||
/* return the stack back */
|
||||
self.i = nb
|
||||
freeStack(sb)
|
||||
|
||||
/* avoid GC ahead */
|
||||
runtime.KeepAlive(vv)
|
||||
return err
|
||||
}
|
||||
|
||||
// UseInt64 indicates the Decoder to unmarshal an integer into an interface{} as an
|
||||
// int64 instead of as a float64.
|
||||
func (self *Decoder) UseInt64() {
|
||||
self.f |= 1 << _F_use_int64
|
||||
self.f &^= 1 << _F_use_number
|
||||
}
|
||||
|
||||
// UseNumber indicates the Decoder to unmarshal a number into an interface{} as a
|
||||
// json.Number instead of as a float64.
|
||||
func (self *Decoder) UseNumber() {
|
||||
self.f &^= 1 << _F_use_int64
|
||||
self.f |= 1 << _F_use_number
|
||||
}
|
||||
|
||||
// UseUnicodeErrors indicates the Decoder to return an error when encounter invalid
|
||||
// UTF-8 escape sequences.
|
||||
func (self *Decoder) UseUnicodeErrors() {
|
||||
self.f |= 1 << _F_disable_urc
|
||||
}
|
||||
|
||||
// DisallowUnknownFields indicates the Decoder to return an error when the destination
|
||||
// is a struct and the input contains object keys which do not match any
|
||||
// non-ignored, exported fields in the destination.
|
||||
func (self *Decoder) DisallowUnknownFields() {
|
||||
self.f |= 1 << _F_disable_unknown
|
||||
}
|
||||
|
||||
// CopyString indicates the Decoder to decode string values by copying instead of referring.
|
||||
func (self *Decoder) CopyString() {
|
||||
self.f |= 1 << _F_copy_string
|
||||
}
|
||||
|
||||
// ValidateString causes the Decoder to validate string values when decoding string value
|
||||
// in JSON. Validation is that, returning error when unescaped control chars(0x00-0x1f) or
|
||||
// invalid UTF-8 chars in the string value of JSON.
|
||||
func (self *Decoder) ValidateString() {
|
||||
self.f |= 1 << _F_validate_string
|
||||
}
|
||||
|
||||
// Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
|
||||
// order to reduce the first-hit latency.
|
||||
//
|
||||
// Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
|
||||
// a compile option to set the depth of recursive compile for the nested struct type.
|
||||
func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
|
||||
cfg := option.DefaultCompileOptions()
|
||||
for _, opt := range opts {
|
||||
opt(&cfg)
|
||||
}
|
||||
return pretouchRec(map[reflect.Type]bool{vt:true}, cfg)
|
||||
}
|
||||
|
||||
func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
|
||||
/* compile function */
|
||||
compiler := newCompiler().apply(opts)
|
||||
decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
|
||||
if pp, err := compiler.compile(_vt); 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, decoder); err == nil {
|
||||
return compiler.rec, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {
|
||||
if opts.RecursiveDepth < 0 || len(vtm) == 0 {
|
||||
return nil
|
||||
}
|
||||
next := make(map[reflect.Type]bool)
|
||||
for vt := range(vtm) {
|
||||
sub, err := pretouchType(vt, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for svt := range(sub) {
|
||||
next[svt] = true
|
||||
}
|
||||
}
|
||||
opts.RecursiveDepth -= 1
|
||||
return pretouchRec(next, opts)
|
||||
}
|
||||
|
||||
// Skip skips only one json value, and returns first non-blank character position and its ending position if it is valid.
|
||||
// Otherwise, returns negative error code using start and invalid character position using end
|
||||
func Skip(data []byte) (start int, end int) {
|
||||
s := rt.Mem2Str(data)
|
||||
p := 0
|
||||
m := types.NewStateMachine()
|
||||
ret := native.SkipOne(&s, &p, m, uint64(0))
|
||||
types.FreeStateMachine(m)
|
||||
return ret, p
|
||||
}
|
||||
181
vendor/github.com/bytedance/sonic/internal/decoder/errors.go
generated
vendored
Normal file
181
vendor/github.com/bytedance/sonic/internal/decoder/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`errors`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`strings`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
type SyntaxError struct {
|
||||
Pos int
|
||||
Src string
|
||||
Code types.ParsingError
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (self SyntaxError) Error() string {
|
||||
return fmt.Sprintf("%q", self.Description())
|
||||
}
|
||||
|
||||
func (self SyntaxError) Description() string {
|
||||
return "Syntax error " + self.description()
|
||||
}
|
||||
|
||||
func (self SyntaxError) description() string {
|
||||
i := 16
|
||||
p := self.Pos - i
|
||||
q := self.Pos + i
|
||||
|
||||
/* check for empty source */
|
||||
if self.Src == "" {
|
||||
return fmt.Sprintf("no sources available: %#v", self)
|
||||
}
|
||||
|
||||
/* prevent slicing before the beginning */
|
||||
if p < 0 {
|
||||
p, q, i = 0, q - p, i + p
|
||||
}
|
||||
|
||||
/* prevent slicing beyond the end */
|
||||
if n := len(self.Src); q > n {
|
||||
n = q - n
|
||||
q = len(self.Src)
|
||||
|
||||
/* move the left bound if possible */
|
||||
if p > n {
|
||||
i += n
|
||||
p -= n
|
||||
}
|
||||
}
|
||||
|
||||
/* left and right length */
|
||||
x := clamp_zero(i)
|
||||
y := clamp_zero(q - p - i - 1)
|
||||
|
||||
/* compose the error description */
|
||||
return fmt.Sprintf(
|
||||
"at index %d: %s\n\n\t%s\n\t%s^%s\n",
|
||||
self.Pos,
|
||||
self.Message(),
|
||||
self.Src[p:q],
|
||||
strings.Repeat(".", x),
|
||||
strings.Repeat(".", y),
|
||||
)
|
||||
}
|
||||
|
||||
func (self SyntaxError) Message() string {
|
||||
if self.Msg == "" {
|
||||
return self.Code.Message()
|
||||
}
|
||||
return self.Msg
|
||||
}
|
||||
|
||||
func clamp_zero(v int) int {
|
||||
if v < 0 {
|
||||
return 0
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
/** JIT Error Helpers **/
|
||||
|
||||
var stackOverflow = &json.UnsupportedValueError {
|
||||
Str : "Value nesting too deep",
|
||||
Value : reflect.ValueOf("..."),
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_wrap(src string, pos int, code types.ParsingError) error {
|
||||
return SyntaxError {
|
||||
Pos : pos,
|
||||
Src : src,
|
||||
Code : code,
|
||||
}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_type(vt *rt.GoType) error {
|
||||
return &json.UnmarshalTypeError{Type: vt.Pack()}
|
||||
}
|
||||
|
||||
type MismatchTypeError struct {
|
||||
Pos int
|
||||
Src string
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
func swithchJSONType (src string, pos int) string {
|
||||
var val string
|
||||
switch src[pos] {
|
||||
case 'f': fallthrough
|
||||
case 't': val = "bool"
|
||||
case '"': val = "string"
|
||||
case '{': val = "object"
|
||||
case '[': val = "array"
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': val = "number"
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (self MismatchTypeError) Error() string {
|
||||
se := SyntaxError {
|
||||
Pos : self.Pos,
|
||||
Src : self.Src,
|
||||
Code : types.ERR_MISMATCH,
|
||||
}
|
||||
return fmt.Sprintf("Mismatch type %s with value %s %q", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
|
||||
}
|
||||
|
||||
func (self MismatchTypeError) Description() string {
|
||||
se := SyntaxError {
|
||||
Pos : self.Pos,
|
||||
Src : self.Src,
|
||||
Code : types.ERR_MISMATCH,
|
||||
}
|
||||
return fmt.Sprintf("Mismatch type %s with value %s %s", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_mismatch(src string, pos int, vt *rt.GoType) error {
|
||||
return &MismatchTypeError {
|
||||
Pos : pos,
|
||||
Src : src,
|
||||
Type : vt.Pack(),
|
||||
}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_field(name string) error {
|
||||
return errors.New("json: unknown field " + strconv.Quote(name))
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_value(value string, vtype reflect.Type) error {
|
||||
return &json.UnmarshalTypeError {
|
||||
Type : vtype,
|
||||
Value : value,
|
||||
}
|
||||
}
|
||||
776
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go116.go
generated
vendored
Normal file
776
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go116.go
generated
vendored
Normal file
|
|
@ -0,0 +1,776 @@
|
|||
// +build go1.15,!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 decoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
)
|
||||
|
||||
/** Crucial Registers:
|
||||
*
|
||||
* ST(BX) : ro, decoder stack
|
||||
* DF(R10) : ro, decoder flags
|
||||
* EP(R11) : wo, error pointer
|
||||
* IP(R12) : ro, input pointer
|
||||
* IL(R13) : ro, input length
|
||||
* IC(R14) : rw, input cursor
|
||||
* VP(R15) : ro, value pointer (to an interface{})
|
||||
*/
|
||||
|
||||
const (
|
||||
_VD_args = 8 // 8 bytes for passing arguments to this functions
|
||||
_VD_fargs = 64 // 64 bytes for passing arguments to other Go functions
|
||||
_VD_saves = 40 // 40 bytes for saving the registers before CALL instructions
|
||||
_VD_locals = 88 // 88 bytes for local variables
|
||||
)
|
||||
|
||||
const (
|
||||
_VD_offs = _VD_fargs + _VD_saves + _VD_locals
|
||||
_VD_size = _VD_offs + 8 // 8 bytes for the parent frame pointer
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_ss = _VAR_ss_Vt
|
||||
_VAR_df = jit.Ptr(_SP, _VD_fargs + _VD_saves)
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_ss_Vt = jit.Ptr(_SP, _VD_fargs + _VD_saves + 8)
|
||||
_VAR_ss_Dv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 16)
|
||||
_VAR_ss_Iv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 24)
|
||||
_VAR_ss_Ep = jit.Ptr(_SP, _VD_fargs + _VD_saves + 32)
|
||||
_VAR_ss_Db = jit.Ptr(_SP, _VD_fargs + _VD_saves + 40)
|
||||
_VAR_ss_Dc = jit.Ptr(_SP, _VD_fargs + _VD_saves + 48)
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_cs_LR = jit.Ptr(_SP, _VD_fargs + _VD_saves + 56)
|
||||
_VAR_cs_p = jit.Ptr(_SP, _VD_fargs + _VD_saves + 64)
|
||||
_VAR_cs_n = jit.Ptr(_SP, _VD_fargs + _VD_saves + 72)
|
||||
_VAR_cs_d = jit.Ptr(_SP, _VD_fargs + _VD_saves + 80)
|
||||
)
|
||||
|
||||
type _ValueDecoder struct {
|
||||
jit.BaseAssembler
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) build() uintptr {
|
||||
self.Init(self.compile)
|
||||
return *(*uintptr)(self.Load("decode_value", _VD_size, _VD_args, argPtrs_generic, localPtrs_generic))
|
||||
}
|
||||
|
||||
/** Function Calling Helpers **/
|
||||
|
||||
func (self *_ValueDecoder) save(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _VD_saves / 8 - 1 {
|
||||
panic("too many registers to save")
|
||||
} else {
|
||||
self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) load(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _VD_saves / 8 - 1 {
|
||||
panic("too many registers to load")
|
||||
} else {
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) call(fn obj.Addr) {
|
||||
self.Emit("MOVQ", fn, _AX) // MOVQ ${fn}, AX
|
||||
self.Rjmp("CALL", _AX) // CALL AX
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) call_go(fn obj.Addr) {
|
||||
self.save(_REG_go...) // SAVE $REG_go
|
||||
self.call(fn) // CALL ${fn}
|
||||
self.load(_REG_go...) // LOAD $REG_go
|
||||
}
|
||||
|
||||
/** Decoder Assembler **/
|
||||
|
||||
const (
|
||||
_S_val = iota + 1
|
||||
_S_arr
|
||||
_S_arr_0
|
||||
_S_obj
|
||||
_S_obj_0
|
||||
_S_obj_delim
|
||||
_S_obj_sep
|
||||
)
|
||||
|
||||
const (
|
||||
_S_omask_key = (1 << _S_obj_0) | (1 << _S_obj_sep)
|
||||
_S_omask_end = (1 << _S_obj_0) | (1 << _S_obj)
|
||||
_S_vmask = (1 << _S_val) | (1 << _S_arr_0)
|
||||
)
|
||||
|
||||
const (
|
||||
_A_init_len = 1
|
||||
_A_init_cap = 16
|
||||
)
|
||||
|
||||
const (
|
||||
_ST_Sp = 0
|
||||
_ST_Vt = _PtrBytes
|
||||
_ST_Vp = _PtrBytes * (types.MAX_RECURSE + 1)
|
||||
)
|
||||
|
||||
var (
|
||||
_V_true = jit.Imm(int64(pbool(true)))
|
||||
_V_false = jit.Imm(int64(pbool(false)))
|
||||
_F_value = jit.Imm(int64(native.S_value))
|
||||
)
|
||||
|
||||
var (
|
||||
_V_max = jit.Imm(int64(types.V_MAX))
|
||||
_E_eof = jit.Imm(int64(types.ERR_EOF))
|
||||
_E_invalid = jit.Imm(int64(types.ERR_INVALID_CHAR))
|
||||
_E_recurse = jit.Imm(int64(types.ERR_RECURSE_EXCEED_MAX))
|
||||
)
|
||||
|
||||
var (
|
||||
_F_convTslice = jit.Func(convTslice)
|
||||
_F_convTstring = jit.Func(convTstring)
|
||||
_F_invalid_vtype = jit.Func(invalid_vtype)
|
||||
)
|
||||
|
||||
var (
|
||||
_T_map = jit.Type(reflect.TypeOf((map[string]interface{})(nil)))
|
||||
_T_bool = jit.Type(reflect.TypeOf(false))
|
||||
_T_int64 = jit.Type(reflect.TypeOf(int64(0)))
|
||||
_T_eface = jit.Type(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
_T_slice = jit.Type(reflect.TypeOf(([]interface{})(nil)))
|
||||
_T_string = jit.Type(reflect.TypeOf(""))
|
||||
_T_number = jit.Type(reflect.TypeOf(json.Number("")))
|
||||
_T_float64 = jit.Type(reflect.TypeOf(float64(0)))
|
||||
)
|
||||
|
||||
var _R_tab = map[int]string {
|
||||
'[': "_decode_V_ARRAY",
|
||||
'{': "_decode_V_OBJECT",
|
||||
':': "_decode_V_KEY_SEP",
|
||||
',': "_decode_V_ELEM_SEP",
|
||||
']': "_decode_V_ARRAY_END",
|
||||
'}': "_decode_V_OBJECT_END",
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) compile() {
|
||||
self.Emit("SUBQ", jit.Imm(_VD_size), _SP) // SUBQ $_VD_size, SP
|
||||
self.Emit("MOVQ", _BP, jit.Ptr(_SP, _VD_offs)) // MOVQ BP, _VD_offs(SP)
|
||||
self.Emit("LEAQ", jit.Ptr(_SP, _VD_offs), _BP) // LEAQ _VD_offs(SP), BP
|
||||
|
||||
/* initialize the state machine */
|
||||
self.Emit("XORL", _CX, _CX) // XORL CX, CX
|
||||
self.Emit("MOVQ", _DF, _VAR_df) // MOVQ DF, df
|
||||
/* initialize digital buffer first */
|
||||
self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_ss_Dc) // MOVQ $_MaxDigitNums, ss.Dcap
|
||||
self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX
|
||||
self.Emit("MOVQ", _AX, _VAR_ss_Db) // MOVQ AX, ss.Dbuf
|
||||
/* add ST offset */
|
||||
self.Emit("ADDQ", jit.Imm(_FsmOffset), _ST) // ADDQ _FsmOffset, _ST
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WriteRecNotAX(0, _VP, jit.Ptr(_ST, _ST_Vp), false) // MOVQ VP, ST.Vp[0]
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Ptr(_ST, _ST_Vt)) // MOVQ _S_val, ST.Vt[0]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* set the value from previous round */
|
||||
self.Link("_set_value") // _set_value:
|
||||
self.Emit("MOVL" , jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_vtype_error") // JNC _vtype_error
|
||||
self.Emit("XORL" , _SI, _SI) // XORL SI, SI
|
||||
self.Emit("SUBQ" , jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("XCHGQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // XCHGQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ" , _R8, jit.Ptr(_SI, 0)) // MOVQ R8, (SI)
|
||||
self.WriteRecNotAX(1, _R9, jit.Ptr(_SI, 8), false) // MOVQ R9, 8(SI)
|
||||
|
||||
/* check for value stack */
|
||||
self.Link("_next") // _next:
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _AX) // MOVQ ST.Sp, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_return") // JS _return
|
||||
|
||||
/* fast path: test up to 4 characters manually */
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , "_decode_fast") // JA _decode_fast
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX
|
||||
self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
|
||||
/* at least 1 to 3 spaces */
|
||||
for i := 0; i < 3; i++ {
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , "_decode_fast") // JA _decode_fast
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX
|
||||
self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
}
|
||||
|
||||
/* at least 4 spaces */
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
|
||||
/* fast path: use lookup table to select decoder */
|
||||
self.Link("_decode_fast") // _decode_fast:
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI
|
||||
self.Sref("_decode_tab", 4) // .... &_decode_tab
|
||||
self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX) // MOVLQSX (DI)(AX*4), AX
|
||||
self.Emit("TESTQ" , _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JZ" , "_decode_native") // JZ _decode_native
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX
|
||||
self.Rjmp("JMP" , _AX) // JMP AX
|
||||
|
||||
/* decode with native decoder */
|
||||
self.Link("_decode_native") // _decode_native:
|
||||
self.Emit("MOVQ", _IP, _DI) // MOVQ IP, DI
|
||||
self.Emit("MOVQ", _IL, _SI) // MOVQ IL, SI
|
||||
self.Emit("MOVQ", _IC, _DX) // MOVQ IC, DX
|
||||
self.Emit("LEAQ", _VAR_ss, _CX) // LEAQ ss, CX
|
||||
self.Emit("MOVQ", _VAR_df, _R8) // MOVQ $df, R8
|
||||
self.Emit("BTSQ", jit.Imm(_F_allow_control), _R8) // ANDQ $1<<_F_allow_control, R8
|
||||
self.call(_F_value) // CALL value
|
||||
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
|
||||
|
||||
/* check for errors */
|
||||
self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_parsing_error")
|
||||
self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype
|
||||
self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max
|
||||
self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype
|
||||
|
||||
/* jump table selector */
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI
|
||||
self.Sref("_switch_table", 4) // .... &_switch_table
|
||||
self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, -4), _AX) // MOVLQSX -4(DI)(AX*4), AX
|
||||
self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX
|
||||
self.Rjmp("JMP" , _AX) // JMP AX
|
||||
|
||||
/** V_EOF **/
|
||||
self.Link("_decode_V_EOF") // _decode_V_EOF:
|
||||
self.Emit("MOVL", _E_eof, _EP) // MOVL _E_eof, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
|
||||
/** V_NULL **/
|
||||
self.Link("_decode_V_NULL") // _decode_V_NULL:
|
||||
self.Emit("XORL", _R8, _R8) // XORL R8, R8
|
||||
self.Emit("XORL", _R9, _R9) // XORL R9, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_TRUE **/
|
||||
self.Link("_decode_V_TRUE") // _decode_V_TRUE:
|
||||
self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8
|
||||
// TODO: maybe modified by users?
|
||||
self.Emit("MOVQ", _V_true, _R9) // MOVQ _V_true, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_FALSE **/
|
||||
self.Link("_decode_V_FALSE") // _decode_V_FALSE:
|
||||
self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8
|
||||
self.Emit("MOVQ", _V_false, _R9) // MOVQ _V_false, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -5), _DI) // LEAQ -5(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_ARRAY **/
|
||||
self.Link("_decode_V_ARRAY") // _decode_V_ARRAY
|
||||
self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char
|
||||
|
||||
/* create a new array */
|
||||
self.Emit("MOVQ", _T_eface, _AX) // MOVQ _T_eface, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_len), jit.Ptr(_SP, 8)) // MOVQ _A_init_len, 8(SP)
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_cap), jit.Ptr(_SP, 16)) // MOVQ _A_init_cap, 16(SP)
|
||||
self.call_go(_F_makeslice) // CALL_GO runtime.makeslice
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 24), _DX) // MOVQ 24(SP), DX
|
||||
|
||||
/* pack into an interface */
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SP, 0)) // MOVQ DX, (SP)
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_len), jit.Ptr(_SP, 8)) // MOVQ _A_init_len, 8(SP)
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_cap), jit.Ptr(_SP, 16)) // MOVQ _A_init_cap, 16(SP)
|
||||
self.call_go(_F_convTslice) // CALL_GO runtime.convTslice
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 24), _R8) // MOVQ 24(SP), R8
|
||||
|
||||
/* replace current state with an array */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Imm(_S_arr), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr, ST.Vt[CX]
|
||||
self.Emit("MOVQ", _T_slice, _AX) // MOVQ _T_slice, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SI, 0)) // MOVQ AX, (SI)
|
||||
self.WriteRecNotAX(2, _R8, jit.Ptr(_SI, 8), false) // MOVQ R8, 8(SI)
|
||||
|
||||
/* add a new slot for the first element */
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow
|
||||
self.Emit("MOVQ", jit.Ptr(_R8, 0), _AX) // MOVQ (R8), AX
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WritePtrAX(3, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_arr_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr_0, ST.Vt[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_OBJECT **/
|
||||
self.Link("_decode_V_OBJECT") // _decode_V_OBJECT:
|
||||
self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char
|
||||
self.call_go(_F_makemap_small) // CALL_GO runtime.makemap_small
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 0), _AX) // MOVQ (SP), AX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj, ST.Vt[CX]
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 0)) // MOVQ DX, (SI)
|
||||
self.WritePtrAX(4, jit.Ptr(_SI, 8), false) // MOVQ AX, 8(SI)
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_STRING **/
|
||||
self.Link("_decode_V_STRING") // _decode_V_STRING:
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX
|
||||
self.Emit("MOVQ", _IC, _AX) // MOVQ IC, AX
|
||||
self.Emit("SUBQ", _CX, _AX) // SUBQ CX, AX
|
||||
|
||||
/* check for escapes */
|
||||
self.Emit("CMPQ", _VAR_ss_Ep, jit.Imm(-1)) // CMPQ ss.Ep, $-1
|
||||
self.Sjmp("JNE" , "_unquote") // JNE _unquote
|
||||
self.Emit("SUBQ", jit.Imm(1), _AX) // SUBQ $1, AX
|
||||
self.Emit("LEAQ", jit.Sib(_IP, _CX, 1, 0), _R8) // LEAQ (IP)(CX), R8
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ (PC), DI
|
||||
self.Sref("_copy_string_end", 4)
|
||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _VAR_df)
|
||||
self.Sjmp("JC", "copy_string")
|
||||
self.Link("_copy_string_end")
|
||||
self.Emit("XORL", _DX, _DX) // XORL DX, DX
|
||||
/* strings with no escape sequences */
|
||||
self.Link("_noescape") // _noescape:
|
||||
self.Emit("MOVL", jit.Imm(_S_omask_key), _DI) // MOVL _S_omask, DI
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _SI) // MOVQ ST.Vt[CX], SI
|
||||
self.Emit("BTQ" , _SI, _DI) // BTQ SI, DI
|
||||
self.Sjmp("JC" , "_object_key") // JC _object_key
|
||||
|
||||
/* check for pre-packed strings, avoid 1 allocation */
|
||||
self.Emit("TESTQ", _DX, _DX) // TESTQ DX, DX
|
||||
self.Sjmp("JNZ" , "_packed_str") // JNZ _packed_str
|
||||
self.Emit("MOVQ" , _R8, jit.Ptr(_SP, 0)) // MOVQ R8, (SP)
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
|
||||
self.call_go(_F_convTstring) // CALL_GO runtime.convTstring
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 16), _R9) // MOVQ 16(SP), R9
|
||||
|
||||
/* packed string already in R9 */
|
||||
self.Link("_packed_str") // _packed_str:
|
||||
self.Emit("MOVQ", _T_string, _R8) // MOVQ _T_string, R8
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _DI) // MOVQ ss.Iv, DI
|
||||
self.Emit("SUBQ", jit.Imm(1), _DI) // SUBQ $1, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* the string is an object key, get the map */
|
||||
self.Link("_object_key")
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
|
||||
/* add a new delimiter */
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj_delim), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj_delim, ST.Vt[CX]
|
||||
|
||||
/* add a new slot int the map */
|
||||
self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SP, 0)) // MOVQ DX, (SP)
|
||||
self.Emit("MOVQ", _SI, jit.Ptr(_SP, 8)) // MOVQ SI, 8(SP)
|
||||
self.Emit("MOVQ", _R8, jit.Ptr(_SP, 16)) // MOVQ R9, 16(SP)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 24)) // MOVQ AX, 24(SP)
|
||||
self.call_go(_F_mapassign_faststr) // CALL_GO runtime.mapassign_faststr
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 32), _AX) // MOVQ 32(SP), AX
|
||||
|
||||
/* add to the pointer stack */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.WritePtrAX(6, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* allocate memory to store the string header and unquoted result */
|
||||
self.Link("_unquote") // _unquote:
|
||||
self.Emit("ADDQ", jit.Imm(15), _AX) // ADDQ $15, AX
|
||||
self.Emit("MOVQ", _T_byte, _CX) // MOVQ _T_byte, CX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.Emit("MOVB", jit.Imm(0), jit.Ptr(_SP, 16)) // MOVB $0, 16(SP)
|
||||
self.call_go(_F_mallocgc) // CALL_GO runtime.mallocgc
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 24), _R9) // MOVQ 24(SP), R9
|
||||
|
||||
/* prepare the unquoting parameters */
|
||||
self.Emit("MOVQ" , _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX
|
||||
self.Emit("LEAQ" , jit.Sib(_IP, _CX, 1, 0), _DI) // LEAQ (IP)(CX), DI
|
||||
self.Emit("NEGQ" , _CX) // NEGQ CX
|
||||
self.Emit("LEAQ" , jit.Sib(_IC, _CX, 1, -1), _SI) // LEAQ -1(IC)(CX), SI
|
||||
self.Emit("LEAQ" , jit.Ptr(_R9, 16), _DX) // LEAQ 16(R8), DX
|
||||
self.Emit("LEAQ" , _VAR_ss_Ep, _CX) // LEAQ ss.Ep, CX
|
||||
self.Emit("XORL" , _R8, _R8) // XORL R8, R8
|
||||
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _VAR_df) // BTQ ${_F_disable_urc}, fv
|
||||
self.Emit("SETCC", _R8) // SETCC R8
|
||||
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8
|
||||
|
||||
/* unquote the string, with R9 been preserved */
|
||||
self.save(_R9) // SAVE R9
|
||||
self.call(_F_unquote) // CALL unquote
|
||||
self.load(_R9) // LOAD R9
|
||||
|
||||
/* check for errors */
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_unquote_error") // JS _unquote_error
|
||||
self.Emit("MOVL" , jit.Imm(1), _DX) // MOVL $1, DX
|
||||
self.Emit("LEAQ" , jit.Ptr(_R9, 16), _R8) // ADDQ $16, R8
|
||||
self.Emit("MOVQ" , _R8, jit.Ptr(_R9, 0)) // MOVQ R8, (R9)
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_R9, 8)) // MOVQ AX, 8(R9)
|
||||
self.Sjmp("JMP" , "_noescape") // JMP _noescape
|
||||
|
||||
/** V_DOUBLE **/
|
||||
self.Link("_decode_V_DOUBLE") // _decode_V_DOUBLE:
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0
|
||||
self.Sjmp("JMP" , "_use_float64") // JMP _use_float64
|
||||
|
||||
/** V_INTEGER **/
|
||||
self.Link("_decode_V_INTEGER") // _decode_V_INTEGER:
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_int64), _VAR_df) // BTQ _F_use_int64, df
|
||||
self.Sjmp("JC" , "_use_int64") // JC _use_int64
|
||||
self.Emit("MOVQ" , _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX
|
||||
self.Emit("CVTSQ2SD", _AX, _X0) // CVTSQ2SD AX, X0
|
||||
|
||||
/* represent numbers as `float64` */
|
||||
self.Link("_use_float64") // _use_float64:
|
||||
self.Emit("MOVSD", _X0, jit.Ptr(_SP, 0)) // MOVSD X0, (SP)
|
||||
self.call_go(_F_convT64) // CALL_GO runtime.convT64
|
||||
self.Emit("MOVQ" , _T_float64, _R8) // MOVQ _T_float64, R8
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 8), _R9) // MOVQ 8(SP), R9
|
||||
self.Emit("MOVQ" , _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* represent numbers as `json.Number` */
|
||||
self.Link("_use_number") // _use_number
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _AX) // MOVQ ss.Ep, AX
|
||||
self.Emit("LEAQ", jit.Sib(_IP, _AX, 1, 0), _SI) // LEAQ (IP)(AX), SI
|
||||
self.Emit("MOVQ", _IC, _CX) // MOVQ IC, CX
|
||||
self.Emit("SUBQ", _AX, _CX) // SUBQ AX, CX
|
||||
self.Emit("MOVQ", _SI, jit.Ptr(_SP, 0)) // MOVQ SI, (SP)
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.call_go(_F_convTstring) // CALL_GO runtime.convTstring
|
||||
self.Emit("MOVQ", _T_number, _R8) // MOVQ _T_number, R8
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 16), _R9) // MOVQ 16(SP), R9
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* represent numbers as `int64` */
|
||||
self.Link("_use_int64") // _use_int64:
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.call_go(_F_convT64) // CALL_GO runtime.convT64
|
||||
self.Emit("MOVQ", _T_int64, _R8) // MOVQ _T_int64, R8
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 8), _R9) // MOVQ 8(SP), R9
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_KEY_SEP **/
|
||||
self.Link("_decode_V_KEY_SEP") // _decode_V_KEY_SEP:
|
||||
// self.Byte(0xcc)
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_obj_delim)) // CMPQ AX, _S_obj_delim
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj), jit.Sib(_ST, _CX, 8, _ST_Vt - 8)) // MOVQ _S_obj, ST.Vt[CX - 1]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_ELEM_SEP **/
|
||||
self.Link("_decode_V_ELEM_SEP") // _decode_V_ELEM_SEP:
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(_S_arr)) // CMPQ _AX, _S_arr
|
||||
self.Sjmp("JE" , "_array_sep") // JZ _next
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(_S_obj)) // CMPQ _AX, _S_arr
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("MOVQ" , jit.Imm(_S_obj_sep), jit.Sib(_ST, _CX, 8, _ST_Vt))
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* arrays */
|
||||
self.Link("_array_sep")
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _DX) // MOVQ 8(SI), DX
|
||||
self.Emit("CMPQ", _DX, jit.Ptr(_SI, 16)) // CMPQ DX, 16(SI)
|
||||
self.Sjmp("JAE" , "_array_more") // JAE _array_more
|
||||
|
||||
/* add a slot for the new element */
|
||||
self.Link("_array_append") // _array_append:
|
||||
self.Emit("ADDQ", jit.Imm(1), jit.Ptr(_SI, 8)) // ADDQ $1, 8(SI)
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 0), _SI) // MOVQ (SI), SI
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow")
|
||||
self.Emit("SHLQ", jit.Imm(1), _DX) // SHLQ $1, DX
|
||||
self.Emit("LEAQ", jit.Sib(_SI, _DX, 8, 0), _SI) // LEAQ (SI)(DX*8), SI
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WriteRecNotAX(7 , _SI, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ SI, ST.Vp[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX}
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_ARRAY_END **/
|
||||
self.Link("_decode_V_ARRAY_END") // _decode_V_ARRAY_END:
|
||||
self.Emit("XORL", _DX, _DX) // XORL DX, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_arr_0)) // CMPQ AX, _S_arr_0
|
||||
self.Sjmp("JE" , "_first_item") // JE _first_item
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_arr)) // CMPQ AX, _S_arr
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* first element of an array */
|
||||
self.Link("_first_item") // _first_item:
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("SUBQ", jit.Imm(2), jit.Ptr(_ST, _ST_Sp)) // SUBQ $2, ST.Sp
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp - 8), _SI) // MOVQ ST.Vp[CX - 1], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp - 8)) // MOVQ DX, ST.Vp[CX - 1]
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_OBJECT_END **/
|
||||
self.Link("_decode_V_OBJECT_END") // _decode_V_OBJECT_END:
|
||||
self.Emit("MOVL", jit.Imm(_S_omask_end), _DX) // MOVL _S_omask, DI
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX)
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("XORL", _AX, _AX) // XORL AX, AX
|
||||
self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("MOVQ", _AX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ AX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* return from decoder */
|
||||
self.Link("_return") // _return:
|
||||
self.Emit("XORL", _EP, _EP) // XORL EP, EP
|
||||
self.Emit("MOVQ", _EP, jit.Ptr(_ST, _ST_Vp)) // MOVQ EP, ST.Vp[0]
|
||||
self.Link("_epilogue") // _epilogue:
|
||||
self.Emit("SUBQ", jit.Imm(_FsmOffset), _ST) // SUBQ _FsmOffset, _ST
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _VD_offs), _BP) // MOVQ _VD_offs(SP), BP
|
||||
self.Emit("ADDQ", jit.Imm(_VD_size), _SP) // ADDQ $_VD_size, SP
|
||||
self.Emit("RET") // RET
|
||||
|
||||
/* array expand */
|
||||
self.Link("_array_more") // _array_more:
|
||||
self.Emit("MOVQ" , _T_eface, _AX) // MOVQ _T_eface, AX
|
||||
self.Emit("MOVOU", jit.Ptr(_SI, 0), _X0) // MOVOU (SI), X0
|
||||
self.Emit("MOVQ" , jit.Ptr(_SI, 16), _DX) // MOVQ 16(SI), DX
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 8)) // MOVOU X0, 8(SP)
|
||||
self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 24)) // MOVQ DX, 24(SP)
|
||||
self.Emit("SHLQ" , jit.Imm(1), _DX) // SHLQ $1, DX
|
||||
self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 32)) // MOVQ DX, 32(SP)
|
||||
self.call_go(_F_growslice) // CALL_GO runtime.growslice
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 40), _DI) // MOVOU 40(SP), DI
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 48), _DX) // MOVOU 48(SP), DX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 56), _AX) // MOVQ 56(SP), AX
|
||||
|
||||
/* update the slice */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SI, 16)) // MOVQ AX, 16(AX)
|
||||
self.WriteRecNotAX(8 , _DI, jit.Ptr(_SI, 0), false) // MOVQ R10, (SI)
|
||||
self.Sjmp("JMP" , "_array_append") // JMP _array_append
|
||||
|
||||
/* copy string */
|
||||
self.Link("copy_string") // pointer: R8, length: AX, return addr: DI
|
||||
// self.Byte(0xcc)
|
||||
self.Emit("MOVQ", _R8, _VAR_cs_p)
|
||||
self.Emit("MOVQ", _AX, _VAR_cs_n)
|
||||
self.Emit("MOVQ", _DI, _VAR_cs_LR)
|
||||
self.Emit("MOVQ", _T_byte, jit.Ptr(_SP, 0))
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 8))
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16))
|
||||
self.call_go(_F_makeslice)
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 24), _R8)
|
||||
self.Emit("MOVQ", _R8, _VAR_cs_d)
|
||||
self.Emit("MOVQ", _R8, jit.Ptr(_SP, 0))
|
||||
self.Emit("MOVQ", _VAR_cs_p, _R8)
|
||||
self.Emit("MOVQ", _R8, jit.Ptr(_SP, 8))
|
||||
self.Emit("MOVQ", _VAR_cs_n, _AX)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16))
|
||||
self.call_go(_F_memmove)
|
||||
self.Emit("MOVQ", _VAR_cs_d, _R8)
|
||||
self.Emit("MOVQ", _VAR_cs_n, _AX)
|
||||
self.Emit("MOVQ", _VAR_cs_LR, _DI)
|
||||
// self.Byte(0xcc)
|
||||
self.Rjmp("JMP", _DI)
|
||||
|
||||
/* error handlers */
|
||||
self.Link("_stack_overflow")
|
||||
self.Emit("MOVL" , _E_recurse, _EP) // MOVQ _E_recurse, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_vtype_error") // _vtype_error:
|
||||
self.Emit("MOVQ" , _DI, _IC) // MOVQ DI, IC
|
||||
self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_invalid_char") // _invalid_char:
|
||||
self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC
|
||||
self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_unquote_error") // _unquote_error:
|
||||
self.Emit("MOVQ" , _VAR_ss_Iv, _IC) // MOVQ ss.Iv, IC
|
||||
self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC
|
||||
self.Link("_parsing_error") // _parsing_error:
|
||||
self.Emit("NEGQ" , _AX) // NEGQ AX
|
||||
self.Emit("MOVQ" , _AX, _EP) // MOVQ AX, EP
|
||||
self.Link("_error") // _error:
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
|
||||
self.Sjmp("JMP" , "_epilogue") // JMP _epilogue
|
||||
|
||||
/* invalid value type, never returns */
|
||||
self.Link("_invalid_vtype")
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.call(_F_invalid_vtype) // CALL invalid_type
|
||||
self.Emit("UD2") // UD2
|
||||
|
||||
/* switch jump table */
|
||||
self.Link("_switch_table") // _switch_table:
|
||||
self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0
|
||||
self.Sref("_decode_V_NULL", -4) // SREF &_decode_V_NULL, $-4
|
||||
self.Sref("_decode_V_TRUE", -8) // SREF &_decode_V_TRUE, $-8
|
||||
self.Sref("_decode_V_FALSE", -12) // SREF &_decode_V_FALSE, $-12
|
||||
self.Sref("_decode_V_ARRAY", -16) // SREF &_decode_V_ARRAY, $-16
|
||||
self.Sref("_decode_V_OBJECT", -20) // SREF &_decode_V_OBJECT, $-20
|
||||
self.Sref("_decode_V_STRING", -24) // SREF &_decode_V_STRING, $-24
|
||||
self.Sref("_decode_V_DOUBLE", -28) // SREF &_decode_V_DOUBLE, $-28
|
||||
self.Sref("_decode_V_INTEGER", -32) // SREF &_decode_V_INTEGER, $-32
|
||||
self.Sref("_decode_V_KEY_SEP", -36) // SREF &_decode_V_KEY_SEP, $-36
|
||||
self.Sref("_decode_V_ELEM_SEP", -40) // SREF &_decode_V_ELEM_SEP, $-40
|
||||
self.Sref("_decode_V_ARRAY_END", -44) // SREF &_decode_V_ARRAY_END, $-44
|
||||
self.Sref("_decode_V_OBJECT_END", -48) // SREF &_decode_V_OBJECT_END, $-48
|
||||
|
||||
/* fast character lookup table */
|
||||
self.Link("_decode_tab") // _decode_tab:
|
||||
self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0
|
||||
|
||||
/* generate rest of the tabs */
|
||||
for i := 1; i < 256; i++ {
|
||||
if to, ok := _R_tab[i]; ok {
|
||||
self.Sref(to, -int64(i) * 4)
|
||||
} else {
|
||||
self.Byte(0x00, 0x00, 0x00, 0x00)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) WritePtrAX(i int, rec obj.Addr, saveDI bool) {
|
||||
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}")
|
||||
if saveDI {
|
||||
self.save(_DI)
|
||||
}
|
||||
self.Emit("LEAQ", rec, _DI)
|
||||
self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX
|
||||
self.Rjmp("CALL", _R10)
|
||||
if saveDI {
|
||||
self.load(_DI)
|
||||
}
|
||||
self.Sjmp("JMP", "_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Emit("MOVQ", _AX, rec)
|
||||
self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool) {
|
||||
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)
|
||||
if saveDI {
|
||||
self.save(_DI)
|
||||
}
|
||||
self.Emit("LEAQ", rec, _DI)
|
||||
self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX
|
||||
self.Rjmp("CALL", _R10)
|
||||
if saveDI {
|
||||
self.load(_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}")
|
||||
}
|
||||
|
||||
/** Generic Decoder **/
|
||||
|
||||
var (
|
||||
_subr_decode_value = new(_ValueDecoder).build()
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
func invalid_vtype(vt types.ValueType) {
|
||||
throw(fmt.Sprintf("invalid value type: %d", vt))
|
||||
}
|
||||
772
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go117.go
generated
vendored
Normal file
772
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go117.go
generated
vendored
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
//go:build go1.17 && !go1.21
|
||||
// +build go1.17,!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 decoder
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
)
|
||||
|
||||
/** Crucial Registers:
|
||||
*
|
||||
* ST(R13) && 0(SP) : ro, decoder stack
|
||||
* DF(AX) : ro, decoder flags
|
||||
* EP(BX) : wo, error pointer
|
||||
* IP(R10) : ro, input pointer
|
||||
* IL(R12) : ro, input length
|
||||
* IC(R11) : rw, input cursor
|
||||
* VP(R15) : ro, value pointer (to an interface{})
|
||||
*/
|
||||
|
||||
const (
|
||||
_VD_args = 8 // 8 bytes for passing arguments to this functions
|
||||
_VD_fargs = 64 // 64 bytes for passing arguments to other Go functions
|
||||
_VD_saves = 48 // 48 bytes for saving the registers before CALL instructions
|
||||
_VD_locals = 96 // 96 bytes for local variables
|
||||
)
|
||||
|
||||
const (
|
||||
_VD_offs = _VD_fargs + _VD_saves + _VD_locals
|
||||
_VD_size = _VD_offs + 8 // 8 bytes for the parent frame pointer
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_ss = _VAR_ss_Vt
|
||||
_VAR_df = jit.Ptr(_SP, _VD_fargs + _VD_saves)
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_ss_Vt = jit.Ptr(_SP, _VD_fargs + _VD_saves + 8)
|
||||
_VAR_ss_Dv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 16)
|
||||
_VAR_ss_Iv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 24)
|
||||
_VAR_ss_Ep = jit.Ptr(_SP, _VD_fargs + _VD_saves + 32)
|
||||
_VAR_ss_Db = jit.Ptr(_SP, _VD_fargs + _VD_saves + 40)
|
||||
_VAR_ss_Dc = jit.Ptr(_SP, _VD_fargs + _VD_saves + 48)
|
||||
)
|
||||
|
||||
var (
|
||||
_VAR_R9 = jit.Ptr(_SP, _VD_fargs + _VD_saves + 56)
|
||||
)
|
||||
type _ValueDecoder struct {
|
||||
jit.BaseAssembler
|
||||
}
|
||||
|
||||
var (
|
||||
_VAR_cs_LR = jit.Ptr(_SP, _VD_fargs + _VD_saves + 64)
|
||||
_VAR_cs_p = jit.Ptr(_SP, _VD_fargs + _VD_saves + 72)
|
||||
_VAR_cs_n = jit.Ptr(_SP, _VD_fargs + _VD_saves + 80)
|
||||
_VAR_cs_d = jit.Ptr(_SP, _VD_fargs + _VD_saves + 88)
|
||||
)
|
||||
|
||||
func (self *_ValueDecoder) build() uintptr {
|
||||
self.Init(self.compile)
|
||||
return *(*uintptr)(self.Load("decode_value", _VD_size, _VD_args, argPtrs_generic, localPtrs_generic))
|
||||
}
|
||||
|
||||
/** Function Calling Helpers **/
|
||||
|
||||
func (self *_ValueDecoder) save(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _VD_saves / 8 - 1 {
|
||||
panic("too many registers to save")
|
||||
} else {
|
||||
self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) load(r ...obj.Addr) {
|
||||
for i, v := range r {
|
||||
if i > _VD_saves / 8 - 1 {
|
||||
panic("too many registers to load")
|
||||
} else {
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) call(fn obj.Addr) {
|
||||
self.Emit("MOVQ", fn, _R9) // MOVQ ${fn}, AX
|
||||
self.Rjmp("CALL", _R9) // CALL AX
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) call_go(fn obj.Addr) {
|
||||
self.save(_REG_go...) // SAVE $REG_go
|
||||
self.call(fn) // CALL ${fn}
|
||||
self.load(_REG_go...) // LOAD $REG_go
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) callc(fn obj.Addr) {
|
||||
self.Emit("XCHGQ", _IP, _BP)
|
||||
self.call(fn)
|
||||
self.Emit("XCHGQ", _IP, _BP)
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) call_c(fn obj.Addr) {
|
||||
self.Emit("XCHGQ", _IC, _BX)
|
||||
self.callc(fn)
|
||||
self.Emit("XCHGQ", _IC, _BX)
|
||||
}
|
||||
|
||||
/** Decoder Assembler **/
|
||||
|
||||
const (
|
||||
_S_val = iota + 1
|
||||
_S_arr
|
||||
_S_arr_0
|
||||
_S_obj
|
||||
_S_obj_0
|
||||
_S_obj_delim
|
||||
_S_obj_sep
|
||||
)
|
||||
|
||||
const (
|
||||
_S_omask_key = (1 << _S_obj_0) | (1 << _S_obj_sep)
|
||||
_S_omask_end = (1 << _S_obj_0) | (1 << _S_obj)
|
||||
_S_vmask = (1 << _S_val) | (1 << _S_arr_0)
|
||||
)
|
||||
|
||||
const (
|
||||
_A_init_len = 1
|
||||
_A_init_cap = 16
|
||||
)
|
||||
|
||||
const (
|
||||
_ST_Sp = 0
|
||||
_ST_Vt = _PtrBytes
|
||||
_ST_Vp = _PtrBytes * (types.MAX_RECURSE + 1)
|
||||
)
|
||||
|
||||
var (
|
||||
_V_true = jit.Imm(int64(pbool(true)))
|
||||
_V_false = jit.Imm(int64(pbool(false)))
|
||||
_F_value = jit.Imm(int64(native.S_value))
|
||||
)
|
||||
|
||||
var (
|
||||
_V_max = jit.Imm(int64(types.V_MAX))
|
||||
_E_eof = jit.Imm(int64(types.ERR_EOF))
|
||||
_E_invalid = jit.Imm(int64(types.ERR_INVALID_CHAR))
|
||||
_E_recurse = jit.Imm(int64(types.ERR_RECURSE_EXCEED_MAX))
|
||||
)
|
||||
|
||||
var (
|
||||
_F_convTslice = jit.Func(convTslice)
|
||||
_F_convTstring = jit.Func(convTstring)
|
||||
_F_invalid_vtype = jit.Func(invalid_vtype)
|
||||
)
|
||||
|
||||
var (
|
||||
_T_map = jit.Type(reflect.TypeOf((map[string]interface{})(nil)))
|
||||
_T_bool = jit.Type(reflect.TypeOf(false))
|
||||
_T_int64 = jit.Type(reflect.TypeOf(int64(0)))
|
||||
_T_eface = jit.Type(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
_T_slice = jit.Type(reflect.TypeOf(([]interface{})(nil)))
|
||||
_T_string = jit.Type(reflect.TypeOf(""))
|
||||
_T_number = jit.Type(reflect.TypeOf(json.Number("")))
|
||||
_T_float64 = jit.Type(reflect.TypeOf(float64(0)))
|
||||
)
|
||||
|
||||
var _R_tab = map[int]string {
|
||||
'[': "_decode_V_ARRAY",
|
||||
'{': "_decode_V_OBJECT",
|
||||
':': "_decode_V_KEY_SEP",
|
||||
',': "_decode_V_ELEM_SEP",
|
||||
']': "_decode_V_ARRAY_END",
|
||||
'}': "_decode_V_OBJECT_END",
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) compile() {
|
||||
self.Emit("SUBQ", jit.Imm(_VD_size), _SP) // SUBQ $_VD_size, SP
|
||||
self.Emit("MOVQ", _BP, jit.Ptr(_SP, _VD_offs)) // MOVQ BP, _VD_offs(SP)
|
||||
self.Emit("LEAQ", jit.Ptr(_SP, _VD_offs), _BP) // LEAQ _VD_offs(SP), BP
|
||||
|
||||
/* initialize the state machine */
|
||||
self.Emit("XORL", _CX, _CX) // XORL CX, CX
|
||||
self.Emit("MOVQ", _DF, _VAR_df) // MOVQ DF, df
|
||||
/* initialize digital buffer first */
|
||||
self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_ss_Dc) // MOVQ $_MaxDigitNums, ss.Dcap
|
||||
self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX
|
||||
self.Emit("MOVQ", _AX, _VAR_ss_Db) // MOVQ AX, ss.Dbuf
|
||||
/* add ST offset */
|
||||
self.Emit("ADDQ", jit.Imm(_FsmOffset), _ST) // ADDQ _FsmOffset, _ST
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WriteRecNotAX(0, _VP, jit.Ptr(_ST, _ST_Vp), false) // MOVQ VP, ST.Vp[0]
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Ptr(_ST, _ST_Vt)) // MOVQ _S_val, ST.Vt[0]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* set the value from previous round */
|
||||
self.Link("_set_value") // _set_value:
|
||||
self.Emit("MOVL" , jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_vtype_error") // JNC _vtype_error
|
||||
self.Emit("XORL" , _SI, _SI) // XORL SI, SI
|
||||
self.Emit("SUBQ" , jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("XCHGQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // XCHGQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ" , _R8, jit.Ptr(_SI, 0)) // MOVQ R8, (SI)
|
||||
self.WriteRecNotAX(1, _R9, jit.Ptr(_SI, 8), false) // MOVQ R9, 8(SI)
|
||||
|
||||
/* check for value stack */
|
||||
self.Link("_next") // _next:
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _AX) // MOVQ ST.Sp, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_return") // JS _return
|
||||
|
||||
/* fast path: test up to 4 characters manually */
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , "_decode_fast") // JA _decode_fast
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX
|
||||
self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
|
||||
/* at least 1 to 3 spaces */
|
||||
for i := 0; i < 3; i++ {
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , "_decode_fast") // JA _decode_fast
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX
|
||||
self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
}
|
||||
|
||||
/* at least 4 spaces */
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
|
||||
/* fast path: use lookup table to select decoder */
|
||||
self.Link("_decode_fast") // _decode_fast:
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI
|
||||
self.Sref("_decode_tab", 4) // .... &_decode_tab
|
||||
self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX) // MOVLQSX (DI)(AX*4), AX
|
||||
self.Emit("TESTQ" , _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JZ" , "_decode_native") // JZ _decode_native
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX
|
||||
self.Rjmp("JMP" , _AX) // JMP AX
|
||||
|
||||
/* decode with native decoder */
|
||||
self.Link("_decode_native") // _decode_native:
|
||||
self.Emit("MOVQ", _IP, _DI) // MOVQ IP, DI
|
||||
self.Emit("MOVQ", _IL, _SI) // MOVQ IL, SI
|
||||
self.Emit("MOVQ", _IC, _DX) // MOVQ IC, DX
|
||||
self.Emit("LEAQ", _VAR_ss, _CX) // LEAQ ss, CX
|
||||
self.Emit("MOVQ", _VAR_df, _R8) // MOVQ $df, R8
|
||||
self.Emit("BTSQ", jit.Imm(_F_allow_control), _R8) // ANDQ $1<<_F_allow_control, R8
|
||||
self.callc(_F_value) // CALL value
|
||||
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
|
||||
|
||||
/* check for errors */
|
||||
self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_parsing_error")
|
||||
self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype
|
||||
self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max
|
||||
self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype
|
||||
|
||||
/* jump table selector */
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI
|
||||
self.Sref("_switch_table", 4) // .... &_switch_table
|
||||
self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, -4), _AX) // MOVLQSX -4(DI)(AX*4), AX
|
||||
self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX
|
||||
self.Rjmp("JMP" , _AX) // JMP AX
|
||||
|
||||
/** V_EOF **/
|
||||
self.Link("_decode_V_EOF") // _decode_V_EOF:
|
||||
self.Emit("MOVL", _E_eof, _EP) // MOVL _E_eof, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
|
||||
/** V_NULL **/
|
||||
self.Link("_decode_V_NULL") // _decode_V_NULL:
|
||||
self.Emit("XORL", _R8, _R8) // XORL R8, R8
|
||||
self.Emit("XORL", _R9, _R9) // XORL R9, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_TRUE **/
|
||||
self.Link("_decode_V_TRUE") // _decode_V_TRUE:
|
||||
self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8
|
||||
// TODO: maybe modified by users?
|
||||
self.Emit("MOVQ", _V_true, _R9) // MOVQ _V_true, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_FALSE **/
|
||||
self.Link("_decode_V_FALSE") // _decode_V_FALSE:
|
||||
self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8
|
||||
self.Emit("MOVQ", _V_false, _R9) // MOVQ _V_false, R9
|
||||
self.Emit("LEAQ", jit.Ptr(_IC, -5), _DI) // LEAQ -5(IC), DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_ARRAY **/
|
||||
self.Link("_decode_V_ARRAY") // _decode_V_ARRAY
|
||||
self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char
|
||||
|
||||
/* create a new array */
|
||||
self.Emit("MOVQ", _T_eface, _AX) // MOVQ _T_eface, AX
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_len), _BX) // MOVQ _A_init_len, BX
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX) // MOVQ _A_init_cap, CX
|
||||
self.call_go(_F_makeslice) // CALL_GO runtime.makeslice
|
||||
|
||||
/* pack into an interface */
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_len), _BX) // MOVQ _A_init_len, BX
|
||||
self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX) // MOVQ _A_init_cap, CX
|
||||
self.call_go(_F_convTslice) // CALL_GO runtime.convTslice
|
||||
self.Emit("MOVQ", _AX, _R8) // MOVQ AX, R8
|
||||
|
||||
/* replace current state with an array */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Imm(_S_arr), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr, ST.Vt[CX]
|
||||
self.Emit("MOVQ", _T_slice, _AX) // MOVQ _T_slice, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SI, 0)) // MOVQ AX, (SI)
|
||||
self.WriteRecNotAX(2, _R8, jit.Ptr(_SI, 8), false) // MOVQ R8, 8(SI)
|
||||
|
||||
/* add a new slot for the first element */
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow
|
||||
self.Emit("MOVQ", jit.Ptr(_R8, 0), _AX) // MOVQ (R8), AX
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WritePtrAX(3, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_arr_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr_0, ST.Vt[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_OBJECT **/
|
||||
self.Link("_decode_V_OBJECT") // _decode_V_OBJECT:
|
||||
self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char
|
||||
self.call_go(_F_makemap_small) // CALL_GO runtime.makemap_small
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj_0, ST.Vt[CX]
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 0)) // MOVQ DX, (SI)
|
||||
self.WritePtrAX(4, jit.Ptr(_SI, 8), false) // MOVQ AX, 8(SI)
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_STRING **/
|
||||
self.Link("_decode_V_STRING") // _decode_V_STRING:
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX
|
||||
self.Emit("MOVQ", _IC, _AX) // MOVQ IC, AX
|
||||
self.Emit("SUBQ", _CX, _AX) // SUBQ CX, AX
|
||||
|
||||
/* check for escapes */
|
||||
self.Emit("CMPQ", _VAR_ss_Ep, jit.Imm(-1)) // CMPQ ss.Ep, $-1
|
||||
self.Sjmp("JNE" , "_unquote") // JNE _unquote
|
||||
self.Emit("SUBQ", jit.Imm(1), _AX) // SUBQ $1, AX
|
||||
self.Emit("LEAQ", jit.Sib(_IP, _CX, 1, 0), _R8) // LEAQ (IP)(CX), R8
|
||||
self.Byte(0x48, 0x8d, 0x3d) // LEAQ (PC), DI
|
||||
self.Sref("_copy_string_end", 4)
|
||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _VAR_df)
|
||||
self.Sjmp("JC", "copy_string")
|
||||
self.Link("_copy_string_end")
|
||||
self.Emit("XORL", _DX, _DX)
|
||||
|
||||
/* strings with no escape sequences */
|
||||
self.Link("_noescape") // _noescape:
|
||||
self.Emit("MOVL", jit.Imm(_S_omask_key), _DI) // MOVL _S_omask, DI
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _SI) // MOVQ ST.Vt[CX], SI
|
||||
self.Emit("BTQ" , _SI, _DI) // BTQ SI, DI
|
||||
self.Sjmp("JC" , "_object_key") // JC _object_key
|
||||
|
||||
/* check for pre-packed strings, avoid 1 allocation */
|
||||
self.Emit("TESTQ", _DX, _DX) // TESTQ DX, DX
|
||||
self.Sjmp("JNZ" , "_packed_str") // JNZ _packed_str
|
||||
self.Emit("MOVQ" , _AX, _BX) // MOVQ AX, BX
|
||||
self.Emit("MOVQ" , _R8, _AX) // MOVQ R8, AX
|
||||
self.call_go(_F_convTstring) // CALL_GO runtime.convTstring
|
||||
self.Emit("MOVQ" , _AX, _R9) // MOVQ AX, R9
|
||||
|
||||
/* packed string already in R9 */
|
||||
self.Link("_packed_str") // _packed_str:
|
||||
self.Emit("MOVQ", _T_string, _R8) // MOVQ _T_string, R8
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _DI) // MOVQ ss.Iv, DI
|
||||
self.Emit("SUBQ", jit.Imm(1), _DI) // SUBQ $1, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* the string is an object key, get the map */
|
||||
self.Link("_object_key")
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
|
||||
/* add a new delimiter */
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj_delim), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj_delim, ST.Vt[CX]
|
||||
|
||||
/* add a new slot int the map */
|
||||
self.Emit("MOVQ", _AX, _DI) // MOVQ AX, DI
|
||||
self.Emit("MOVQ", _T_map, _AX) // MOVQ _T_map, AX
|
||||
self.Emit("MOVQ", _SI, _BX) // MOVQ SI, BX
|
||||
self.Emit("MOVQ", _R8, _CX) // MOVQ R9, CX
|
||||
self.call_go(_F_mapassign_faststr) // CALL_GO runtime.mapassign_faststr
|
||||
|
||||
/* add to the pointer stack */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.WritePtrAX(6, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* allocate memory to store the string header and unquoted result */
|
||||
self.Link("_unquote") // _unquote:
|
||||
self.Emit("ADDQ", jit.Imm(15), _AX) // ADDQ $15, AX
|
||||
self.Emit("MOVQ", _T_byte, _BX) // MOVQ _T_byte, BX
|
||||
self.Emit("MOVB", jit.Imm(0), _CX) // MOVB $0, CX
|
||||
self.call_go(_F_mallocgc) // CALL_GO runtime.mallocgc
|
||||
self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9
|
||||
|
||||
/* prepare the unquoting parameters */
|
||||
self.Emit("MOVQ" , _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX
|
||||
self.Emit("LEAQ" , jit.Sib(_IP, _CX, 1, 0), _DI) // LEAQ (IP)(CX), DI
|
||||
self.Emit("NEGQ" , _CX) // NEGQ CX
|
||||
self.Emit("LEAQ" , jit.Sib(_IC, _CX, 1, -1), _SI) // LEAQ -1(IC)(CX), SI
|
||||
self.Emit("LEAQ" , jit.Ptr(_R9, 16), _DX) // LEAQ 16(R8), DX
|
||||
self.Emit("LEAQ" , _VAR_ss_Ep, _CX) // LEAQ ss.Ep, CX
|
||||
self.Emit("XORL" , _R8, _R8) // XORL R8, R8
|
||||
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _VAR_df) // BTQ ${_F_disable_urc}, fv
|
||||
self.Emit("SETCC", _R8) // SETCC R8
|
||||
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8
|
||||
|
||||
/* unquote the string, with R9 been preserved */
|
||||
self.Emit("MOVQ", _R9, _VAR_R9) // SAVE R9
|
||||
self.call_c(_F_unquote) // CALL unquote
|
||||
self.Emit("MOVQ", _VAR_R9, _R9) // LOAD R9
|
||||
|
||||
/* check for errors */
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , "_unquote_error") // JS _unquote_error
|
||||
self.Emit("MOVL" , jit.Imm(1), _DX) // MOVL $1, DX
|
||||
self.Emit("LEAQ" , jit.Ptr(_R9, 16), _R8) // ADDQ $16, R8
|
||||
self.Emit("MOVQ" , _R8, jit.Ptr(_R9, 0)) // MOVQ R8, (R9)
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_R9, 8)) // MOVQ AX, 8(R9)
|
||||
self.Sjmp("JMP" , "_noescape") // JMP _noescape
|
||||
|
||||
/** V_DOUBLE **/
|
||||
self.Link("_decode_V_DOUBLE") // _decode_V_DOUBLE:
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0
|
||||
self.Sjmp("JMP" , "_use_float64") // JMP _use_float64
|
||||
|
||||
/** V_INTEGER **/
|
||||
self.Link("_decode_V_INTEGER") // _decode_V_INTEGER:
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_int64), _VAR_df) // BTQ _F_use_int64, df
|
||||
self.Sjmp("JC" , "_use_int64") // JC _use_int64
|
||||
//TODO: use ss.Dv directly
|
||||
self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0
|
||||
|
||||
/* represent numbers as `float64` */
|
||||
self.Link("_use_float64") // _use_float64:
|
||||
self.Emit("MOVQ" , _X0, _AX) // MOVQ X0, AX
|
||||
self.call_go(_F_convT64) // CALL_GO runtime.convT64
|
||||
self.Emit("MOVQ" , _T_float64, _R8) // MOVQ _T_float64, R8
|
||||
self.Emit("MOVQ" , _AX, _R9) // MOVQ AX, R9
|
||||
self.Emit("MOVQ" , _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* represent numbers as `json.Number` */
|
||||
self.Link("_use_number") // _use_number
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _AX) // MOVQ ss.Ep, AX
|
||||
self.Emit("LEAQ", jit.Sib(_IP, _AX, 1, 0), _SI) // LEAQ (IP)(AX), SI
|
||||
self.Emit("MOVQ", _IC, _CX) // MOVQ IC, CX
|
||||
self.Emit("SUBQ", _AX, _CX) // SUBQ AX, CX
|
||||
self.Emit("MOVQ", _SI, _AX) // MOVQ SI, AX
|
||||
self.Emit("MOVQ", _CX, _BX) // MOVQ CX, BX
|
||||
self.call_go(_F_convTstring) // CALL_GO runtime.convTstring
|
||||
self.Emit("MOVQ", _T_number, _R8) // MOVQ _T_number, R8
|
||||
self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/* represent numbers as `int64` */
|
||||
self.Link("_use_int64") // _use_int64:
|
||||
self.Emit("MOVQ", _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX
|
||||
self.call_go(_F_convT64) // CALL_GO runtime.convT64
|
||||
self.Emit("MOVQ", _T_int64, _R8) // MOVQ _T_int64, R8
|
||||
self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9
|
||||
self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI
|
||||
self.Sjmp("JMP" , "_set_value") // JMP _set_value
|
||||
|
||||
/** V_KEY_SEP **/
|
||||
self.Link("_decode_V_KEY_SEP") // _decode_V_KEY_SEP:
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_obj_delim)) // CMPQ AX, _S_obj_delim
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_obj), jit.Sib(_ST, _CX, 8, _ST_Vt - 8)) // MOVQ _S_obj, ST.Vt[CX - 1]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_ELEM_SEP **/
|
||||
self.Link("_decode_V_ELEM_SEP") // _decode_V_ELEM_SEP:
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(_S_arr))
|
||||
self.Sjmp("JE" , "_array_sep") // JZ _next
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(_S_obj)) // CMPQ _AX, _S_arr
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("MOVQ" , jit.Imm(_S_obj_sep), jit.Sib(_ST, _CX, 8, _ST_Vt))
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* arrays */
|
||||
self.Link("_array_sep")
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _DX) // MOVQ 8(SI), DX
|
||||
self.Emit("CMPQ", _DX, jit.Ptr(_SI, 16)) // CMPQ DX, 16(SI)
|
||||
self.Sjmp("JAE" , "_array_more") // JAE _array_more
|
||||
|
||||
/* add a slot for the new element */
|
||||
self.Link("_array_append") // _array_append:
|
||||
self.Emit("ADDQ", jit.Imm(1), jit.Ptr(_SI, 8)) // ADDQ $1, 8(SI)
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 0), _SI) // MOVQ (SI), SI
|
||||
self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX
|
||||
self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}
|
||||
self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow
|
||||
self.Emit("SHLQ", jit.Imm(1), _DX) // SHLQ $1, DX
|
||||
self.Emit("LEAQ", jit.Sib(_SI, _DX, 8, 0), _SI) // LEAQ (SI)(DX*8), SI
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp
|
||||
self.WriteRecNotAX(7 , _SI, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ SI, ST.Vp[CX]
|
||||
self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX}
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_ARRAY_END **/
|
||||
self.Link("_decode_V_ARRAY_END") // _decode_V_ARRAY_END:
|
||||
self.Emit("XORL", _DX, _DX) // XORL DX, DX
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_arr_0)) // CMPQ AX, _S_arr_0
|
||||
self.Sjmp("JE" , "_first_item") // JE _first_item
|
||||
self.Emit("CMPQ", _AX, jit.Imm(_S_arr)) // CMPQ AX, _S_arr
|
||||
self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* first element of an array */
|
||||
self.Link("_first_item") // _first_item:
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("SUBQ", jit.Imm(2), jit.Ptr(_ST, _ST_Sp)) // SUBQ $2, ST.Sp
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp - 8), _SI) // MOVQ ST.Vp[CX - 1], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp - 8)) // MOVQ DX, ST.Vp[CX - 1]
|
||||
self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/** V_OBJECT_END **/
|
||||
self.Link("_decode_V_OBJECT_END") // _decode_V_OBJECT_END:
|
||||
self.Emit("MOVL", jit.Imm(_S_omask_end), _DI) // MOVL _S_omask, DI
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX
|
||||
self.Emit("BTQ" , _AX, _DI)
|
||||
self.Sjmp("JNC" , "_invalid_char") // JNE _invalid_char
|
||||
self.Emit("XORL", _AX, _AX) // XORL AX, AX
|
||||
self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp
|
||||
self.Emit("MOVQ", _AX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ AX, ST.Vp[CX]
|
||||
self.Sjmp("JMP" , "_next") // JMP _next
|
||||
|
||||
/* return from decoder */
|
||||
self.Link("_return") // _return:
|
||||
self.Emit("XORL", _EP, _EP) // XORL EP, EP
|
||||
self.Emit("MOVQ", _EP, jit.Ptr(_ST, _ST_Vp)) // MOVQ EP, ST.Vp[0]
|
||||
self.Link("_epilogue") // _epilogue:
|
||||
self.Emit("SUBQ", jit.Imm(_FsmOffset), _ST) // SUBQ _FsmOffset, _ST
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, _VD_offs), _BP) // MOVQ _VD_offs(SP), BP
|
||||
self.Emit("ADDQ", jit.Imm(_VD_size), _SP) // ADDQ $_VD_size, SP
|
||||
self.Emit("RET") // RET
|
||||
|
||||
/* array expand */
|
||||
self.Link("_array_more") // _array_more:
|
||||
self.Emit("MOVQ" , _T_eface, _AX) // MOVQ _T_eface, AX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SI, 0), _BX) // MOVQ (SI), BX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SI, 8), _CX) // MOVQ 8(SI), CX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SI, 16), _DI) // MOVQ 16(SI), DI
|
||||
self.Emit("MOVQ" , _DI, _SI) // MOVQ DI, 24(SP)
|
||||
self.Emit("SHLQ" , jit.Imm(1), _SI) // SHLQ $1, SI
|
||||
self.call_go(_F_growslice) // CALL_GO runtime.growslice
|
||||
self.Emit("MOVQ" , _AX, _DI) // MOVQ AX, DI
|
||||
self.Emit("MOVQ" , _BX, _DX) // MOVQ BX, DX
|
||||
self.Emit("MOVQ" , _CX, _AX) // MOVQ CX, AX
|
||||
|
||||
/* update the slice */
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI
|
||||
self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI
|
||||
self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SI, 16)) // MOVQ AX, 16(AX)
|
||||
self.WriteRecNotAX(8 , _DI, jit.Ptr(_SI, 0), false) // MOVQ R10, (SI)
|
||||
self.Sjmp("JMP" , "_array_append") // JMP _array_append
|
||||
|
||||
/* copy string */
|
||||
self.Link("copy_string") // pointer: R8, length: AX, return addr: DI
|
||||
self.Emit("MOVQ", _R8, _VAR_cs_p)
|
||||
self.Emit("MOVQ", _AX, _VAR_cs_n)
|
||||
self.Emit("MOVQ", _DI, _VAR_cs_LR)
|
||||
self.Emit("MOVQ", _AX, _BX)
|
||||
self.Emit("MOVQ", _AX, _CX)
|
||||
self.Emit("MOVQ", _T_byte, _AX)
|
||||
self.call_go(_F_makeslice)
|
||||
self.Emit("MOVQ", _AX, _VAR_cs_d)
|
||||
self.Emit("MOVQ", _VAR_cs_p, _BX)
|
||||
self.Emit("MOVQ", _VAR_cs_n, _CX)
|
||||
self.call_go(_F_memmove)
|
||||
self.Emit("MOVQ", _VAR_cs_d, _R8)
|
||||
self.Emit("MOVQ", _VAR_cs_n, _AX)
|
||||
self.Emit("MOVQ", _VAR_cs_LR, _DI)
|
||||
self.Rjmp("JMP", _DI)
|
||||
|
||||
/* error handlers */
|
||||
self.Link("_stack_overflow")
|
||||
self.Emit("MOVL" , _E_recurse, _EP) // MOVQ _E_recurse, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_vtype_error") // _vtype_error:
|
||||
self.Emit("MOVQ" , _DI, _IC) // MOVQ DI, IC
|
||||
self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_invalid_char") // _invalid_char:
|
||||
self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC
|
||||
self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP
|
||||
self.Sjmp("JMP" , "_error") // JMP _error
|
||||
self.Link("_unquote_error") // _unquote_error:
|
||||
self.Emit("MOVQ" , _VAR_ss_Iv, _IC) // MOVQ ss.Iv, IC
|
||||
self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC
|
||||
self.Link("_parsing_error") // _parsing_error:
|
||||
self.Emit("NEGQ" , _AX) // NEGQ AX
|
||||
self.Emit("MOVQ" , _AX, _EP) // MOVQ AX, EP
|
||||
self.Link("_error") // _error:
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
|
||||
self.Sjmp("JMP" , "_epilogue") // JMP _epilogue
|
||||
|
||||
/* invalid value type, never returns */
|
||||
self.Link("_invalid_vtype")
|
||||
self.call_go(_F_invalid_vtype) // CALL invalid_type
|
||||
self.Emit("UD2") // UD2
|
||||
|
||||
/* switch jump table */
|
||||
self.Link("_switch_table") // _switch_table:
|
||||
self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0
|
||||
self.Sref("_decode_V_NULL", -4) // SREF &_decode_V_NULL, $-4
|
||||
self.Sref("_decode_V_TRUE", -8) // SREF &_decode_V_TRUE, $-8
|
||||
self.Sref("_decode_V_FALSE", -12) // SREF &_decode_V_FALSE, $-12
|
||||
self.Sref("_decode_V_ARRAY", -16) // SREF &_decode_V_ARRAY, $-16
|
||||
self.Sref("_decode_V_OBJECT", -20) // SREF &_decode_V_OBJECT, $-20
|
||||
self.Sref("_decode_V_STRING", -24) // SREF &_decode_V_STRING, $-24
|
||||
self.Sref("_decode_V_DOUBLE", -28) // SREF &_decode_V_DOUBLE, $-28
|
||||
self.Sref("_decode_V_INTEGER", -32) // SREF &_decode_V_INTEGER, $-32
|
||||
self.Sref("_decode_V_KEY_SEP", -36) // SREF &_decode_V_KEY_SEP, $-36
|
||||
self.Sref("_decode_V_ELEM_SEP", -40) // SREF &_decode_V_ELEM_SEP, $-40
|
||||
self.Sref("_decode_V_ARRAY_END", -44) // SREF &_decode_V_ARRAY_END, $-44
|
||||
self.Sref("_decode_V_OBJECT_END", -48) // SREF &_decode_V_OBJECT_END, $-48
|
||||
|
||||
/* fast character lookup table */
|
||||
self.Link("_decode_tab") // _decode_tab:
|
||||
self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0
|
||||
|
||||
/* generate rest of the tabs */
|
||||
for i := 1; i < 256; i++ {
|
||||
if to, ok := _R_tab[i]; ok {
|
||||
self.Sref(to, -int64(i) * 4)
|
||||
} else {
|
||||
self.Byte(0x00, 0x00, 0x00, 0x00)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) WritePtrAX(i int, rec obj.Addr, saveDI bool) {
|
||||
self.Emit("MOVQ", _V_writeBarrier, _R9)
|
||||
self.Emit("CMPL", jit.Ptr(_R9, 0), jit.Imm(0))
|
||||
self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
if saveDI {
|
||||
self.save(_DI)
|
||||
}
|
||||
self.Emit("LEAQ", rec, _DI)
|
||||
self.call(_F_gcWriteBarrierAX)
|
||||
if saveDI {
|
||||
self.load(_DI)
|
||||
}
|
||||
self.Sjmp("JMP", "_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Emit("MOVQ", _AX, rec)
|
||||
self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
}
|
||||
|
||||
func (self *_ValueDecoder) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool) {
|
||||
if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
|
||||
panic("rec contains AX!")
|
||||
}
|
||||
self.Emit("MOVQ", _V_writeBarrier, _AX)
|
||||
self.Emit("CMPL", jit.Ptr(_AX, 0), jit.Imm(0))
|
||||
self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
|
||||
self.Emit("MOVQ", ptr, _AX)
|
||||
if saveDI {
|
||||
self.save(_DI)
|
||||
}
|
||||
self.Emit("LEAQ", rec, _DI)
|
||||
self.call(_F_gcWriteBarrierAX)
|
||||
if saveDI {
|
||||
self.load(_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}")
|
||||
}
|
||||
|
||||
/** Generic Decoder **/
|
||||
|
||||
var (
|
||||
_subr_decode_value = new(_ValueDecoder).build()
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
func invalid_vtype(vt types.ValueType) {
|
||||
throw(fmt.Sprintf("invalid value type: %d", vt))
|
||||
}
|
||||
37
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go117_test.s
generated
vendored
Normal file
37
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_go117_test.s
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// +build go1.17,!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.
|
||||
//
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·decodeValueStub(SB), NOSPLIT, $0 - 72
|
||||
NO_LOCAL_POINTERS
|
||||
PXOR X0, X0
|
||||
MOVOU X0, rv+48(FP)
|
||||
MOVQ st+0(FP) , R13
|
||||
MOVQ sp+8(FP) , R10
|
||||
MOVQ sn+16(FP), R12
|
||||
MOVQ ic+24(FP), R11
|
||||
MOVQ vp+32(FP), R15
|
||||
MOVQ df+40(FP), AX
|
||||
MOVQ ·_subr_decode_value(SB), BX
|
||||
CALL BX
|
||||
MOVQ R11, rp+48(FP)
|
||||
MOVQ BX, ex+56(FP)
|
||||
RET
|
||||
37
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_test.s
generated
vendored
Normal file
37
vendor/github.com/bytedance/sonic/internal/decoder/generic_amd64_test.s
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// +build go1.15,!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.
|
||||
//
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·decodeValueStub(SB), NOSPLIT, $0 - 72
|
||||
NO_LOCAL_POINTERS
|
||||
PXOR X0, X0
|
||||
MOVOU X0, rv+48(FP)
|
||||
MOVQ st+0(FP), BX
|
||||
MOVQ sp+8(FP), R12
|
||||
MOVQ sn+16(FP), R13
|
||||
MOVQ ic+24(FP), R14
|
||||
MOVQ vp+32(FP), R15
|
||||
MOVQ df+40(FP), R10
|
||||
MOVQ ·_subr_decode_value(SB), AX
|
||||
CALL AX
|
||||
MOVQ R14, rp+48(FP)
|
||||
MOVQ R11, ex+56(FP)
|
||||
RET
|
||||
143
vendor/github.com/bytedance/sonic/internal/decoder/pools.go
generated
vendored
Normal file
143
vendor/github.com/bytedance/sonic/internal/decoder/pools.go
generated
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`sync`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/caching`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
const (
|
||||
_MinSlice = 2
|
||||
_MaxStack = 4096 // 4k slots
|
||||
_MaxStackBytes = _MaxStack * _PtrBytes
|
||||
_MaxDigitNums = 800 // used in atof fallback algorithm
|
||||
)
|
||||
|
||||
const (
|
||||
_PtrBytes = _PTR_SIZE / 8
|
||||
_FsmOffset = (_MaxStack + 1) * _PtrBytes
|
||||
_DbufOffset = _FsmOffset + int64(unsafe.Sizeof(types.StateMachine{})) + types.MAX_RECURSE * _PtrBytes
|
||||
_StackSize = unsafe.Sizeof(_Stack{})
|
||||
)
|
||||
|
||||
var (
|
||||
stackPool = sync.Pool{}
|
||||
valueCache = []unsafe.Pointer(nil)
|
||||
fieldCache = []*caching.FieldMap(nil)
|
||||
fieldCacheMux = sync.Mutex{}
|
||||
programCache = caching.CreateProgramCache()
|
||||
)
|
||||
|
||||
type _Stack struct {
|
||||
sp uintptr
|
||||
sb [_MaxStack]unsafe.Pointer
|
||||
mm types.StateMachine
|
||||
vp [types.MAX_RECURSE]unsafe.Pointer
|
||||
dp [_MaxDigitNums]byte
|
||||
}
|
||||
|
||||
type _Decoder func(
|
||||
s string,
|
||||
i int,
|
||||
vp unsafe.Pointer,
|
||||
sb *_Stack,
|
||||
fv uint64,
|
||||
sv string, // DO NOT pass value to this arguement, since it is only used for local _VAR_sv
|
||||
vk unsafe.Pointer, // DO NOT pass value to this arguement, since it is only used for local _VAR_vk
|
||||
) (int, error)
|
||||
|
||||
var _KeepAlive struct {
|
||||
s string
|
||||
i int
|
||||
vp unsafe.Pointer
|
||||
sb *_Stack
|
||||
fv uint64
|
||||
sv string
|
||||
vk unsafe.Pointer
|
||||
|
||||
ret int
|
||||
err error
|
||||
|
||||
frame_decoder [_FP_offs]byte
|
||||
frame_generic [_VD_offs]byte
|
||||
}
|
||||
|
||||
var (
|
||||
argPtrs = []bool{true, false, false, true, true, false, true, false, true}
|
||||
localPtrs = []bool{}
|
||||
)
|
||||
|
||||
var (
|
||||
argPtrs_generic = []bool{true}
|
||||
localPtrs_generic = []bool{}
|
||||
)
|
||||
|
||||
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 freeStack(p *_Stack) {
|
||||
p.sp = 0
|
||||
stackPool.Put(p)
|
||||
}
|
||||
|
||||
func freezeValue(v unsafe.Pointer) uintptr {
|
||||
valueCache = append(valueCache, v)
|
||||
return uintptr(v)
|
||||
}
|
||||
|
||||
func freezeFields(v *caching.FieldMap) int64 {
|
||||
fieldCacheMux.Lock()
|
||||
fieldCache = append(fieldCache, v)
|
||||
fieldCacheMux.Unlock()
|
||||
return referenceFields(v)
|
||||
}
|
||||
|
||||
func referenceFields(v *caching.FieldMap) int64 {
|
||||
return int64(uintptr(unsafe.Pointer(v)))
|
||||
}
|
||||
|
||||
func makeDecoder(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
|
||||
if pp, err := newCompiler().compile(vt.Pack()); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return newAssembler(pp).Load(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func findOrCompile(vt *rt.GoType) (_Decoder, error) {
|
||||
if val := programCache.Get(vt); val != nil {
|
||||
return val.(_Decoder), nil
|
||||
} else if ret, err := programCache.Compute(vt, makeDecoder); err == nil {
|
||||
return ret.(_Decoder), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
46
vendor/github.com/bytedance/sonic/internal/decoder/primitives.go
generated
vendored
Normal file
46
vendor/github.com/bytedance/sonic/internal/decoder/primitives.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`encoding`
|
||||
`encoding/json`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
func decodeTypedPointer(s string, i int, vt *rt.GoType, vp unsafe.Pointer, sb *_Stack, fv uint64) (int, error) {
|
||||
if fn, err := findOrCompile(vt); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
rt.MoreStack(_FP_size + _VD_size + native.MaxFrameSize)
|
||||
rt.StopProf()
|
||||
ret, err := fn(s, i, vp, sb, fv, "", nil)
|
||||
rt.StartProf()
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
|
||||
func decodeJsonUnmarshaler(vv interface{}, s string) error {
|
||||
return vv.(json.Unmarshaler).UnmarshalJSON(rt.Str2Mem(s))
|
||||
}
|
||||
|
||||
func decodeTextUnmarshaler(vv interface{}, s string) error {
|
||||
return vv.(encoding.TextUnmarshaler).UnmarshalText(rt.Str2Mem(s))
|
||||
}
|
||||
217
vendor/github.com/bytedance/sonic/internal/decoder/stream.go
generated
vendored
Normal file
217
vendor/github.com/bytedance/sonic/internal/decoder/stream.go
generated
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`bytes`
|
||||
`io`
|
||||
`sync`
|
||||
|
||||
`github.com/bytedance/sonic/option`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
var (
|
||||
minLeftBufferShift uint = 1
|
||||
)
|
||||
|
||||
// StreamDecoder is the decoder context object for streaming input.
|
||||
type StreamDecoder struct {
|
||||
r io.Reader
|
||||
buf []byte
|
||||
scanp int
|
||||
scanned int64
|
||||
err error
|
||||
Decoder
|
||||
}
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func () interface{} {
|
||||
return make([]byte, 0, option.DefaultDecoderBufferSize)
|
||||
},
|
||||
}
|
||||
|
||||
// NewStreamDecoder adapts to encoding/json.NewDecoder API.
|
||||
//
|
||||
// NewStreamDecoder returns a new decoder that reads from r.
|
||||
func NewStreamDecoder(r io.Reader) *StreamDecoder {
|
||||
return &StreamDecoder{r : r}
|
||||
}
|
||||
|
||||
// Decode decodes input stream into val with corresponding data.
|
||||
// Redundantly bytes may be read and left in its buffer, and can be used at next call.
|
||||
// Either io error from underlying io.Reader (except io.EOF)
|
||||
// or syntax error from data will be recorded and stop subsequently decoding.
|
||||
func (self *StreamDecoder) Decode(val interface{}) (err error) {
|
||||
if self.err != nil {
|
||||
return self.err
|
||||
}
|
||||
|
||||
var buf = self.buf[self.scanp:]
|
||||
var p = 0
|
||||
var recycle bool
|
||||
if cap(buf) == 0 {
|
||||
buf = bufPool.Get().([]byte)
|
||||
recycle = true
|
||||
}
|
||||
|
||||
var first = true
|
||||
var repeat = true
|
||||
read_more:
|
||||
for {
|
||||
l := len(buf)
|
||||
realloc(&buf)
|
||||
n, err := self.r.Read(buf[l:cap(buf)])
|
||||
buf = buf[:l+n]
|
||||
if err != nil {
|
||||
repeat = false
|
||||
if err == io.EOF {
|
||||
if len(buf) == 0 {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
self.err = err
|
||||
return err
|
||||
}
|
||||
if n > 0 || first {
|
||||
break
|
||||
}
|
||||
}
|
||||
first = false
|
||||
|
||||
l := len(buf)
|
||||
if l > 0 {
|
||||
self.Decoder.Reset(string(buf))
|
||||
err = self.Decoder.Decode(val)
|
||||
if err != nil {
|
||||
if repeat && self.repeatable(err) {
|
||||
goto read_more
|
||||
}
|
||||
self.err = err
|
||||
}
|
||||
|
||||
p = self.Decoder.Pos()
|
||||
self.scanned += int64(p)
|
||||
self.scanp = 0
|
||||
}
|
||||
|
||||
if l > p {
|
||||
// remain undecoded bytes, so copy them into self.buf
|
||||
self.buf = append(self.buf[:0], buf[p:]...)
|
||||
} else {
|
||||
self.buf = nil
|
||||
recycle = true
|
||||
}
|
||||
|
||||
if recycle {
|
||||
buf = buf[:0]
|
||||
bufPool.Put(buf)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self StreamDecoder) repeatable(err error) bool {
|
||||
if ee, ok := err.(SyntaxError); ok &&
|
||||
(ee.Code == types.ERR_EOF || (ee.Code == types.ERR_INVALID_CHAR && self.i >= len(self.s)-1)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// InputOffset returns the input stream byte offset of the current decoder position.
|
||||
// The offset gives the location of the end of the most recently returned token and the beginning of the next token.
|
||||
func (self *StreamDecoder) InputOffset() int64 {
|
||||
return self.scanned + int64(self.scanp)
|
||||
}
|
||||
|
||||
// Buffered returns a reader of the data remaining in the Decoder's buffer.
|
||||
// The reader is valid until the next call to Decode.
|
||||
func (self *StreamDecoder) Buffered() io.Reader {
|
||||
return bytes.NewReader(self.buf[self.scanp:])
|
||||
}
|
||||
|
||||
// More reports whether there is another element in the
|
||||
// current array or object being parsed.
|
||||
func (self *StreamDecoder) More() bool {
|
||||
if self.err != nil {
|
||||
return false
|
||||
}
|
||||
c, err := self.peek()
|
||||
return err == nil && c != ']' && c != '}'
|
||||
}
|
||||
|
||||
func (self *StreamDecoder) peek() (byte, error) {
|
||||
var err error
|
||||
for {
|
||||
for i := self.scanp; i < len(self.buf); i++ {
|
||||
c := self.buf[i]
|
||||
if isSpace(c) {
|
||||
continue
|
||||
}
|
||||
self.scanp = i
|
||||
return c, nil
|
||||
}
|
||||
// buffer has been scanned, now report any error
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
self.err = err
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
err = self.refill()
|
||||
}
|
||||
}
|
||||
|
||||
func isSpace(c byte) bool {
|
||||
return types.SPACE_MASK & (1 << c) != 0
|
||||
}
|
||||
|
||||
func (self *StreamDecoder) refill() error {
|
||||
// Make room to read more into the buffer.
|
||||
// First slide down data already consumed.
|
||||
if self.scanp > 0 {
|
||||
self.scanned += int64(self.scanp)
|
||||
n := copy(self.buf, self.buf[self.scanp:])
|
||||
self.buf = self.buf[:n]
|
||||
self.scanp = 0
|
||||
}
|
||||
|
||||
// Grow buffer if not large enough.
|
||||
realloc(&self.buf)
|
||||
|
||||
// Read. Delay error for next iteration (after scan).
|
||||
n, err := self.r.Read(self.buf[len(self.buf):cap(self.buf)])
|
||||
self.buf = self.buf[0 : len(self.buf)+n]
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func realloc(buf *[]byte) {
|
||||
l := uint(len(*buf))
|
||||
c := uint(cap(*buf))
|
||||
if c - l <= c >> minLeftBufferShift {
|
||||
e := l+(l>>minLeftBufferShift)
|
||||
if e < option.DefaultDecoderBufferSize {
|
||||
e = option.DefaultDecoderBufferSize
|
||||
}
|
||||
tmp := make([]byte, l, e)
|
||||
copy(tmp, *buf)
|
||||
*buf = tmp
|
||||
}
|
||||
}
|
||||
|
||||
111
vendor/github.com/bytedance/sonic/internal/decoder/stubs_go115.go
generated
vendored
Normal file
111
vendor/github.com/bytedance/sonic/internal/decoder/stubs_go115.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// +build go1.15,!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 decoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
`reflect`
|
||||
|
||||
_ `github.com/chenzhuoyu/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64decode github.com/chenzhuoyu/base64x._subr__b64decode
|
||||
var _subr__b64decode uintptr
|
||||
|
||||
// runtime.maxElementSize
|
||||
const _max_map_element_size uintptr = 128
|
||||
|
||||
func mapfast(vt reflect.Type) bool {
|
||||
return vt.Elem().Size() <= _max_map_element_size
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
//go:linkname throw runtime.throw
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func throw(s string)
|
||||
|
||||
//go:linkname convT64 runtime.convT64
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convT64(v uint64) unsafe.Pointer
|
||||
|
||||
//go:linkname convTslice runtime.convTslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convTslice(v []byte) unsafe.Pointer
|
||||
|
||||
//go:linkname convTstring runtime.convTstring
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convTstring(v string) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memequal runtime.memequal
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memequal(a unsafe.Pointer, b unsafe.Pointer, size uintptr) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname mallocgc runtime.mallocgc
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mallocgc(size uintptr, typ *rt.GoType, needzero bool) unsafe.Pointer
|
||||
|
||||
//go:linkname makeslice runtime.makeslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func makeslice(et *rt.GoType, len int, cap int) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
//go:linkname growslice runtime.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname makemap_small runtime.makemap_small
|
||||
func makemap_small() unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign runtime.mapassign
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign(t *rt.GoType, h unsafe.Pointer, k unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast32 runtime.mapassign_fast32
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast32(t *rt.GoType, h unsafe.Pointer, k uint32) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast64 runtime.mapassign_fast64
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast64(t *rt.GoType, h unsafe.Pointer, k uint64) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast64ptr runtime.mapassign_fast64ptr
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast64ptr(t *rt.GoType, h unsafe.Pointer, k unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_faststr runtime.mapassign_faststr
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_faststr(t *rt.GoType, h unsafe.Pointer, s string) unsafe.Pointer
|
||||
|
||||
//go:nosplit
|
||||
//go:linkname memclrHasPointers runtime.memclrHasPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrHasPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
111
vendor/github.com/bytedance/sonic/internal/decoder/stubs_go120.go
generated
vendored
Normal file
111
vendor/github.com/bytedance/sonic/internal/decoder/stubs_go120.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// +build 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 decoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
`reflect`
|
||||
|
||||
_ `github.com/chenzhuoyu/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64decode github.com/chenzhuoyu/base64x._subr__b64decode
|
||||
var _subr__b64decode uintptr
|
||||
|
||||
// runtime.maxElementSize
|
||||
const _max_map_element_size uintptr = 128
|
||||
|
||||
func mapfast(vt reflect.Type) bool {
|
||||
return vt.Elem().Size() <= _max_map_element_size
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
//go:linkname throw runtime.throw
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func throw(s string)
|
||||
|
||||
//go:linkname convT64 runtime.convT64
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convT64(v uint64) unsafe.Pointer
|
||||
|
||||
//go:linkname convTslice runtime.convTslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convTslice(v []byte) unsafe.Pointer
|
||||
|
||||
//go:linkname convTstring runtime.convTstring
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func convTstring(v string) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memequal runtime.memequal
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memequal(a unsafe.Pointer, b unsafe.Pointer, size uintptr) bool
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memmove runtime.memmove
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname mallocgc runtime.mallocgc
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mallocgc(size uintptr, typ *rt.GoType, needzero bool) unsafe.Pointer
|
||||
|
||||
//go:linkname makeslice runtime.makeslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func makeslice(et *rt.GoType, len int, cap int) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
//go:linkname growslice reflect.growslice
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
|
||||
|
||||
//go:linkname makemap_small runtime.makemap_small
|
||||
func makemap_small() unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign runtime.mapassign
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign(t *rt.GoType, h unsafe.Pointer, k unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast32 runtime.mapassign_fast32
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast32(t *rt.GoType, h unsafe.Pointer, k uint32) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast64 runtime.mapassign_fast64
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast64(t *rt.GoType, h unsafe.Pointer, k uint64) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_fast64ptr runtime.mapassign_fast64ptr
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_fast64ptr(t *rt.GoType, h unsafe.Pointer, k unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign_faststr runtime.mapassign_faststr
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func mapassign_faststr(t *rt.GoType, h unsafe.Pointer, s string) unsafe.Pointer
|
||||
|
||||
//go:nosplit
|
||||
//go:linkname memclrHasPointers runtime.memclrHasPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrHasPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
58
vendor/github.com/bytedance/sonic/internal/decoder/types.go
generated
vendored
Normal file
58
vendor/github.com/bytedance/sonic/internal/decoder/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`encoding`
|
||||
`encoding/base64`
|
||||
`encoding/json`
|
||||
`reflect`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
var (
|
||||
byteType = reflect.TypeOf(byte(0))
|
||||
intType = reflect.TypeOf(int(0))
|
||||
int8Type = reflect.TypeOf(int8(0))
|
||||
int16Type = reflect.TypeOf(int16(0))
|
||||
int32Type = reflect.TypeOf(int32(0))
|
||||
int64Type = reflect.TypeOf(int64(0))
|
||||
uintType = reflect.TypeOf(uint(0))
|
||||
uint8Type = reflect.TypeOf(uint8(0))
|
||||
uint16Type = reflect.TypeOf(uint16(0))
|
||||
uint32Type = reflect.TypeOf(uint32(0))
|
||||
uint64Type = reflect.TypeOf(uint64(0))
|
||||
float32Type = reflect.TypeOf(float32(0))
|
||||
float64Type = reflect.TypeOf(float64(0))
|
||||
stringType = reflect.TypeOf("")
|
||||
bytesType = reflect.TypeOf([]byte(nil))
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
base64CorruptInputError = reflect.TypeOf(base64.CorruptInputError(0))
|
||||
)
|
||||
|
||||
var (
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
encodingTextUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
func rtype(t reflect.Type) (*rt.GoItab, *rt.GoType) {
|
||||
p := (*rt.GoIface)(unsafe.Pointer(&t))
|
||||
return p.Itab, (*rt.GoType)(p.Value)
|
||||
}
|
||||
39
vendor/github.com/bytedance/sonic/internal/decoder/utils.go
generated
vendored
Normal file
39
vendor/github.com/bytedance/sonic/internal/decoder/utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 decoder
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/loader`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
func pbool(v bool) uintptr {
|
||||
return freezeValue(unsafe.Pointer(&v))
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func ptodec(p loader.Function) _Decoder {
|
||||
return *(*_Decoder)(unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
func assert_eq(v int64, exp int64, msg string) {
|
||||
if v != exp {
|
||||
panic(msg)
|
||||
}
|
||||
}
|
||||
0
vendor/github.com/bytedance/sonic/internal/encoder/asm.s
generated
vendored
Normal file
0
vendor/github.com/bytedance/sonic/internal/encoder/asm.s
generated
vendored
Normal file
1199
vendor/github.com/bytedance/sonic/internal/encoder/assembler_amd64_go116.go
generated
vendored
Normal file
1199
vendor/github.com/bytedance/sonic/internal/encoder/assembler_amd64_go116.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1202
vendor/github.com/bytedance/sonic/internal/encoder/assembler_amd64_go117.go
generated
vendored
Normal file
1202
vendor/github.com/bytedance/sonic/internal/encoder/assembler_amd64_go117.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
885
vendor/github.com/bytedance/sonic/internal/encoder/compiler.go
generated
vendored
Normal file
885
vendor/github.com/bytedance/sonic/internal/encoder/compiler.go
generated
vendored
Normal file
|
|
@ -0,0 +1,885 @@
|
|||
/*
|
||||
* 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`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`strings`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/resolver`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/bytedance/sonic/option`
|
||||
)
|
||||
|
||||
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 (
|
||||
_MAX_ILBUF = 100000 // cutoff at 100k of IL instructions
|
||||
_MAX_FIELDS = 50 // cutoff at 50 fields struct
|
||||
)
|
||||
|
||||
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 {
|
||||
u uint64 // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
|
||||
p unsafe.Pointer // maybe GoString.Ptr, or *GoType
|
||||
}
|
||||
|
||||
func packOp(op _Op) uint64 {
|
||||
return uint64(op) << 56
|
||||
}
|
||||
|
||||
func newInsOp(op _Op) _Instr {
|
||||
return _Instr{u: packOp(op)}
|
||||
}
|
||||
|
||||
func newInsVi(op _Op, vi int) _Instr {
|
||||
return _Instr{u: packOp(op) | rt.PackInt(vi)}
|
||||
}
|
||||
|
||||
func newInsVs(op _Op, vs string) _Instr {
|
||||
return _Instr {
|
||||
u: packOp(op) | rt.PackInt(len(vs)),
|
||||
p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
|
||||
}
|
||||
}
|
||||
|
||||
func newInsVt(op _Op, vt reflect.Type) _Instr {
|
||||
return _Instr {
|
||||
u: packOp(op),
|
||||
p: unsafe.Pointer(rt.UnpackType(vt)),
|
||||
}
|
||||
}
|
||||
|
||||
func newInsVp(op _Op, vt reflect.Type, pv bool) _Instr {
|
||||
i := 0
|
||||
if pv {
|
||||
i = 1
|
||||
}
|
||||
return _Instr {
|
||||
u: packOp(op) | rt.PackInt(i),
|
||||
p: unsafe.Pointer(rt.UnpackType(vt)),
|
||||
}
|
||||
}
|
||||
|
||||
func (self _Instr) op() _Op {
|
||||
return _Op(self.u >> 56)
|
||||
}
|
||||
|
||||
func (self _Instr) vi() int {
|
||||
return rt.UnpackInt(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) vp() (vt reflect.Type, pv bool) {
|
||||
return (*rt.GoType)(self.p).Pack(), rt.UnpackInt(self.u) == 1
|
||||
}
|
||||
|
||||
func (self _Instr) i64() int64 {
|
||||
return int64(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 : fallthrough
|
||||
case _OP_marshal : fallthrough
|
||||
case _OP_marshal_p : fallthrough
|
||||
case _OP_marshal_text : fallthrough
|
||||
case _OP_marshal_text_p : return fmt.Sprintf("%-18s%s", self.op().String(), self.vt())
|
||||
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 self.op().String()
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
_Program []_Instr
|
||||
)
|
||||
|
||||
func (self _Program) pc() int {
|
||||
return len(self)
|
||||
}
|
||||
|
||||
func (self _Program) tag(n int) {
|
||||
if n >= _MaxStack {
|
||||
panic("type nesting too deep")
|
||||
}
|
||||
}
|
||||
|
||||
func (self _Program) pin(i int) {
|
||||
v := &self[i]
|
||||
v.u &= 0xffff000000000000
|
||||
v.u |= rt.PackInt(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) 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")
|
||||
}
|
||||
|
||||
type _Compiler struct {
|
||||
opts option.CompileOptions
|
||||
pv bool
|
||||
tab map[reflect.Type]bool
|
||||
rec map[reflect.Type]uint8
|
||||
}
|
||||
|
||||
func newCompiler() *_Compiler {
|
||||
return &_Compiler {
|
||||
opts: option.DefaultCompileOptions(),
|
||||
tab: map[reflect.Type]bool{},
|
||||
rec: map[reflect.Type]uint8{},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
|
||||
self.opts = opts
|
||||
if self.opts.RecursiveDepth > 0 {
|
||||
self.rec = map[reflect.Type]uint8{}
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *_Compiler) rescue(ep *error) {
|
||||
if val := recover(); val != nil {
|
||||
if err, ok := val.(error); ok {
|
||||
*ep = err
|
||||
} else {
|
||||
panic(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compile(vt reflect.Type, pv bool) (ret _Program, err error) {
|
||||
defer self.rescue(&err)
|
||||
self.compileOne(&ret, 0, vt, pv)
|
||||
return
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type, pv bool) {
|
||||
if self.tab[vt] {
|
||||
p.vp(_OP_recurse, vt, pv)
|
||||
} else {
|
||||
self.compileRec(p, sp, vt, pv)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool) {
|
||||
pr := self.pv
|
||||
pt := reflect.PtrTo(vt)
|
||||
|
||||
/* check for addressable `json.Marshaler` with pointer receiver */
|
||||
if pv && pt.Implements(jsonMarshalerType) {
|
||||
p.rtt(_OP_marshal_p, pt)
|
||||
return
|
||||
}
|
||||
|
||||
/* check for `json.Marshaler` */
|
||||
if vt.Implements(jsonMarshalerType) {
|
||||
self.compileMarshaler(p, _OP_marshal, vt, jsonMarshalerType)
|
||||
return
|
||||
}
|
||||
|
||||
/* check for addressable `encoding.TextMarshaler` with pointer receiver */
|
||||
if pv && pt.Implements(encodingTextMarshalerType) {
|
||||
p.rtt(_OP_marshal_text_p, pt)
|
||||
return
|
||||
}
|
||||
|
||||
/* check for `encoding.TextMarshaler` */
|
||||
if vt.Implements(encodingTextMarshalerType) {
|
||||
self.compileMarshaler(p, _OP_marshal_text, vt, encodingTextMarshalerType)
|
||||
return
|
||||
}
|
||||
|
||||
/* enter the recursion, and compile the type */
|
||||
self.pv = pv
|
||||
self.tab[vt] = true
|
||||
self.compileOps(p, sp, vt)
|
||||
|
||||
/* exit the recursion */
|
||||
self.pv = pr
|
||||
delete(self.tab, vt)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
|
||||
switch vt.Kind() {
|
||||
case reflect.Bool : p.add(_OP_bool)
|
||||
case reflect.Int : p.add(_OP_int())
|
||||
case reflect.Int8 : p.add(_OP_i8)
|
||||
case reflect.Int16 : p.add(_OP_i16)
|
||||
case reflect.Int32 : p.add(_OP_i32)
|
||||
case reflect.Int64 : p.add(_OP_i64)
|
||||
case reflect.Uint : p.add(_OP_uint())
|
||||
case reflect.Uint8 : p.add(_OP_u8)
|
||||
case reflect.Uint16 : p.add(_OP_u16)
|
||||
case reflect.Uint32 : p.add(_OP_u32)
|
||||
case reflect.Uint64 : p.add(_OP_u64)
|
||||
case reflect.Uintptr : p.add(_OP_uintptr())
|
||||
case reflect.Float32 : p.add(_OP_f32)
|
||||
case reflect.Float64 : p.add(_OP_f64)
|
||||
case reflect.String : self.compileString (p, vt)
|
||||
case reflect.Array : self.compileArray (p, sp, vt.Elem(), vt.Len())
|
||||
case reflect.Interface : self.compileInterface (p, vt)
|
||||
case reflect.Map : self.compileMap (p, sp, vt)
|
||||
case reflect.Ptr : self.compilePtr (p, sp, vt.Elem())
|
||||
case reflect.Slice : self.compileSlice (p, sp, vt.Elem())
|
||||
case reflect.Struct : self.compileStruct (p, sp, vt)
|
||||
default : panic (error_type(vt))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileNil(p *_Program, sp int, vt reflect.Type, nil_op _Op, fn func(*_Program, int, reflect.Type)) {
|
||||
x := p.pc()
|
||||
p.add(_OP_is_nil)
|
||||
fn(p, sp, vt)
|
||||
e := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(x)
|
||||
p.add(nil_op)
|
||||
p.pin(e)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compilePtr(p *_Program, sp int, vt reflect.Type) {
|
||||
self.compileNil(p, sp, vt, _OP_null, self.compilePtrBody)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compilePtrBody(p *_Program, sp int, vt reflect.Type) {
|
||||
p.tag(sp)
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_deref)
|
||||
self.compileOne(p, sp + 1, vt, true)
|
||||
p.add(_OP_drop)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
|
||||
self.compileNil(p, sp, vt, _OP_empty_obj, self.compileMapBody)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMapBody(p *_Program, sp int, vt reflect.Type) {
|
||||
p.tag(sp + 1)
|
||||
p.int(_OP_byte, '{')
|
||||
p.add(_OP_save)
|
||||
p.rtt(_OP_map_iter, vt)
|
||||
p.add(_OP_save)
|
||||
i := p.pc()
|
||||
p.add(_OP_map_check_key)
|
||||
u := p.pc()
|
||||
p.add(_OP_map_write_key)
|
||||
self.compileMapBodyKey(p, vt.Key())
|
||||
p.pin(u)
|
||||
p.int(_OP_byte, ':')
|
||||
p.add(_OP_map_value_next)
|
||||
self.compileOne(p, sp + 2, vt.Elem(), false)
|
||||
j := p.pc()
|
||||
p.add(_OP_map_check_key)
|
||||
p.int(_OP_byte, ',')
|
||||
v := p.pc()
|
||||
p.add(_OP_map_write_key)
|
||||
self.compileMapBodyKey(p, vt.Key())
|
||||
p.pin(v)
|
||||
p.int(_OP_byte, ':')
|
||||
p.add(_OP_map_value_next)
|
||||
self.compileOne(p, sp + 2, vt.Elem(), false)
|
||||
p.int(_OP_goto, j)
|
||||
p.pin(i)
|
||||
p.pin(j)
|
||||
p.add(_OP_map_stop)
|
||||
p.add(_OP_drop_2)
|
||||
p.int(_OP_byte, '}')
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMapBodyKey(p *_Program, vk reflect.Type) {
|
||||
if !vk.Implements(encodingTextMarshalerType) {
|
||||
self.compileMapBodyTextKey(p, vk)
|
||||
} else {
|
||||
self.compileMapBodyUtextKey(p, vk)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMapBodyTextKey(p *_Program, vk reflect.Type) {
|
||||
switch vk.Kind() {
|
||||
case reflect.Invalid : panic("map key is nil")
|
||||
case reflect.Bool : p.key(_OP_bool)
|
||||
case reflect.Int : p.key(_OP_int())
|
||||
case reflect.Int8 : p.key(_OP_i8)
|
||||
case reflect.Int16 : p.key(_OP_i16)
|
||||
case reflect.Int32 : p.key(_OP_i32)
|
||||
case reflect.Int64 : p.key(_OP_i64)
|
||||
case reflect.Uint : p.key(_OP_uint())
|
||||
case reflect.Uint8 : p.key(_OP_u8)
|
||||
case reflect.Uint16 : p.key(_OP_u16)
|
||||
case reflect.Uint32 : p.key(_OP_u32)
|
||||
case reflect.Uint64 : p.key(_OP_u64)
|
||||
case reflect.Uintptr : p.key(_OP_uintptr())
|
||||
case reflect.Float32 : p.key(_OP_f32)
|
||||
case reflect.Float64 : p.key(_OP_f64)
|
||||
case reflect.String : self.compileString(p, vk)
|
||||
default : panic(error_type(vk))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMapBodyUtextKey(p *_Program, vk reflect.Type) {
|
||||
if vk.Kind() != reflect.Ptr {
|
||||
p.rtt(_OP_marshal_text, vk)
|
||||
} else {
|
||||
self.compileMapBodyUtextPtr(p, vk)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMapBodyUtextPtr(p *_Program, vk reflect.Type) {
|
||||
i := p.pc()
|
||||
p.add(_OP_is_nil)
|
||||
p.rtt(_OP_marshal_text, vk)
|
||||
j := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(i)
|
||||
p.str(_OP_text, "\"\"")
|
||||
p.pin(j)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
|
||||
self.compileNil(p, sp, vt, _OP_empty_arr, self.compileSliceBody)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSliceBody(p *_Program, sp int, vt reflect.Type) {
|
||||
if isSimpleByte(vt) {
|
||||
p.add(_OP_bin)
|
||||
} else {
|
||||
self.compileSliceArray(p, sp, vt)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSliceArray(p *_Program, sp int, vt reflect.Type) {
|
||||
p.tag(sp)
|
||||
p.int(_OP_byte, '[')
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_slice_len)
|
||||
i := p.pc()
|
||||
p.rtt(_OP_slice_next, vt)
|
||||
self.compileOne(p, sp + 1, vt, true)
|
||||
j := p.pc()
|
||||
p.rtt(_OP_slice_next, vt)
|
||||
p.int(_OP_byte, ',')
|
||||
self.compileOne(p, sp + 1, vt, true)
|
||||
p.int(_OP_goto, j)
|
||||
p.pin(i)
|
||||
p.pin(j)
|
||||
p.add(_OP_drop)
|
||||
p.int(_OP_byte, ']')
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type, nb int) {
|
||||
p.tag(sp)
|
||||
p.int(_OP_byte, '[')
|
||||
p.add(_OP_save)
|
||||
|
||||
/* first item */
|
||||
if nb != 0 {
|
||||
self.compileOne(p, sp + 1, vt, self.pv)
|
||||
p.add(_OP_load)
|
||||
}
|
||||
|
||||
/* remaining items */
|
||||
for i := 1; i < nb; i++ {
|
||||
p.int(_OP_byte, ',')
|
||||
p.int(_OP_index, i * int(vt.Size()))
|
||||
self.compileOne(p, sp + 1, vt, self.pv)
|
||||
p.add(_OP_load)
|
||||
}
|
||||
|
||||
/* end of array */
|
||||
p.add(_OP_drop)
|
||||
p.int(_OP_byte, ']')
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
|
||||
if vt != jsonNumberType {
|
||||
p.add(_OP_str)
|
||||
} else {
|
||||
p.add(_OP_number)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
|
||||
if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
|
||||
p.vp(_OP_recurse, vt, self.pv)
|
||||
if self.opts.RecursiveDepth > 0 {
|
||||
if self.pv {
|
||||
self.rec[vt] = 1
|
||||
} else {
|
||||
self.rec[vt] = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.compileStructBody(p, sp, vt)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
|
||||
p.tag(sp)
|
||||
p.int(_OP_byte, '{')
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_cond_set)
|
||||
|
||||
/* compile each field */
|
||||
for _, fv := range resolver.ResolveStruct(vt) {
|
||||
var s []int
|
||||
var o resolver.Offset
|
||||
|
||||
/* "omitempty" for arrays */
|
||||
if fv.Type.Kind() == reflect.Array {
|
||||
if fv.Type.Len() == 0 && (fv.Opts & resolver.F_omitempty) != 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
/* index to the field */
|
||||
for _, o = range fv.Path {
|
||||
if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
|
||||
s = append(s, p.pc())
|
||||
p.add(_OP_is_nil)
|
||||
p.add(_OP_deref)
|
||||
}
|
||||
}
|
||||
|
||||
/* check for "omitempty" option */
|
||||
if fv.Type.Kind() != reflect.Struct && fv.Type.Kind() != reflect.Array && (fv.Opts & resolver.F_omitempty) != 0 {
|
||||
s = append(s, p.pc())
|
||||
self.compileStructFieldZero(p, fv.Type)
|
||||
}
|
||||
|
||||
/* add the comma if not the first element */
|
||||
i := p.pc()
|
||||
p.add(_OP_cond_testc)
|
||||
p.int(_OP_byte, ',')
|
||||
p.pin(i)
|
||||
|
||||
/* compile the key and value */
|
||||
ft := fv.Type
|
||||
p.str(_OP_text, Quote(fv.Name) + ":")
|
||||
|
||||
/* check for "stringnize" option */
|
||||
if (fv.Opts & resolver.F_stringize) == 0 {
|
||||
self.compileOne(p, sp + 1, ft, self.pv)
|
||||
} else {
|
||||
self.compileStructFieldStr(p, sp + 1, ft)
|
||||
}
|
||||
|
||||
/* patch the skipping jumps and reload the struct pointer */
|
||||
p.rel(s)
|
||||
p.add(_OP_load)
|
||||
}
|
||||
|
||||
/* end of object */
|
||||
p.add(_OP_drop)
|
||||
p.int(_OP_byte, '}')
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
|
||||
pc := -1
|
||||
ft := vt
|
||||
sv := false
|
||||
|
||||
/* dereference the pointer if needed */
|
||||
if ft.Kind() == reflect.Ptr {
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
/* check if it can be stringized */
|
||||
switch ft.Kind() {
|
||||
case reflect.Bool : sv = true
|
||||
case reflect.Int : sv = true
|
||||
case reflect.Int8 : sv = true
|
||||
case reflect.Int16 : sv = true
|
||||
case reflect.Int32 : sv = true
|
||||
case reflect.Int64 : sv = true
|
||||
case reflect.Uint : sv = true
|
||||
case reflect.Uint8 : sv = true
|
||||
case reflect.Uint16 : sv = true
|
||||
case reflect.Uint32 : sv = true
|
||||
case reflect.Uint64 : sv = true
|
||||
case reflect.Uintptr : sv = true
|
||||
case reflect.Float32 : sv = true
|
||||
case reflect.Float64 : sv = true
|
||||
case reflect.String : sv = true
|
||||
}
|
||||
|
||||
/* if it's not, ignore the "string" and follow the regular path */
|
||||
if !sv {
|
||||
self.compileOne(p, sp, vt, self.pv)
|
||||
return
|
||||
}
|
||||
|
||||
/* dereference the pointer */
|
||||
if vt.Kind() == reflect.Ptr {
|
||||
pc = p.pc()
|
||||
vt = vt.Elem()
|
||||
p.add(_OP_is_nil)
|
||||
p.add(_OP_deref)
|
||||
}
|
||||
|
||||
/* special case of a double-quoted string */
|
||||
if ft != jsonNumberType && ft.Kind() == reflect.String {
|
||||
p.add(_OP_quote)
|
||||
} else {
|
||||
self.compileStructFieldQuoted(p, sp, vt)
|
||||
}
|
||||
|
||||
/* the "null" case of the pointer */
|
||||
if pc != -1 {
|
||||
e := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(pc)
|
||||
p.add(_OP_null)
|
||||
p.pin(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStructFieldZero(p *_Program, vt reflect.Type) {
|
||||
switch vt.Kind() {
|
||||
case reflect.Bool : p.add(_OP_is_zero_1)
|
||||
case reflect.Int : p.add(_OP_is_zero_ints())
|
||||
case reflect.Int8 : p.add(_OP_is_zero_1)
|
||||
case reflect.Int16 : p.add(_OP_is_zero_2)
|
||||
case reflect.Int32 : p.add(_OP_is_zero_4)
|
||||
case reflect.Int64 : p.add(_OP_is_zero_8)
|
||||
case reflect.Uint : p.add(_OP_is_zero_ints())
|
||||
case reflect.Uint8 : p.add(_OP_is_zero_1)
|
||||
case reflect.Uint16 : p.add(_OP_is_zero_2)
|
||||
case reflect.Uint32 : p.add(_OP_is_zero_4)
|
||||
case reflect.Uint64 : p.add(_OP_is_zero_8)
|
||||
case reflect.Uintptr : p.add(_OP_is_nil)
|
||||
case reflect.Float32 : p.add(_OP_is_zero_4)
|
||||
case reflect.Float64 : p.add(_OP_is_zero_8)
|
||||
case reflect.String : p.add(_OP_is_nil_p1)
|
||||
case reflect.Interface : p.add(_OP_is_nil_p1)
|
||||
case reflect.Map : p.add(_OP_is_zero_map)
|
||||
case reflect.Ptr : p.add(_OP_is_nil)
|
||||
case reflect.Slice : p.add(_OP_is_nil_p1)
|
||||
default : panic(error_type(vt))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStructFieldQuoted(p *_Program, sp int, vt reflect.Type) {
|
||||
p.int(_OP_byte, '"')
|
||||
self.compileOne(p, sp, vt, self.pv)
|
||||
p.int(_OP_byte, '"')
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
|
||||
x := p.pc()
|
||||
p.add(_OP_is_nil_p1)
|
||||
|
||||
/* iface and efaces are different */
|
||||
if vt.NumMethod() == 0 {
|
||||
p.add(_OP_eface)
|
||||
} else {
|
||||
p.add(_OP_iface)
|
||||
}
|
||||
|
||||
/* the "null" value */
|
||||
e := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(x)
|
||||
p.add(_OP_null)
|
||||
p.pin(e)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt reflect.Type) {
|
||||
pc := p.pc()
|
||||
vk := vt.Kind()
|
||||
|
||||
/* direct receiver */
|
||||
if vk != reflect.Ptr {
|
||||
p.rtt(op, vt)
|
||||
return
|
||||
}
|
||||
|
||||
/* value receiver with a pointer type, check for nil before calling the marshaler */
|
||||
p.add(_OP_is_nil)
|
||||
p.rtt(op, vt)
|
||||
i := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(pc)
|
||||
p.add(_OP_null)
|
||||
p.pin(i)
|
||||
}
|
||||
66
vendor/github.com/bytedance/sonic/internal/encoder/debug_go116.go
generated
vendored
Normal file
66
vendor/github.com/bytedance/sonic/internal/encoder/debug_go116.go
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// +build go1.15,!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 (
|
||||
`os`
|
||||
`strings`
|
||||
`runtime`
|
||||
`runtime/debug`
|
||||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
)
|
||||
|
||||
var (
|
||||
debugSyncGC = os.Getenv("SONIC_SYNC_GC") != ""
|
||||
debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
|
||||
)
|
||||
|
||||
var (
|
||||
_Instr_End _Instr = newInsOp(_OP_null)
|
||||
|
||||
_F_gc = jit.Func(runtime.GC)
|
||||
_F_force_gc = jit.Func(debug.FreeOSMemory)
|
||||
_F_println = jit.Func(println_wrapper)
|
||||
)
|
||||
|
||||
func println_wrapper(i int, op1 int, op2 int){
|
||||
println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2])
|
||||
}
|
||||
|
||||
func (self *_Assembler) force_gc() {
|
||||
self.call_go(_F_gc)
|
||||
self.call_go(_F_force_gc)
|
||||
}
|
||||
|
||||
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.force_gc()
|
||||
}
|
||||
}
|
||||
205
vendor/github.com/bytedance/sonic/internal/encoder/debug_go117.go
generated
vendored
Normal file
205
vendor/github.com/bytedance/sonic/internal/encoder/debug_go117.go
generated
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
// +build go1.17,!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 (
|
||||
`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...)
|
||||
}
|
||||
328
vendor/github.com/bytedance/sonic/internal/encoder/encoder.go
generated
vendored
Normal file
328
vendor/github.com/bytedance/sonic/internal/encoder/encoder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* 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`
|
||||
`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`
|
||||
)
|
||||
|
||||
// Options is a set of encoding options.
|
||||
type Options uint64
|
||||
|
||||
const (
|
||||
bitSortMapKeys = iota
|
||||
bitEscapeHTML
|
||||
bitCompactMarshaler
|
||||
bitNoQuoteTextMarshaler
|
||||
bitNoNullSliceOrMap
|
||||
bitValidateString
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// CompactMarshaler indicates that the output JSON from json.Marshaler
|
||||
// is always compact and needs no validation
|
||||
CompactMarshaler Options = 1 << bitCompactMarshaler
|
||||
|
||||
// NoQuoteTextMarshaler indicates that the output text from encoding.TextMarshaler
|
||||
// is always escaped string and needs no quoting
|
||||
NoQuoteTextMarshaler Options = 1 << bitNoQuoteTextMarshaler
|
||||
|
||||
// NoNullSliceOrMap indicates all empty Array or Object are encoded as '[]' or '{}',
|
||||
// instead of 'null'
|
||||
NoNullSliceOrMap Options = 1 << bitNoNullSliceOrMap
|
||||
|
||||
// ValidateString indicates that encoder should validate the input string
|
||||
// before encoding it into JSON.
|
||||
ValidateString Options = 1 << bitValidateString
|
||||
|
||||
// CompatibleWithStd is used to be compatible with std encoder.
|
||||
CompatibleWithStd Options = SortMapKeys | EscapeHTML | CompactMarshaler
|
||||
)
|
||||
|
||||
// Encoder represents a specific set of encoder configurations.
|
||||
type Encoder struct {
|
||||
Opts Options
|
||||
prefix string
|
||||
indent string
|
||||
}
|
||||
|
||||
// Encode returns the JSON encoding of v.
|
||||
func (self *Encoder) Encode(v interface{}) ([]byte, error) {
|
||||
if self.indent != "" || self.prefix != "" {
|
||||
return EncodeIndented(v, self.prefix, self.indent, self.Opts)
|
||||
}
|
||||
return Encode(v, self.Opts)
|
||||
}
|
||||
|
||||
// SortKeys enables the SortMapKeys option.
|
||||
func (self *Encoder) SortKeys() *Encoder {
|
||||
self.Opts |= SortMapKeys
|
||||
return self
|
||||
}
|
||||
|
||||
// SetEscapeHTML specifies if option EscapeHTML opens
|
||||
func (self *Encoder) SetEscapeHTML(f bool) {
|
||||
if f {
|
||||
self.Opts |= EscapeHTML
|
||||
} else {
|
||||
self.Opts &= ^EscapeHTML
|
||||
}
|
||||
}
|
||||
|
||||
// SetValidateString specifies if option ValidateString opens
|
||||
func (self *Encoder) SetValidateString(f bool) {
|
||||
if f {
|
||||
self.Opts |= ValidateString
|
||||
} else {
|
||||
self.Opts &= ^ValidateString
|
||||
}
|
||||
}
|
||||
|
||||
// SetCompactMarshaler specifies if option CompactMarshaler opens
|
||||
func (self *Encoder) SetCompactMarshaler(f bool) {
|
||||
if f {
|
||||
self.Opts |= CompactMarshaler
|
||||
} else {
|
||||
self.Opts &= ^CompactMarshaler
|
||||
}
|
||||
}
|
||||
|
||||
// SetNoQuoteTextMarshaler specifies if option NoQuoteTextMarshaler opens
|
||||
func (self *Encoder) SetNoQuoteTextMarshaler(f bool) {
|
||||
if f {
|
||||
self.Opts |= NoQuoteTextMarshaler
|
||||
} else {
|
||||
self.Opts &= ^NoQuoteTextMarshaler
|
||||
}
|
||||
}
|
||||
|
||||
// SetIndent instructs the encoder to format each subsequent encoded
|
||||
// value as if indented by the package-level function EncodeIndent().
|
||||
// Calling SetIndent("", "") disables indentation.
|
||||
func (enc *Encoder) SetIndent(prefix, indent string) {
|
||||
enc.prefix = prefix
|
||||
enc.indent = indent
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
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
|
||||
|
||||
/* return when allocated a new buffer */
|
||||
if pbuf != pold {
|
||||
freeBytes(old)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
/* make a copy of the result */
|
||||
ret = make([]byte, len(buf))
|
||||
copy(ret, buf)
|
||||
|
||||
freeBytes(buf)
|
||||
/* return the buffer into pool */
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*buf = encodeFinish(*buf, opts)
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeInto(buf *[]byte, val interface{}, opts Options) error {
|
||||
stk := 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)
|
||||
}
|
||||
freeStack(stk)
|
||||
|
||||
/* avoid GC ahead */
|
||||
runtime.KeepAlive(buf)
|
||||
runtime.KeepAlive(efv)
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeFinish(buf []byte, opts Options) []byte {
|
||||
if opts & EscapeHTML != 0 {
|
||||
buf = HTMLEscape(nil, 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
|
||||
// so that the JSON will be safe to embed inside HTML <script> tags.
|
||||
// For historical reasons, web browsers don't honor standard HTML
|
||||
// escaping within <script> tags, so an alternative JSON encoding must
|
||||
// be used.
|
||||
func HTMLEscape(dst []byte, src []byte) []byte {
|
||||
return htmlEscape(dst, src)
|
||||
}
|
||||
|
||||
// EncodeIndented is like Encode but applies Indent to format the output.
|
||||
// Each JSON element in the output will begin on a new line beginning with prefix
|
||||
// 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)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
freeBytes(out)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* indent the JSON */
|
||||
buf = newBuffer()
|
||||
err = json.Indent(buf, out, prefix, indent)
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
freeBytes(out)
|
||||
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)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
|
||||
// order to reduce the first-hit latency.
|
||||
//
|
||||
// Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
|
||||
// a compile option to set the depth of recursive compile for the nested struct type.
|
||||
func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
|
||||
cfg := option.DefaultCompileOptions()
|
||||
for _, opt := range opts {
|
||||
opt(&cfg)
|
||||
break
|
||||
}
|
||||
return pretouchRec(map[reflect.Type]uint8{vt: 0}, cfg)
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
65
vendor/github.com/bytedance/sonic/internal/encoder/errors.go
generated
vendored
Normal file
65
vendor/github.com/bytedance/sonic/internal/encoder/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
var _ERR_too_deep = &json.UnsupportedValueError {
|
||||
Str : "Value nesting too deep",
|
||||
Value : reflect.ValueOf("..."),
|
||||
}
|
||||
|
||||
var _ERR_nan_or_infinite = &json.UnsupportedValueError {
|
||||
Str : "NaN or ±Infinite",
|
||||
Value : reflect.ValueOf("NaN or ±Infinite"),
|
||||
}
|
||||
|
||||
func error_type(vtype reflect.Type) error {
|
||||
return &json.UnsupportedTypeError{Type: vtype}
|
||||
}
|
||||
|
||||
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 {
|
||||
return fmt.Errorf("invalid Marshaler output json syntax at %d: %q", pos, ret)
|
||||
}
|
||||
|
||||
const (
|
||||
panicNilPointerOfNonEmptyString int = 1 + iota
|
||||
)
|
||||
|
||||
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)))
|
||||
default:
|
||||
panic("encoder error!")
|
||||
}
|
||||
}
|
||||
199
vendor/github.com/bytedance/sonic/internal/encoder/mapiter.go
generated
vendored
Normal file
199
vendor/github.com/bytedance/sonic/internal/encoder/mapiter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* 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"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/native"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type _MapPair struct {
|
||||
k string // when the map key is integer, k is pointed to m
|
||||
v unsafe.Pointer
|
||||
m [32]byte
|
||||
}
|
||||
|
||||
type _MapIterator struct {
|
||||
it rt.GoMapIterator // must be the first field
|
||||
kv rt.GoSlice // slice of _MapPair
|
||||
ki int
|
||||
}
|
||||
|
||||
var (
|
||||
iteratorPool = sync.Pool{}
|
||||
iteratorPair = rt.UnpackType(reflect.TypeOf(_MapPair{}))
|
||||
)
|
||||
|
||||
func init() {
|
||||
if unsafe.Offsetof(_MapIterator{}.it) != 0 {
|
||||
panic("_MapIterator.it is not the first field")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func newIterator() *_MapIterator {
|
||||
if v := iteratorPool.Get(); v == nil {
|
||||
return new(_MapIterator)
|
||||
} else {
|
||||
return resetIterator(v.(*_MapIterator))
|
||||
}
|
||||
}
|
||||
|
||||
func resetIterator(p *_MapIterator) *_MapIterator {
|
||||
p.ki = 0
|
||||
p.it = rt.GoMapIterator{}
|
||||
p.kv.Len = 0
|
||||
return p
|
||||
}
|
||||
|
||||
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) {
|
||||
p = self.at(self.kv.Len)
|
||||
self.kv.Len++
|
||||
return
|
||||
}
|
||||
|
||||
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) {
|
||||
p := self.add()
|
||||
p.v = v
|
||||
|
||||
/* check for strings */
|
||||
if tk := t.Kind(); tk != reflect.String {
|
||||
return self.appendGeneric(p, t, tk, k)
|
||||
}
|
||||
|
||||
/* fast path for strings */
|
||||
p.k = *(*string)(k)
|
||||
return nil
|
||||
}
|
||||
|
||||
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.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) {
|
||||
// compiler has already checked that the type implements the encoding.MarshalText interface
|
||||
if !t.Indirect() {
|
||||
k = *(*unsafe.Pointer)(k)
|
||||
}
|
||||
eface := rt.GoEface{Value: k, Type: t}.Pack()
|
||||
out, err := eface.(encoding.TextMarshaler).MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.k = rt.Mem2Str(out)
|
||||
return
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func iteratorStop(p *_MapIterator) {
|
||||
iteratorPool.Put(p)
|
||||
}
|
||||
|
||||
func iteratorNext(p *_MapIterator) {
|
||||
i := p.ki
|
||||
t := &p.it
|
||||
|
||||
/* check for unordered iteration */
|
||||
if i < 0 {
|
||||
mapiternext(t)
|
||||
return
|
||||
}
|
||||
|
||||
/* check for end of iteration */
|
||||
if p.ki >= p.kv.Len {
|
||||
t.K = nil
|
||||
t.V = nil
|
||||
return
|
||||
}
|
||||
|
||||
/* update the key-value pair, and increase the pointer */
|
||||
t.K = unsafe.Pointer(&p.at(p.ki).k)
|
||||
t.V = p.at(p.ki).v
|
||||
p.ki++
|
||||
}
|
||||
|
||||
func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, error) {
|
||||
it := newIterator()
|
||||
mapiterinit(t, m, &it.it)
|
||||
|
||||
/* check for key-sorting, empty map don't need sorting */
|
||||
if m.Count == 0 || (fv & uint64(SortMapKeys)) == 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)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the keys, map with only 1 item don't need sorting */
|
||||
if it.ki = 1; m.Count > 1 {
|
||||
radixQsort(it.data(), 0, maxDepth(it.kv.Len))
|
||||
}
|
||||
|
||||
/* load the first pair into iterator */
|
||||
it.it.V = it.at(0).v
|
||||
it.it.K = unsafe.Pointer(&it.at(0).k)
|
||||
return it, nil
|
||||
}
|
||||
193
vendor/github.com/bytedance/sonic/internal/encoder/pools.go
generated
vendored
Normal file
193
vendor/github.com/bytedance/sonic/internal/encoder/pools.go
generated
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* 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)
|
||||
}
|
||||
168
vendor/github.com/bytedance/sonic/internal/encoder/primitives.go
generated
vendored
Normal file
168
vendor/github.com/bytedance/sonic/internal/encoder/primitives.go
generated
vendored
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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/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)
|
||||
rt.StopProf()
|
||||
err := fn(buf, *vp, sb, fv)
|
||||
rt.StartProf()
|
||||
return err
|
||||
} else {
|
||||
rt.MoreStack(_FP_size + native.MaxFrameSize)
|
||||
rt.StopProf()
|
||||
err := fn(buf, unsafe.Pointer(vp), sb, fv)
|
||||
rt.StartProf()
|
||||
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 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) + native.BufPaddingSize {
|
||||
cap := len(src) * 3 / 2 + native.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(assertI2I)
|
||||
)
|
||||
|
||||
func asText(v unsafe.Pointer) (string, error) {
|
||||
text := assertI2I(_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 := assertI2I(_T_json_Marshaler, *(*rt.GoIface)(v))
|
||||
r, e := (*(*json.Marshaler)(unsafe.Pointer(&text))).MarshalJSON()
|
||||
return rt.Mem2Str(r), e
|
||||
}
|
||||
206
vendor/github.com/bytedance/sonic/internal/encoder/sort.go
generated
vendored
Normal file
206
vendor/github.com/bytedance/sonic/internal/encoder/sort.go
generated
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
// Algorithm 3-way Radix Quicksort, d means the radix.
|
||||
// Reference: https://algs4.cs.princeton.edu/51radix/Quick3string.java.html
|
||||
func radixQsort(kvs []_MapPair, d, maxDepth int) {
|
||||
for len(kvs) > 11 {
|
||||
// To avoid the worst case of quickSort (time: O(n^2)), use introsort here.
|
||||
// Reference: https://en.wikipedia.org/wiki/Introsort and
|
||||
// https://github.com/golang/go/issues/467
|
||||
if maxDepth == 0 {
|
||||
heapSort(kvs, 0, len(kvs))
|
||||
return
|
||||
}
|
||||
maxDepth--
|
||||
|
||||
p := pivot(kvs, d)
|
||||
lt, i, gt := 0, 0, len(kvs)
|
||||
for i < gt {
|
||||
c := byteAt(kvs[i].k, d)
|
||||
if c < p {
|
||||
swap(kvs, lt, i)
|
||||
i++
|
||||
lt++
|
||||
} else if c > p {
|
||||
gt--
|
||||
swap(kvs, i, gt)
|
||||
} else {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// kvs[0:lt] < v = kvs[lt:gt] < kvs[gt:len(kvs)]
|
||||
// Native implemention:
|
||||
// radixQsort(kvs[:lt], d, maxDepth)
|
||||
// if p > -1 {
|
||||
// radixQsort(kvs[lt:gt], d+1, maxDepth)
|
||||
// }
|
||||
// radixQsort(kvs[gt:], d, maxDepth)
|
||||
// Optimize as follows: make recursive calls only for the smaller parts.
|
||||
// Reference: https://www.geeksforgeeks.org/quicksort-tail-call-optimization-reducing-worst-case-space-log-n/
|
||||
if p == -1 {
|
||||
if lt > len(kvs) - gt {
|
||||
radixQsort(kvs[gt:], d, maxDepth)
|
||||
kvs = kvs[:lt]
|
||||
} else {
|
||||
radixQsort(kvs[:lt], d, maxDepth)
|
||||
kvs = kvs[gt:]
|
||||
}
|
||||
} else {
|
||||
ml := maxThree(lt, gt-lt, len(kvs)-gt)
|
||||
if ml == lt {
|
||||
radixQsort(kvs[lt:gt], d+1, maxDepth)
|
||||
radixQsort(kvs[gt:], d, maxDepth)
|
||||
kvs = kvs[:lt]
|
||||
} else if ml == gt-lt {
|
||||
radixQsort(kvs[:lt], d, maxDepth)
|
||||
radixQsort(kvs[gt:], d, maxDepth)
|
||||
kvs = kvs[lt:gt]
|
||||
d += 1
|
||||
} else {
|
||||
radixQsort(kvs[:lt], d, maxDepth)
|
||||
radixQsort(kvs[lt:gt], d+1, maxDepth)
|
||||
kvs = kvs[gt:]
|
||||
}
|
||||
}
|
||||
}
|
||||
insertRadixSort(kvs, d)
|
||||
}
|
||||
|
||||
func insertRadixSort(kvs []_MapPair, d int) {
|
||||
for i := 1; i < len(kvs); i++ {
|
||||
for j := i; j > 0 && lessFrom(kvs[j].k, kvs[j-1].k, d); j-- {
|
||||
swap(kvs, j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pivot(kvs []_MapPair, d int) int {
|
||||
m := len(kvs) >> 1
|
||||
if len(kvs) > 40 {
|
||||
// Tukey's ``Ninther,'' median of three mediankvs of three.
|
||||
t := len(kvs) / 8
|
||||
return medianThree(
|
||||
medianThree(byteAt(kvs[0].k, d), byteAt(kvs[t].k, d), byteAt(kvs[2*t].k, d)),
|
||||
medianThree(byteAt(kvs[m].k, d), byteAt(kvs[m-t].k, d), byteAt(kvs[m+t].k, d)),
|
||||
medianThree(byteAt(kvs[len(kvs)-1].k, d),
|
||||
byteAt(kvs[len(kvs)-1-t].k, d),
|
||||
byteAt(kvs[len(kvs)-1-2*t].k, d)))
|
||||
}
|
||||
return medianThree(byteAt(kvs[0].k, d), byteAt(kvs[m].k, d), byteAt(kvs[len(kvs)-1].k, d))
|
||||
}
|
||||
|
||||
func medianThree(i, j, k int) int {
|
||||
if i > j {
|
||||
i, j = j, i
|
||||
} // i < j
|
||||
if k < i {
|
||||
return i
|
||||
}
|
||||
if k > j {
|
||||
return j
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
func maxThree(i, j, k int) int {
|
||||
max := i
|
||||
if max < j {
|
||||
max = j
|
||||
}
|
||||
if max < k {
|
||||
max = k
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
// maxDepth returns a threshold at which quicksort should switch
|
||||
// to heapsort. It returnkvs 2*ceil(lg(n+1)).
|
||||
func maxDepth(n int) int {
|
||||
var depth int
|
||||
for i := n; i > 0; i >>= 1 {
|
||||
depth++
|
||||
}
|
||||
return depth * 2
|
||||
}
|
||||
|
||||
// siftDown implements the heap property on kvs[lo:hi].
|
||||
// first is an offset into the array where the root of the heap lies.
|
||||
func siftDown(kvs []_MapPair, lo, hi, first int) {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && kvs[first+child].k < kvs[first+child+1].k {
|
||||
child++
|
||||
}
|
||||
if kvs[first+root].k >= kvs[first+child].k {
|
||||
return
|
||||
}
|
||||
swap(kvs, first+root, first+child)
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
func heapSort(kvs []_MapPair, a, b int) {
|
||||
first := a
|
||||
lo := 0
|
||||
hi := b - a
|
||||
|
||||
// Build heap with the greatest element at top.
|
||||
for i := (hi - 1) / 2; i >= 0; i-- {
|
||||
siftDown(kvs, i, hi, first)
|
||||
}
|
||||
|
||||
// Pop elements, the largest first, into end of kvs.
|
||||
for i := hi - 1; i >= 0; i-- {
|
||||
swap(kvs, first, first+i)
|
||||
siftDown(kvs, lo, i, first)
|
||||
}
|
||||
}
|
||||
|
||||
// Note that _MapPair.k is NOT pointed to _MapPair.m when map key is integer after swap
|
||||
func swap(kvs []_MapPair, a, b int) {
|
||||
kvs[a].k, kvs[b].k = kvs[b].k, kvs[a].k
|
||||
kvs[a].v, kvs[b].v = kvs[b].v, kvs[a].v
|
||||
}
|
||||
|
||||
// Compare two strings from the pos d.
|
||||
func lessFrom(a, b string, d int) bool {
|
||||
l := len(a)
|
||||
if l > len(b) {
|
||||
l = len(b)
|
||||
}
|
||||
for i := d; i < l; i++ {
|
||||
if a[i] == b[i] {
|
||||
continue
|
||||
}
|
||||
return a[i] < b[i]
|
||||
}
|
||||
return len(a) < len(b)
|
||||
}
|
||||
|
||||
func byteAt(b string, p int) int {
|
||||
if p < len(b) {
|
||||
return int(b[p])
|
||||
}
|
||||
return -1
|
||||
}
|
||||
84
vendor/github.com/bytedance/sonic/internal/encoder/stream.go
generated
vendored
Normal file
84
vendor/github.com/bytedance/sonic/internal/encoder/stream.go
generated
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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`
|
||||
`io`
|
||||
)
|
||||
|
||||
// StreamEncoder uses io.Writer as input.
|
||||
type StreamEncoder struct {
|
||||
w io.Writer
|
||||
Encoder
|
||||
}
|
||||
|
||||
// NewStreamEncoder adapts to encoding/json.NewDecoder API.
|
||||
//
|
||||
// NewStreamEncoder returns a new encoder that write to w.
|
||||
func NewStreamEncoder(w io.Writer) *StreamEncoder {
|
||||
return &StreamEncoder{w: w}
|
||||
}
|
||||
|
||||
// Encode encodes interface{} as JSON to io.Writer
|
||||
func (enc *StreamEncoder) Encode(val interface{}) (err error) {
|
||||
out := newBytes()
|
||||
|
||||
/* encode into the buffer */
|
||||
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)
|
||||
if err != nil {
|
||||
freeBuffer(buf)
|
||||
goto free_bytes
|
||||
}
|
||||
|
||||
// according to standard library, terminate each value with a newline...
|
||||
buf.WriteByte('\n')
|
||||
|
||||
/* copy into io.Writer */
|
||||
_, err = io.Copy(enc.w, buf)
|
||||
if err != nil {
|
||||
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:]
|
||||
if err != nil {
|
||||
goto free_bytes
|
||||
}
|
||||
}
|
||||
|
||||
// according to standard library, terminate each value with a newline...
|
||||
enc.w.Write([]byte{'\n'})
|
||||
}
|
||||
|
||||
free_bytes:
|
||||
freeBytes(out)
|
||||
return err
|
||||
}
|
||||
65
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go116.go
generated
vendored
Normal file
65
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go116.go
generated
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// +build go1.15,!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/chenzhuoyu/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/chenzhuoyu/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 assertI2I runtime.assertI2I
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface
|
||||
|
||||
//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()
|
||||
66
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go117.go
generated
vendored
Normal file
66
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go117.go
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// +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/chenzhuoyu/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/chenzhuoyu/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 assertI2I runtime.assertI2I2
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface
|
||||
|
||||
//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()
|
||||
66
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go120.go
generated
vendored
Normal file
66
vendor/github.com/bytedance/sonic/internal/encoder/stubs_go120.go
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// +build 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/chenzhuoyu/base64x`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
//go:linkname _subr__b64encode github.com/chenzhuoyu/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 assertI2I runtime.assertI2I2
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func assertI2I(inter *rt.GoType, i rt.GoIface) rt.GoIface
|
||||
|
||||
//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()
|
||||
47
vendor/github.com/bytedance/sonic/internal/encoder/types.go
generated
vendored
Normal file
47
vendor/github.com/bytedance/sonic/internal/encoder/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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`
|
||||
`reflect`
|
||||
)
|
||||
|
||||
var (
|
||||
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()
|
||||
)
|
||||
|
||||
func isSimpleByte(vt reflect.Type) bool {
|
||||
if vt.Kind() != byteType.Kind() {
|
||||
return false
|
||||
} else {
|
||||
return !isEitherMarshaler(vt) && !isEitherMarshaler(reflect.PtrTo(vt))
|
||||
}
|
||||
}
|
||||
|
||||
func isEitherMarshaler(vt reflect.Type) bool {
|
||||
return vt.Implements(jsonMarshalerType) || vt.Implements(encodingTextMarshalerType)
|
||||
}
|
||||
52
vendor/github.com/bytedance/sonic/internal/encoder/utils.go
generated
vendored
Normal file
52
vendor/github.com/bytedance/sonic/internal/encoder/utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
12
vendor/github.com/bytedance/sonic/internal/jit/assembler_amd64.go
generated
vendored
12
vendor/github.com/bytedance/sonic/internal/jit/assembler_amd64.go
generated
vendored
|
|
@ -72,6 +72,18 @@ func (self *BaseAssembler) NOPn(n int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *BaseAssembler) StorePtr(ptr int64, to obj.Addr, tmp obj.Addr) {
|
||||
if (to.Type != obj.TYPE_MEM) || (tmp.Type != obj.TYPE_REG) {
|
||||
panic("must store imm to memory, tmp must be register")
|
||||
}
|
||||
if (ptr >> 32) != 0 {
|
||||
self.Emit("MOVQ", Imm(ptr), tmp)
|
||||
self.Emit("MOVQ", tmp, to)
|
||||
} else {
|
||||
self.Emit("MOVQ", Imm(ptr), to);
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BaseAssembler) Byte(v ...byte) {
|
||||
for ; len(v) >= 8; v = v[8:] { self.From("QUAD", Imm(rt.Get64(v))) }
|
||||
for ; len(v) >= 4; v = v[4:] { self.From("LONG", Imm(int64(rt.Get32(v)))) }
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/avx/native_amd64.go
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/avx/native_amd64.go
generated
vendored
|
|
@ -122,7 +122,7 @@ func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}) (ret int)
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
|
|||
16296
vendor/github.com/bytedance/sonic/internal/native/avx/native_amd64.s
generated
vendored
16296
vendor/github.com/bytedance/sonic/internal/native/avx/native_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
62
vendor/github.com/bytedance/sonic/internal/native/avx/native_subr_amd64.go
generated
vendored
62
vendor/github.com/bytedance/sonic/internal/native/avx/native_subr_amd64.go
generated
vendored
|
|
@ -9,53 +9,53 @@ package avx
|
|||
func __native_entry__() uintptr
|
||||
|
||||
var (
|
||||
_subr__f32toa = __native_entry__() + 29744
|
||||
_subr__f64toa = __native_entry__() + 496
|
||||
_subr__get_by_path = __native_entry__() + 27424
|
||||
_subr__html_escape = __native_entry__() + 9968
|
||||
_subr__i64toa = __native_entry__() + 4112
|
||||
_subr__lspace = __native_entry__() + 80
|
||||
_subr__quote = __native_entry__() + 5792
|
||||
_subr__skip_array = __native_entry__() + 20576
|
||||
_subr__skip_number = __native_entry__() + 23920
|
||||
_subr__skip_object = __native_entry__() + 22496
|
||||
_subr__skip_one = __native_entry__() + 24080
|
||||
_subr__skip_one_fast = __native_entry__() + 24320
|
||||
_subr__u64toa = __native_entry__() + 4384
|
||||
_subr__unquote = __native_entry__() + 7488
|
||||
_subr__validate_one = __native_entry__() + 24144
|
||||
_subr__validate_utf8 = __native_entry__() + 28464
|
||||
_subr__validate_utf8_fast = __native_entry__() + 29136
|
||||
_subr__value = __native_entry__() + 14672
|
||||
_subr__vnumber = __native_entry__() + 18320
|
||||
_subr__vsigned = __native_entry__() + 19856
|
||||
_subr__vstring = __native_entry__() + 16864
|
||||
_subr__vunsigned = __native_entry__() + 20208
|
||||
_subr__f32toa = __native_entry__() + 31264
|
||||
_subr__f64toa = __native_entry__() + 192
|
||||
_subr__get_by_path = __native_entry__() + 25856
|
||||
_subr__html_escape = __native_entry__() + 9040
|
||||
_subr__i64toa = __native_entry__() + 3488
|
||||
_subr__lspace = __native_entry__() + 16
|
||||
_subr__quote = __native_entry__() + 4880
|
||||
_subr__skip_array = __native_entry__() + 17952
|
||||
_subr__skip_number = __native_entry__() + 21952
|
||||
_subr__skip_object = __native_entry__() + 20368
|
||||
_subr__skip_one = __native_entry__() + 22112
|
||||
_subr__skip_one_fast = __native_entry__() + 22352
|
||||
_subr__u64toa = __native_entry__() + 3600
|
||||
_subr__unquote = __native_entry__() + 6672
|
||||
_subr__validate_one = __native_entry__() + 22176
|
||||
_subr__validate_utf8 = __native_entry__() + 30000
|
||||
_subr__validate_utf8_fast = __native_entry__() + 30672
|
||||
_subr__value = __native_entry__() + 12224
|
||||
_subr__vnumber = __native_entry__() + 15616
|
||||
_subr__vsigned = __native_entry__() + 17232
|
||||
_subr__vstring = __native_entry__() + 14064
|
||||
_subr__vunsigned = __native_entry__() + 17600
|
||||
)
|
||||
|
||||
const (
|
||||
_stack__f32toa = 56
|
||||
_stack__f32toa = 48
|
||||
_stack__f64toa = 80
|
||||
_stack__get_by_path = 312
|
||||
_stack__get_by_path = 304
|
||||
_stack__html_escape = 64
|
||||
_stack__i64toa = 16
|
||||
_stack__lspace = 8
|
||||
_stack__quote = 80
|
||||
_stack__quote = 56
|
||||
_stack__skip_array = 128
|
||||
_stack__skip_number = 72
|
||||
_stack__skip_object = 128
|
||||
_stack__skip_one = 128
|
||||
_stack__skip_one_fast = 208
|
||||
_stack__skip_one_fast = 200
|
||||
_stack__u64toa = 8
|
||||
_stack__unquote = 128
|
||||
_stack__unquote = 88
|
||||
_stack__validate_one = 128
|
||||
_stack__validate_utf8 = 48
|
||||
_stack__validate_utf8_fast = 24
|
||||
_stack__value = 368
|
||||
_stack__vnumber = 280
|
||||
_stack__value = 328
|
||||
_stack__vnumber = 240
|
||||
_stack__vsigned = 16
|
||||
_stack__vstring = 128
|
||||
_stack__vunsigned = 24
|
||||
_stack__vstring = 136
|
||||
_stack__vunsigned = 16
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/avx2/native_amd64.go
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/avx2/native_amd64.go
generated
vendored
|
|
@ -122,7 +122,7 @@ func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}) (ret int)
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
|
|||
17139
vendor/github.com/bytedance/sonic/internal/native/avx2/native_amd64.s
generated
vendored
17139
vendor/github.com/bytedance/sonic/internal/native/avx2/native_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
74
vendor/github.com/bytedance/sonic/internal/native/avx2/native_subr_amd64.go
generated
vendored
74
vendor/github.com/bytedance/sonic/internal/native/avx2/native_subr_amd64.go
generated
vendored
|
|
@ -9,53 +9,53 @@ package avx2
|
|||
func __native_entry__() uintptr
|
||||
|
||||
var (
|
||||
_subr__f32toa = __native_entry__() + 35216
|
||||
_subr__f64toa = __native_entry__() + 752
|
||||
_subr__get_by_path = __native_entry__() + 30384
|
||||
_subr__html_escape = __native_entry__() + 11712
|
||||
_subr__i64toa = __native_entry__() + 4368
|
||||
_subr__lspace = __native_entry__() + 224
|
||||
_subr__quote = __native_entry__() + 6160
|
||||
_subr__skip_array = __native_entry__() + 22864
|
||||
_subr__skip_number = __native_entry__() + 26928
|
||||
_subr__skip_object = __native_entry__() + 24864
|
||||
_subr__skip_one = __native_entry__() + 27088
|
||||
_subr__skip_one_fast = __native_entry__() + 27504
|
||||
_subr__u64toa = __native_entry__() + 4640
|
||||
_subr__unquote = __native_entry__() + 8960
|
||||
_subr__validate_one = __native_entry__() + 27152
|
||||
_subr__validate_utf8 = __native_entry__() + 31552
|
||||
_subr__validate_utf8_fast = __native_entry__() + 32496
|
||||
_subr__value = __native_entry__() + 16816
|
||||
_subr__vnumber = __native_entry__() + 20608
|
||||
_subr__vsigned = __native_entry__() + 22144
|
||||
_subr__vstring = __native_entry__() + 19312
|
||||
_subr__vunsigned = __native_entry__() + 22496
|
||||
_subr__f32toa = __native_entry__() + 33888
|
||||
_subr__f64toa = __native_entry__() + 288
|
||||
_subr__get_by_path = __native_entry__() + 28336
|
||||
_subr__html_escape = __native_entry__() + 10496
|
||||
_subr__i64toa = __native_entry__() + 3584
|
||||
_subr__lspace = __native_entry__() + 64
|
||||
_subr__quote = __native_entry__() + 5072
|
||||
_subr__skip_array = __native_entry__() + 20688
|
||||
_subr__skip_number = __native_entry__() + 24912
|
||||
_subr__skip_object = __native_entry__() + 22736
|
||||
_subr__skip_one = __native_entry__() + 25072
|
||||
_subr__skip_one_fast = __native_entry__() + 25488
|
||||
_subr__u64toa = __native_entry__() + 3696
|
||||
_subr__unquote = __native_entry__() + 7888
|
||||
_subr__validate_one = __native_entry__() + 25136
|
||||
_subr__validate_utf8 = __native_entry__() + 30320
|
||||
_subr__validate_utf8_fast = __native_entry__() + 31280
|
||||
_subr__value = __native_entry__() + 15024
|
||||
_subr__vnumber = __native_entry__() + 18352
|
||||
_subr__vsigned = __native_entry__() + 19968
|
||||
_subr__vstring = __native_entry__() + 17024
|
||||
_subr__vunsigned = __native_entry__() + 20336
|
||||
)
|
||||
|
||||
const (
|
||||
_stack__f32toa = 56
|
||||
_stack__f32toa = 48
|
||||
_stack__f64toa = 80
|
||||
_stack__get_by_path = 320
|
||||
_stack__get_by_path = 296
|
||||
_stack__html_escape = 72
|
||||
_stack__i64toa = 16
|
||||
_stack__lspace = 8
|
||||
_stack__quote = 72
|
||||
_stack__skip_array = 120
|
||||
_stack__skip_number = 80
|
||||
_stack__skip_object = 120
|
||||
_stack__skip_one = 120
|
||||
_stack__skip_one_fast = 216
|
||||
_stack__quote = 56
|
||||
_stack__skip_array = 128
|
||||
_stack__skip_number = 72
|
||||
_stack__skip_object = 128
|
||||
_stack__skip_one = 128
|
||||
_stack__skip_one_fast = 208
|
||||
_stack__u64toa = 8
|
||||
_stack__unquote = 128
|
||||
_stack__validate_one = 120
|
||||
_stack__unquote = 72
|
||||
_stack__validate_one = 128
|
||||
_stack__validate_utf8 = 48
|
||||
_stack__validate_utf8_fast = 200
|
||||
_stack__value = 368
|
||||
_stack__vnumber = 280
|
||||
_stack__validate_utf8_fast = 176
|
||||
_stack__value = 328
|
||||
_stack__vnumber = 240
|
||||
_stack__vsigned = 16
|
||||
_stack__vstring = 104
|
||||
_stack__vunsigned = 24
|
||||
_stack__vstring = 112
|
||||
_stack__vunsigned = 16
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/dispatch_amd64.go
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/dispatch_amd64.go
generated
vendored
|
|
@ -94,7 +94,7 @@ func SkipOneFast(s *string, p *int) int
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func GetByPath(s *string, p *int, path *[]interface{}) int
|
||||
func GetByPath(s *string, p *int, path *[]interface{}, m *types.StateMachine) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/dispatch_amd64.s
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/dispatch_amd64.s
generated
vendored
|
|
@ -72,7 +72,7 @@ TEXT ·SkipOneFast(SB), NOSPLIT, $0 - 24
|
|||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__skip_one_fast(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕sse·__skip_one_fast(SB)
|
||||
|
||||
TEXT ·GetByPath(SB), NOSPLIT, $0 - 32
|
||||
TEXT ·GetByPath(SB), NOSPLIT, $0 - 40
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__get_by_path(SB)
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/native_amd64.tmpl
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/native_amd64.tmpl
generated
vendored
|
|
@ -120,7 +120,7 @@ func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}) (ret int)
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/native/sse/native_amd64.go
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/native/sse/native_amd64.go
generated
vendored
|
|
@ -122,7 +122,7 @@ func __validate_one(s *string, p *int, m *types.StateMachine) (ret int)
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}) (ret int)
|
||||
func __get_by_path(s *string, p *int, path *[]interface{}, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
|
|||
16227
vendor/github.com/bytedance/sonic/internal/native/sse/native_amd64.s
generated
vendored
16227
vendor/github.com/bytedance/sonic/internal/native/sse/native_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
62
vendor/github.com/bytedance/sonic/internal/native/sse/native_subr_amd64.go
generated
vendored
62
vendor/github.com/bytedance/sonic/internal/native/sse/native_subr_amd64.go
generated
vendored
|
|
@ -9,53 +9,53 @@ package sse
|
|||
func __native_entry__() uintptr
|
||||
|
||||
var (
|
||||
_subr__f32toa = __native_entry__() + 28688
|
||||
_subr__f64toa = __native_entry__() + 464
|
||||
_subr__get_by_path = __native_entry__() + 26432
|
||||
_subr__html_escape = __native_entry__() + 9584
|
||||
_subr__i64toa = __native_entry__() + 3744
|
||||
_subr__lspace = __native_entry__() + 80
|
||||
_subr__quote = __native_entry__() + 5472
|
||||
_subr__skip_array = __native_entry__() + 19184
|
||||
_subr__skip_number = __native_entry__() + 22528
|
||||
_subr__skip_object = __native_entry__() + 21088
|
||||
_subr__skip_one = __native_entry__() + 22688
|
||||
_subr__skip_one_fast = __native_entry__() + 22912
|
||||
_subr__u64toa = __native_entry__() + 4016
|
||||
_subr__unquote = __native_entry__() + 7184
|
||||
_subr__validate_one = __native_entry__() + 22736
|
||||
_subr__validate_utf8 = __native_entry__() + 27456
|
||||
_subr__validate_utf8_fast = __native_entry__() + 28128
|
||||
_subr__value = __native_entry__() + 13216
|
||||
_subr__vnumber = __native_entry__() + 16928
|
||||
_subr__vsigned = __native_entry__() + 18464
|
||||
_subr__vstring = __native_entry__() + 15408
|
||||
_subr__vunsigned = __native_entry__() + 18816
|
||||
_subr__f32toa = __native_entry__() + 31760
|
||||
_subr__f64toa = __native_entry__() + 160
|
||||
_subr__get_by_path = __native_entry__() + 26384
|
||||
_subr__html_escape = __native_entry__() + 9072
|
||||
_subr__i64toa = __native_entry__() + 3424
|
||||
_subr__lspace = __native_entry__() + 16
|
||||
_subr__quote = __native_entry__() + 4864
|
||||
_subr__skip_array = __native_entry__() + 18112
|
||||
_subr__skip_number = __native_entry__() + 22128
|
||||
_subr__skip_object = __native_entry__() + 20512
|
||||
_subr__skip_one = __native_entry__() + 22288
|
||||
_subr__skip_one_fast = __native_entry__() + 22512
|
||||
_subr__u64toa = __native_entry__() + 3552
|
||||
_subr__unquote = __native_entry__() + 6704
|
||||
_subr__validate_one = __native_entry__() + 22336
|
||||
_subr__validate_utf8 = __native_entry__() + 30528
|
||||
_subr__validate_utf8_fast = __native_entry__() + 31200
|
||||
_subr__value = __native_entry__() + 12272
|
||||
_subr__vnumber = __native_entry__() + 15728
|
||||
_subr__vsigned = __native_entry__() + 17376
|
||||
_subr__vstring = __native_entry__() + 14112
|
||||
_subr__vunsigned = __native_entry__() + 17760
|
||||
)
|
||||
|
||||
const (
|
||||
_stack__f32toa = 56
|
||||
_stack__f32toa = 48
|
||||
_stack__f64toa = 80
|
||||
_stack__get_by_path = 264
|
||||
_stack__get_by_path = 240
|
||||
_stack__html_escape = 64
|
||||
_stack__i64toa = 16
|
||||
_stack__lspace = 8
|
||||
_stack__quote = 80
|
||||
_stack__quote = 64
|
||||
_stack__skip_array = 128
|
||||
_stack__skip_number = 72
|
||||
_stack__skip_object = 128
|
||||
_stack__skip_one = 128
|
||||
_stack__skip_one_fast = 160
|
||||
_stack__skip_one_fast = 136
|
||||
_stack__u64toa = 8
|
||||
_stack__unquote = 128
|
||||
_stack__unquote = 88
|
||||
_stack__validate_one = 128
|
||||
_stack__validate_utf8 = 48
|
||||
_stack__validate_utf8_fast = 24
|
||||
_stack__value = 368
|
||||
_stack__vnumber = 280
|
||||
_stack__value = 328
|
||||
_stack__vnumber = 240
|
||||
_stack__vsigned = 16
|
||||
_stack__vstring = 128
|
||||
_stack__vunsigned = 24
|
||||
_stack__vstring = 136
|
||||
_stack__vunsigned = 16
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
4
vendor/github.com/bytedance/sonic/internal/native/types/types.go
generated
vendored
4
vendor/github.com/bytedance/sonic/internal/native/types/types.go
generated
vendored
|
|
@ -76,6 +76,10 @@ const (
|
|||
ERR_FLOAT_INFINITY ParsingError = 8
|
||||
ERR_MISMATCH ParsingError = 9
|
||||
ERR_INVALID_UTF8 ParsingError = 10
|
||||
|
||||
// error code used in ast
|
||||
ERR_NOT_FOUND ParsingError = 33
|
||||
ERR_UNSUPPORT_TYPE ParsingError = 34
|
||||
)
|
||||
|
||||
var _ParsingErrors = []string{
|
||||
|
|
|
|||
2
vendor/github.com/bytedance/sonic/internal/resolver/resolver.go
generated
vendored
2
vendor/github.com/bytedance/sonic/internal/resolver/resolver.go
generated
vendored
|
|
@ -152,8 +152,8 @@ func resolveFields(vt reflect.Type) []FieldMeta {
|
|||
}
|
||||
|
||||
/* get the index to the last offset */
|
||||
fvt := fv.typ
|
||||
idx := len(path) - 1
|
||||
fvt := path[idx].Type
|
||||
|
||||
/* do not dereference into fields */
|
||||
if path[idx].Kind == F_deref {
|
||||
|
|
|
|||
1
vendor/github.com/bytedance/sonic/internal/rt/fastmem.go
generated
vendored
1
vendor/github.com/bytedance/sonic/internal/rt/fastmem.go
generated
vendored
|
|
@ -87,7 +87,6 @@ func GuardSlice(buf *[]byte, n int) {
|
|||
copy(tmp, *buf)
|
||||
*buf = tmp
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
|
|
|
|||
15
vendor/github.com/bytedance/sonic/internal/rt/fastvalue.go
generated
vendored
15
vendor/github.com/bytedance/sonic/internal/rt/fastvalue.go
generated
vendored
|
|
@ -22,14 +22,23 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
reflectRtypeItab = findReflectRtypeItab()
|
||||
reflectRtypeItab = findReflectRtypeItab()
|
||||
)
|
||||
|
||||
// GoType.KindFlags const
|
||||
const (
|
||||
F_direct = 1 << 5
|
||||
F_kind_mask = (1 << 5) - 1
|
||||
)
|
||||
|
||||
// GoType.Flags const
|
||||
const (
|
||||
tflagUncommon uint8 = 1 << 0
|
||||
tflagExtraStar uint8 = 1 << 1
|
||||
tflagNamed uint8 = 1 << 2
|
||||
tflagRegularMemory uint8 = 1 << 3
|
||||
)
|
||||
|
||||
type GoType struct {
|
||||
Size uintptr
|
||||
PtrData uintptr
|
||||
|
|
@ -44,6 +53,10 @@ type GoType struct {
|
|||
PtrToSelf int32
|
||||
}
|
||||
|
||||
func (self *GoType) IsNamed() bool {
|
||||
return (self.Flags & tflagNamed) != 0
|
||||
}
|
||||
|
||||
func (self *GoType) Kind() reflect.Kind {
|
||||
return reflect.Kind(self.KindFlags & F_kind_mask)
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/bytedance/sonic/internal/rt/stackmap.go
generated
vendored
1
vendor/github.com/bytedance/sonic/internal/rt/stackmap.go
generated
vendored
|
|
@ -152,6 +152,7 @@ type StackMapBuilder struct {
|
|||
b Bitmap
|
||||
}
|
||||
|
||||
//go:nocheckptr
|
||||
func (self *StackMapBuilder) Build() (p *StackMap) {
|
||||
nb := len(self.b.B)
|
||||
bm := mallocgc(_StackMapSize + uintptr(nb) - 1, byteType, false)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue