mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
feat: CPU feature detection support
This commit is contained in:
parent
accee2e689
commit
34fa8d64a8
47 changed files with 10838 additions and 2470 deletions
|
|
@ -8,13 +8,15 @@ header:
|
|||
- '**/*.s'
|
||||
|
||||
paths-ignore:
|
||||
- 'ast/asm.s' # empty file
|
||||
- 'encoder/asm.s' # empty file
|
||||
- 'internal/caching/asm.s' # empty file
|
||||
- 'internal/jit/asm.s' # empty file
|
||||
- 'internal/native/native_amd64.s' # auto-generated by asm2asm
|
||||
- 'internal/native/native_subr_amd64.go' # auto-generated by asm2asm
|
||||
- 'internal/resolver/asm.s' # empty file
|
||||
- 'internal/rt/asm.s' # empty file
|
||||
- 'ast/asm.s' # empty file
|
||||
- 'encoder/asm.s' # empty file
|
||||
- 'internal/caching/asm.s' # empty file
|
||||
- 'internal/jit/asm.s' # empty file
|
||||
- 'internal/native/avx/native_amd64.s' # auto-generated by asm2asm
|
||||
- 'internal/native/avx/native_subr_amd64.go' # auto-generated by asm2asm
|
||||
- 'internal/native/avx2/native_amd64.s' # auto-generated by asm2asm
|
||||
- 'internal/native/avx2/native_subr_amd64.go' # auto-generated by asm2asm
|
||||
- 'internal/resolver/asm.s' # empty file
|
||||
- 'internal/rt/asm.s' # empty file
|
||||
|
||||
comment: on-failure
|
||||
113
Makefile
113
Makefile
|
|
@ -14,39 +14,92 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
.PHONY: all clean
|
||||
ARCH := avx avx2
|
||||
TMP_DIR := output
|
||||
OUT_DIR := internal/native
|
||||
SRC_FILE := native/native.c
|
||||
|
||||
CFLAGS := -mavx
|
||||
CFLAGS += -mavx2
|
||||
CFLAGS += -mbmi
|
||||
CFLAGS += -mbmi2
|
||||
CFLAGS += -mfma
|
||||
CFLAGS += -msse
|
||||
CFLAGS += -msse2
|
||||
CFLAGS += -msse3
|
||||
CFLAGS += -msse4
|
||||
CFLAGS += -mssse3
|
||||
CFLAGS += -mno-red-zone
|
||||
CFLAGS += -ffast-math
|
||||
CFLAGS += -fno-asynchronous-unwind-tables
|
||||
CFLAGS += -fno-builtin
|
||||
CFLAGS += -fno-exceptions
|
||||
CFLAGS += -fno-rtti
|
||||
CFLAGS += -fno-stack-protector
|
||||
CFLAGS += -nostdlib
|
||||
CFLAGS += -O3
|
||||
CPU_avx := amd64
|
||||
CPU_avx2 := amd64
|
||||
|
||||
NATIVE_ASM := $(wildcard native/*.S)
|
||||
NATIVE_SRC := $(wildcard native/*.h)
|
||||
NATIVE_SRC += $(wildcard native/*.c)
|
||||
TMPL_avx := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
|
||||
TMPL_avx2 := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
|
||||
|
||||
all: internal/native/native_amd64.s
|
||||
CFLAGS_avx := -msse2 -mavx -mno-avx2 -DUSE_SSE=1 -DUSE_AVX=1 -DUSE_AVX2=0
|
||||
CFLAGS_avx2 := -msse2 -mavx -mavx2 -DUSE_SSE=1 -DUSE_AVX=1 -DUSE_AVX2=1
|
||||
|
||||
CC_amd64 := clang
|
||||
ASM2ASM_amd64 := tools/asm2asm/asm2asm.py
|
||||
|
||||
CFLAGS := -mno-red-zone
|
||||
CFLAGS += -fno-asynchronous-unwind-tables
|
||||
CFLAGS += -fno-builtin
|
||||
CFLAGS += -fno-exceptions
|
||||
CFLAGS += -fno-rtti
|
||||
CFLAGS += -fno-stack-protector
|
||||
CFLAGS += -nostdlib
|
||||
CFLAGS += -O3
|
||||
|
||||
NATIVE_SRC := $(wildcard native/*.h)
|
||||
NATIVE_SRC += $(wildcard native/*.c)
|
||||
|
||||
.PHONY: all clean ${ARCH}
|
||||
|
||||
define build_tmpl
|
||||
$(eval @arch := $(1))
|
||||
$(eval @tmpl := $(2))
|
||||
$(eval @dest := $(3))
|
||||
|
||||
${@dest}: ${@tmpl}
|
||||
mkdir -p $(dir ${@dest})
|
||||
echo '// Code generated by Makefile, DO NOT EDIT.' > ${@dest}
|
||||
echo >> ${@dest}
|
||||
sed -e 's/{{PACKAGE}}/${@arch}/g' ${@tmpl} >> ${@dest}
|
||||
endef
|
||||
|
||||
define build_arch
|
||||
$(eval @cpu := $(value CPU_$(1)))
|
||||
$(eval @deps := $(foreach tmpl,$(value TMPL_$(1)),${OUT_DIR}/$(1)/${tmpl}.go))
|
||||
$(eval @asmin := ${TMP_DIR}/$(1)/native.s)
|
||||
$(eval @asmout := ${OUT_DIR}/$(1)/native_${@cpu}.s)
|
||||
$(eval @stubin := ${OUT_DIR}/native_${@cpu}.tmpl)
|
||||
$(eval @stubout := ${OUT_DIR}/$(1)/native_${@cpu}.go)
|
||||
|
||||
$(1): ${@asmout} ${@deps}
|
||||
|
||||
${@asmout}: ${@stubout} ${NATIVE_SRC}
|
||||
mkdir -p ${TMP_DIR}/$(1)
|
||||
$${CC_${@cpu}} $${CFLAGS} $${CFLAGS_$(1)} -S -o ${TMP_DIR}/$(1)/native.s ${SRC_FILE}
|
||||
python3 $${ASM2ASM_${@cpu}} ${@asmout} ${TMP_DIR}/$(1)/native.s
|
||||
asmfmt -w ${@asmout}
|
||||
|
||||
$(eval $(call \
|
||||
build_tmpl, \
|
||||
$(1), \
|
||||
${@stubin}, \
|
||||
${@stubout} \
|
||||
))
|
||||
|
||||
$(foreach \
|
||||
tmpl, \
|
||||
$(value TMPL_$(1)), \
|
||||
$(eval $(call \
|
||||
build_tmpl, \
|
||||
$(1), \
|
||||
${OUT_DIR}/${tmpl}.tmpl, \
|
||||
${OUT_DIR}/$(1)/${tmpl}.go \
|
||||
)) \
|
||||
)
|
||||
endef
|
||||
|
||||
all: ${ARCH}
|
||||
|
||||
clean:
|
||||
rm -vf internal/native/native_amd64.s output/*.s
|
||||
rm -vfr ${TMP_DIR}/{sse,avx,avx2}
|
||||
rm -vfr ${OUT_DIR}/{sse,avx,avx2}
|
||||
|
||||
internal/native/native_amd64.s: ${NATIVE_SRC} ${NATIVE_ASM} internal/native/native_amd64.go
|
||||
mkdir -p output
|
||||
clang ${CFLAGS} -S -o output/native.s native/native.c
|
||||
python3 tools/asm2asm/asm2asm.py internal/native/native_amd64.s output/native.s ${NATIVE_ASM}
|
||||
asmfmt -w internal/native/native_amd64.s
|
||||
$(foreach \
|
||||
arch, \
|
||||
${ARCH}, \
|
||||
$(eval $(call build_arch,${arch})) \
|
||||
)
|
||||
|
|
|
|||
174
ast/node.go
174
ast/node.go
|
|
@ -21,7 +21,7 @@ import (
|
|||
`fmt`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
|
|
@ -36,23 +36,23 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
V_RAW native.ValueType = 1 << 4
|
||||
V_NUMBER native.ValueType = 10
|
||||
V_ARRAY_RAW = V_RAW | native.V_ARRAY
|
||||
V_OBJECT_RAW = V_RAW | native.V_OBJECT
|
||||
MASK_RAW = V_RAW - 1
|
||||
V_RAW types.ValueType = 1 << 4
|
||||
V_NUMBER types.ValueType = 10
|
||||
V_ARRAY_RAW = V_RAW | types.V_ARRAY
|
||||
V_OBJECT_RAW = V_RAW | types.V_OBJECT
|
||||
MASK_RAW = V_RAW - 1
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
v int64
|
||||
t native.ValueType
|
||||
t types.ValueType
|
||||
p unsafe.Pointer
|
||||
m map[string]unsafe.Pointer
|
||||
}
|
||||
|
||||
/** Node Type Accessor **/
|
||||
|
||||
func (self *Node) Type() native.ValueType {
|
||||
func (self *Node) Type() types.ValueType {
|
||||
return self.t & MASK_RAW
|
||||
}
|
||||
|
||||
|
|
@ -69,12 +69,12 @@ func (self *Node) Raw() string {
|
|||
|
||||
// Bool returns bool value represented by this node
|
||||
//
|
||||
// If node type is not native.V_TRUE or native.V_FALSE, or V_RAW (must be a bool json value)
|
||||
// If node type is not types.V_TRUE or types.V_FALSE, or V_RAW (must be a bool json value)
|
||||
// it will panic
|
||||
func (self *Node) Bool() bool {
|
||||
switch self.t {
|
||||
case native.V_TRUE : return true
|
||||
case native.V_FALSE : return false
|
||||
case types.V_TRUE : return true
|
||||
case types.V_FALSE : return false
|
||||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.Bool()
|
||||
|
|
@ -86,9 +86,9 @@ func (self *Node) Bool() bool {
|
|||
func (self *Node) Int64() int64 {
|
||||
switch self.t {
|
||||
case V_NUMBER : return numberToInt64(self)
|
||||
case native.V_TRUE : return 1
|
||||
case native.V_FALSE : return 0
|
||||
case V_RAW :
|
||||
case types.V_TRUE : return 1
|
||||
case types.V_FALSE : return 0
|
||||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.Int64()
|
||||
default : panic("value cannot be represented as an integer")
|
||||
|
|
@ -109,36 +109,36 @@ func (self *Node) Number() json.Number {
|
|||
// String as above.
|
||||
func (self *Node) String() string {
|
||||
switch self.t {
|
||||
case V_NUMBER : return toNumber(self).String()
|
||||
case native.V_NULL : return "null"
|
||||
case native.V_TRUE : return "true"
|
||||
case native.V_FALSE : return "false"
|
||||
case native.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_NUMBER : return toNumber(self).String()
|
||||
case types.V_NULL : return "null"
|
||||
case types.V_TRUE : return "true"
|
||||
case types.V_FALSE : return "false"
|
||||
case types.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.String()
|
||||
default : panic("value cannot be represented as a simple string")
|
||||
default : panic("value cannot be represented as a simple string")
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 as above.
|
||||
func (self *Node) Float64() float64 {
|
||||
switch self.t {
|
||||
case V_NUMBER : return numberToFloat64(self)
|
||||
case native.V_TRUE : return 1.0
|
||||
case native.V_FALSE : return 0.0
|
||||
case V_NUMBER : return numberToFloat64(self)
|
||||
case types.V_TRUE : return 1.0
|
||||
case types.V_FALSE : return 0.0
|
||||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.Float64()
|
||||
default : panic("value cannot be represented as an integer")
|
||||
default : panic("value cannot be represented as an integer")
|
||||
}
|
||||
}
|
||||
|
||||
// IsRaw returns true if the node is type of below three:
|
||||
//
|
||||
// 1. V_RAW (never parsed)
|
||||
// 2. native.V_Object_RAW (partially parsed)
|
||||
// 3. native.V_Array_RAW (partially parsed)
|
||||
// 2. types.V_Object_RAW (partially parsed)
|
||||
// 3. types.V_Array_RAW (partially parsed)
|
||||
func (self *Node) IsRaw() bool {
|
||||
return self.t&V_RAW != 0
|
||||
}
|
||||
|
|
@ -148,9 +148,9 @@ func (self *Node) IsRaw() bool {
|
|||
// Len returns children count of a array|object|string node
|
||||
// For partially loaded node, it also works but only counts the parsed children
|
||||
func (self *Node) Len() int {
|
||||
if self.t == native.V_ARRAY || self.t == native.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
return int(self.v & _LEN_MASK)
|
||||
} else if self.t == native.V_STRING {
|
||||
} else if self.t == types.V_STRING {
|
||||
return int(self.v)
|
||||
} else {
|
||||
panic("value does not have a length")
|
||||
|
|
@ -159,7 +159,7 @@ func (self *Node) Len() int {
|
|||
|
||||
// Cap returns malloc capacity of a array|object node for children
|
||||
func (self *Node) Cap() int {
|
||||
if self.t == native.V_ARRAY || self.t == native.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
return int(self.v >> _CAP_BITS)
|
||||
} else {
|
||||
panic("value does not have a capacity")
|
||||
|
|
@ -205,7 +205,7 @@ func (self *Node) SetByIndex(index int, node Node) {
|
|||
|
||||
// Add appends the given node under array node
|
||||
func (self *Node) Add(node Node) {
|
||||
self.must(native.V_ARRAY, "an array")
|
||||
self.must(types.V_ARRAY, "an array")
|
||||
self.loadAllIndex()
|
||||
l := self.Len()
|
||||
c := self.Cap()
|
||||
|
|
@ -240,26 +240,26 @@ func (self *Node) GetByPath(path ...interface{}) *Node {
|
|||
|
||||
// Get loads given key of an object node on demands
|
||||
func (self *Node) Get(key string) *Node {
|
||||
self.must(native.V_OBJECT, "an object")
|
||||
self.must(types.V_OBJECT, "an object")
|
||||
return self.loadKey(key)
|
||||
}
|
||||
|
||||
// Index loads given index of an array node on demands
|
||||
func (self *Node) Index(idx int) *Node {
|
||||
self.must(native.V_ARRAY, "an array")
|
||||
self.must(types.V_ARRAY, "an array")
|
||||
return self.loadIndex(idx)
|
||||
}
|
||||
|
||||
// Values returns iterator for array's children traversal
|
||||
func (self *Node) Values() ListIterator {
|
||||
self.must(native.V_ARRAY, "an array")
|
||||
self.must(types.V_ARRAY, "an array")
|
||||
self.loadAllIndex()
|
||||
return ListIterator{Iterator{p: self}}
|
||||
}
|
||||
|
||||
// Values returns iterator for object's children traversal
|
||||
// Properties returns iterator for object's children traversal
|
||||
func (self *Node) Properties() ObjectIterator {
|
||||
self.must(native.V_OBJECT, "an object")
|
||||
self.must(types.V_OBJECT, "an object")
|
||||
self.loadAllKey()
|
||||
return ObjectIterator{Iterator{p: self}}
|
||||
}
|
||||
|
|
@ -268,28 +268,28 @@ func (self *Node) Properties() ObjectIterator {
|
|||
|
||||
// Map loads all keys of an object node
|
||||
func (self *Node) Map() map[string]interface{} {
|
||||
self.must(native.V_OBJECT, "an object")
|
||||
self.must(types.V_OBJECT, "an object")
|
||||
self.loadAllKey()
|
||||
return self.toGenericObject()
|
||||
}
|
||||
|
||||
// MapUseNumber loads all keys of an object node, with numeric nodes casted to json.Number
|
||||
func (self *Node) MapUseNumber() map[string]interface{} {
|
||||
self.must(native.V_OBJECT, "an object")
|
||||
self.must(types.V_OBJECT, "an object")
|
||||
self.loadAllKey()
|
||||
return self.toGenericObjectUseNumber()
|
||||
}
|
||||
|
||||
// Array loads all indexes of an array node
|
||||
func (self *Node) Array() []interface{} {
|
||||
self.must(native.V_ARRAY, "an array")
|
||||
self.must(types.V_ARRAY, "an array")
|
||||
self.loadAllIndex()
|
||||
return self.toGenericArray()
|
||||
}
|
||||
|
||||
// Array loads all indexes of an array node, with numeric nodes casted to json.Number
|
||||
// ArrayUseNumber loads all indexes of an array node, with numeric nodes casted to json.Number
|
||||
func (self *Node) ArrayUseNumber() []interface{} {
|
||||
self.must(native.V_ARRAY, "an array")
|
||||
self.must(types.V_ARRAY, "an array")
|
||||
self.loadAllIndex()
|
||||
return self.toGenericArrayUseNumber()
|
||||
}
|
||||
|
|
@ -299,14 +299,14 @@ func (self *Node) ArrayUseNumber() []interface{} {
|
|||
// all numberic nodes are casted to float64
|
||||
func (self *Node) Interface() interface{} {
|
||||
switch self.t {
|
||||
case native.V_EOF : panic("invalid value")
|
||||
case native.V_NULL : return nil
|
||||
case native.V_TRUE : return true
|
||||
case native.V_FALSE : return false
|
||||
case native.V_ARRAY : return self.toGenericArray()
|
||||
case native.V_OBJECT : return self.toGenericObject()
|
||||
case native.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_NUMBER :
|
||||
case types.V_EOF : panic("invalid value")
|
||||
case types.V_NULL : return nil
|
||||
case types.V_TRUE : return true
|
||||
case types.V_FALSE : return false
|
||||
case types.V_ARRAY : return self.toGenericArray()
|
||||
case types.V_OBJECT : return self.toGenericObject()
|
||||
case types.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_NUMBER :
|
||||
return numberToFloat64(self)
|
||||
case V_ARRAY_RAW:
|
||||
self.loadAllIndex()
|
||||
|
|
@ -317,7 +317,7 @@ func (self *Node) Interface() interface{} {
|
|||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.Interface()
|
||||
default : panic("not gonna happen")
|
||||
default : panic("not gonna happen")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -325,14 +325,14 @@ func (self *Node) Interface() interface{} {
|
|||
// except numberic nodes are casted to json.Number
|
||||
func (self *Node) InterfaceUseNumber() interface{} {
|
||||
switch self.t {
|
||||
case native.V_EOF : panic("invalid value")
|
||||
case native.V_NULL : return nil
|
||||
case native.V_TRUE : return true
|
||||
case native.V_FALSE : return false
|
||||
case native.V_ARRAY : return self.toGenericArrayUseNumber()
|
||||
case native.V_OBJECT : return self.toGenericObjectUseNumber()
|
||||
case native.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_NUMBER :
|
||||
case types.V_EOF : panic("invalid value")
|
||||
case types.V_NULL : return nil
|
||||
case types.V_TRUE : return true
|
||||
case types.V_FALSE : return false
|
||||
case types.V_ARRAY : return self.toGenericArrayUseNumber()
|
||||
case types.V_OBJECT : return self.toGenericObjectUseNumber()
|
||||
case types.V_STRING : return addr2str(self.p, self.v)
|
||||
case V_NUMBER :
|
||||
return toNumber(self)
|
||||
case V_ARRAY_RAW:
|
||||
self.loadAllIndex()
|
||||
|
|
@ -340,10 +340,10 @@ func (self *Node) InterfaceUseNumber() interface{} {
|
|||
case V_OBJECT_RAW:
|
||||
self.loadAllKey()
|
||||
return self.toGenericObjectUseNumber()
|
||||
case V_RAW :
|
||||
case V_RAW :
|
||||
n := self.parseRaw()
|
||||
return n.InterfaceUseNumber()
|
||||
default : panic("not gonna happen")
|
||||
default : panic("not gonna happen")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ var (
|
|||
)
|
||||
|
||||
func (self *Node) setCapAndLen(cap int, len int) {
|
||||
if self.t == native.V_ARRAY || self.t == native.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == V_ARRAY_RAW || self.t == V_OBJECT_RAW {
|
||||
self.v = int64(len&_LEN_MASK | cap<<_CAP_BITS)
|
||||
} else {
|
||||
panic("value does not have a length")
|
||||
|
|
@ -370,7 +370,7 @@ func (self *Pair) unsafe_next() *Pair {
|
|||
return (*Pair)(unsafe.Pointer(uintptr(unsafe.Pointer(self)) + _PAIR_SIZE))
|
||||
}
|
||||
|
||||
func (self *Node) must(t native.ValueType, s string) {
|
||||
func (self *Node) must(t types.ValueType, s string) {
|
||||
if self.t == V_RAW {
|
||||
*self = self.parseRaw()
|
||||
}
|
||||
|
|
@ -470,7 +470,7 @@ func (self *Node) loadAllIndex() {
|
|||
if !self.IsRaw() {
|
||||
return
|
||||
}
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
stack := (*parseArrayStack)(self.p)
|
||||
parser := &stack.parser
|
||||
old := parser.noLazy
|
||||
|
|
@ -486,7 +486,7 @@ func (self *Node) loadAllKey() {
|
|||
if !self.IsRaw() {
|
||||
return
|
||||
}
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
stack := (*parseObjectStack)(self.p)
|
||||
parser := &stack.parser
|
||||
old := parser.noLazy
|
||||
|
|
@ -523,7 +523,7 @@ func (self *Node) loadIndex(index int) *Node {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (self *Node) loadNextNode() (*Node, native.ParsingError) {
|
||||
func (self *Node) loadNextNode() (*Node, types.ParsingError) {
|
||||
stack := (*parseArrayStack)(self.p)
|
||||
ret := stack.v
|
||||
parser := &stack.parser
|
||||
|
|
@ -532,7 +532,7 @@ func (self *Node) loadNextNode() (*Node, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if parser.p = parser.lspace(sp); parser.p >= ns {
|
||||
return nil, native.ERR_EOF
|
||||
return nil, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty array */
|
||||
|
|
@ -543,7 +543,7 @@ func (self *Node) loadNextNode() (*Node, native.ParsingError) {
|
|||
}
|
||||
|
||||
var val Node
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
|
||||
/* decode the value */
|
||||
parser.noLazy = true
|
||||
|
|
@ -558,7 +558,7 @@ func (self *Node) loadNextNode() (*Node, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if parser.p >= ns {
|
||||
return &ret[len(ret)-1], native.ERR_EOF
|
||||
return &ret[len(ret)-1], types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -572,7 +572,7 @@ func (self *Node) loadNextNode() (*Node, native.ParsingError) {
|
|||
self.setArray(ret)
|
||||
return &ret[len(ret)-1], 0
|
||||
default:
|
||||
return &ret[len(ret)-1], native.ERR_INVALID_CHAR
|
||||
return &ret[len(ret)-1], types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +596,7 @@ func (self *Node) loadKey(key string) *Node {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (self *Node) loadNextPair() (*Pair, native.ParsingError) {
|
||||
func (self *Node) loadNextPair() (*Pair, types.ParsingError) {
|
||||
stack := (*parseObjectStack)(self.p)
|
||||
ret := stack.v
|
||||
parser := &stack.parser
|
||||
|
|
@ -605,7 +605,7 @@ func (self *Node) loadNextPair() (*Pair, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if parser.p = parser.lspace(sp); parser.p >= ns {
|
||||
return nil, native.ERR_EOF
|
||||
return nil, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty object */
|
||||
|
|
@ -617,12 +617,12 @@ func (self *Node) loadNextPair() (*Pair, native.ParsingError) {
|
|||
|
||||
/* decode one pair */
|
||||
var val Node
|
||||
var njs native.JsonState
|
||||
var err native.ParsingError
|
||||
var njs types.JsonState
|
||||
var err types.ParsingError
|
||||
|
||||
/* decode the key */
|
||||
if njs = parser.decodeValue(); njs.Vt != native.V_STRING {
|
||||
return nil, native.ERR_INVALID_CHAR
|
||||
if njs = parser.decodeValue(); njs.Vt != types.V_STRING {
|
||||
return nil, types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* extract the key */
|
||||
|
|
@ -654,7 +654,7 @@ func (self *Node) loadNextPair() (*Pair, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if parser.p >= ns {
|
||||
return &ret[len(ret)-1], native.ERR_EOF
|
||||
return &ret[len(ret)-1], types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -668,7 +668,7 @@ func (self *Node) loadNextPair() (*Pair, native.ParsingError) {
|
|||
self.setObject(ret)
|
||||
return &ret[len(ret)-1], 0
|
||||
default:
|
||||
return &ret[len(ret)-1], native.ERR_INVALID_CHAR
|
||||
return &ret[len(ret)-1], types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -752,12 +752,12 @@ func (self *Node) toGenericObjectUseNumber() map[string]interface{} {
|
|||
/** Internal Factory Methods **/
|
||||
|
||||
var (
|
||||
nullNode = Node{t: native.V_NULL}
|
||||
trueNode = Node{t: native.V_TRUE}
|
||||
falseNode = Node{t: native.V_FALSE}
|
||||
nullNode = Node{t: types.V_NULL}
|
||||
trueNode = Node{t: types.V_TRUE}
|
||||
falseNode = Node{t: types.V_FALSE}
|
||||
|
||||
emptyArrayNode = Node{t: native.V_ARRAY}
|
||||
emptyObjectNode = Node{t: native.V_OBJECT}
|
||||
emptyArrayNode = Node{t: types.V_ARRAY}
|
||||
emptyObjectNode = Node{t: types.V_OBJECT}
|
||||
)
|
||||
|
||||
func newNumber(v string) Node {
|
||||
|
|
@ -790,7 +790,7 @@ func numberToInt64(node *Node) int64 {
|
|||
|
||||
func newBytes(v []byte) Node {
|
||||
return Node{
|
||||
t: native.V_STRING,
|
||||
t: types.V_STRING,
|
||||
p: mem2ptr(v),
|
||||
v: int64(len(v)),
|
||||
}
|
||||
|
|
@ -798,7 +798,7 @@ func newBytes(v []byte) Node {
|
|||
|
||||
func newString(v string) Node {
|
||||
return Node{
|
||||
t: native.V_STRING,
|
||||
t: types.V_STRING,
|
||||
p: str2ptr(v),
|
||||
v: int64(len(v)),
|
||||
}
|
||||
|
|
@ -806,28 +806,28 @@ func newString(v string) Node {
|
|||
|
||||
func newArray(v []Node) Node {
|
||||
return Node{
|
||||
t: native.V_ARRAY,
|
||||
t: types.V_ARRAY,
|
||||
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
|
||||
p: *(*unsafe.Pointer)(unsafe.Pointer(&v)),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Node) setArray(v []Node) {
|
||||
self.t = native.V_ARRAY
|
||||
self.t = types.V_ARRAY
|
||||
self.setCapAndLen(cap(v), len(v))
|
||||
self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v))
|
||||
}
|
||||
|
||||
func newObject(v []Pair) Node {
|
||||
return Node{
|
||||
t: native.V_OBJECT,
|
||||
t: types.V_OBJECT,
|
||||
v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
|
||||
p: *(*unsafe.Pointer)(unsafe.Pointer(&v)),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Node) setObject(v []Pair) {
|
||||
self.t = native.V_OBJECT
|
||||
self.t = types.V_OBJECT
|
||||
self.setCapAndLen(cap(v), len(v))
|
||||
self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
|
|
@ -34,24 +35,24 @@ type Parser struct {
|
|||
|
||||
var stackPool = sync.Pool{
|
||||
New: func()interface{}{
|
||||
return &native.StateMachine{}
|
||||
return &types.StateMachine{}
|
||||
},
|
||||
}
|
||||
|
||||
/** Parser Private Methods **/
|
||||
|
||||
func (self *Parser) delim() native.ParsingError {
|
||||
func (self *Parser) delim() types.ParsingError {
|
||||
n := len(self.s)
|
||||
p := self.lspace(self.p)
|
||||
|
||||
/* check for EOF */
|
||||
if p >= n {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the delimtier */
|
||||
if self.s[p] != ':' {
|
||||
return native.ERR_INVALID_CHAR
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* update the read pointer */
|
||||
|
|
@ -59,18 +60,18 @@ func (self *Parser) delim() native.ParsingError {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (self *Parser) object() native.ParsingError {
|
||||
func (self *Parser) object() types.ParsingError {
|
||||
n := len(self.s)
|
||||
p := self.lspace(self.p)
|
||||
|
||||
/* check for EOF */
|
||||
if p >= n {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the delimtier */
|
||||
if self.s[p] != '{' {
|
||||
return native.ERR_INVALID_CHAR
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* update the read pointer */
|
||||
|
|
@ -78,18 +79,18 @@ func (self *Parser) object() native.ParsingError {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (self *Parser) array() native.ParsingError {
|
||||
func (self *Parser) array() types.ParsingError {
|
||||
n := len(self.s)
|
||||
p := self.lspace(self.p)
|
||||
|
||||
/* check for EOF */
|
||||
if p >= n {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the delimtier */
|
||||
if self.s[p] != '[' {
|
||||
return native.ERR_INVALID_CHAR
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* update the read pointer */
|
||||
|
|
@ -102,19 +103,19 @@ func (self *Parser) lspace(sp int) int {
|
|||
return native.Lspace(sv.Ptr, sv.Len, sp)
|
||||
}
|
||||
|
||||
func (self *Parser) decodeValue() (val native.JsonState) {
|
||||
func (self *Parser) decodeValue() (val types.JsonState) {
|
||||
sv := (*rt.GoString)(unsafe.Pointer(&self.s))
|
||||
self.p = native.Value(sv.Ptr, sv.Len, self.p, &val)
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Parser) decodeArray(ret []Node) (Node, native.ParsingError) {
|
||||
func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
|
||||
sp := self.p
|
||||
ns := len(self.s)
|
||||
|
||||
/* check for EOF */
|
||||
if self.p = self.lspace(sp); self.p >= ns {
|
||||
return Node{}, native.ERR_EOF
|
||||
return Node{}, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty array */
|
||||
|
|
@ -126,7 +127,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, native.ParsingError) {
|
|||
/* allocate array space and parse every element */
|
||||
for {
|
||||
var val Node
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
|
||||
/* decode the value */
|
||||
if val, err = self.Parse(); err != 0 {
|
||||
|
|
@ -139,7 +140,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if self.p >= ns {
|
||||
return Node{}, native.ERR_EOF
|
||||
return Node{}, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -150,18 +151,18 @@ func (self *Parser) decodeArray(ret []Node) (Node, native.ParsingError) {
|
|||
if val.IsRaw() {
|
||||
return newRawArray(self, ret), 0
|
||||
}
|
||||
return Node{}, native.ERR_INVALID_CHAR
|
||||
return Node{}, types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) decodeObject(ret []Pair) (Node, native.ParsingError) {
|
||||
func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
|
||||
sp := self.p
|
||||
ns := len(self.s)
|
||||
|
||||
/* check for EOF */
|
||||
if self.p = self.lspace(sp); self.p >= ns {
|
||||
return Node{}, native.ERR_EOF
|
||||
return Node{}, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty object */
|
||||
|
|
@ -173,12 +174,12 @@ func (self *Parser) decodeObject(ret []Pair) (Node, native.ParsingError) {
|
|||
/* decode each pair */
|
||||
for {
|
||||
var val Node
|
||||
var njs native.JsonState
|
||||
var err native.ParsingError
|
||||
var njs types.JsonState
|
||||
var err types.ParsingError
|
||||
|
||||
/* decode the key */
|
||||
if njs = self.decodeValue(); njs.Vt != native.V_STRING {
|
||||
return Node{}, native.ERR_INVALID_CHAR
|
||||
if njs = self.decodeValue(); njs.Vt != types.V_STRING {
|
||||
return Node{}, types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* extract the key */
|
||||
|
|
@ -208,7 +209,7 @@ func (self *Parser) decodeObject(ret []Pair) (Node, native.ParsingError) {
|
|||
|
||||
/* check for EOF */
|
||||
if self.p >= ns {
|
||||
return Node{}, native.ERR_EOF
|
||||
return Node{}, types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -219,12 +220,12 @@ func (self *Parser) decodeObject(ret []Pair) (Node, native.ParsingError) {
|
|||
if val.IsRaw() {
|
||||
return newRawObject(self, ret), 0
|
||||
}
|
||||
return Node{}, native.ERR_INVALID_CHAR
|
||||
return Node{}, types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) decodeString(iv int64, ep int) (Node, native.ParsingError) {
|
||||
func (self *Parser) decodeString(iv int64, ep int) (Node, types.ParsingError) {
|
||||
p := self.p - 1
|
||||
s := self.s[iv:p]
|
||||
|
||||
|
|
@ -251,36 +252,36 @@ func (self *Parser) Pos() int {
|
|||
return self.p
|
||||
}
|
||||
|
||||
func (self *Parser) Parse() (Node, native.ParsingError) {
|
||||
func (self *Parser) Parse() (Node, types.ParsingError) {
|
||||
switch val := self.decodeValue(); val.Vt {
|
||||
case native.V_EOF : return Node{}, native.ERR_EOF
|
||||
case native.V_NULL : return nullNode, 0
|
||||
case native.V_TRUE : return trueNode, 0
|
||||
case native.V_FALSE : return falseNode, 0
|
||||
case native.V_STRING : return self.decodeString(val.Iv, val.Ep)
|
||||
case native.V_ARRAY:
|
||||
case types.V_EOF : return Node{}, types.ERR_EOF
|
||||
case types.V_NULL : return nullNode, 0
|
||||
case types.V_TRUE : return trueNode, 0
|
||||
case types.V_FALSE : return falseNode, 0
|
||||
case types.V_STRING : return self.decodeString(val.Iv, val.Ep)
|
||||
case types.V_ARRAY:
|
||||
if self.noLazy {
|
||||
return self.decodeArray(make([]Node, 0, _DEFAULT_NODE_CAP))
|
||||
}
|
||||
return newRawArray(self, make([]Node, 0, _DEFAULT_NODE_CAP)), 0
|
||||
case native.V_OBJECT:
|
||||
case types.V_OBJECT:
|
||||
if self.noLazy {
|
||||
return self.decodeObject(make([]Pair, 0, _DEFAULT_NODE_CAP))
|
||||
}
|
||||
return newRawObject(self, make([]Pair, 0, _DEFAULT_NODE_CAP)), 0
|
||||
case native.V_DOUBLE : return newNumber(self.s[val.Ep:self.p]), 0
|
||||
case native.V_INTEGER : return newNumber(self.s[val.Ep:self.p]), 0
|
||||
default : return Node{}, native.ParsingError(-val.Vt)
|
||||
case types.V_DOUBLE : return newNumber(self.s[val.Ep:self.p]), 0
|
||||
case types.V_INTEGER : return newNumber(self.s[val.Ep:self.p]), 0
|
||||
default : return Node{}, types.ParsingError(-val.Vt)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) skip() (int, native.ParsingError) {
|
||||
fsm := stackPool.Get().(*native.StateMachine)
|
||||
func (self *Parser) skip() (int, types.ParsingError) {
|
||||
fsm := stackPool.Get().(*types.StateMachine)
|
||||
start := native.SkipOne(&self.s, &self.p, fsm)
|
||||
stackPool.Put(fsm)
|
||||
|
||||
if start < 0 {
|
||||
return self.p, native.ParsingError(-start)
|
||||
return self.p, types.ParsingError(-start)
|
||||
}
|
||||
return start, 0
|
||||
}
|
||||
|
|
@ -288,7 +289,7 @@ func (self *Parser) skip() (int, native.ParsingError) {
|
|||
/** Parser Factory **/
|
||||
|
||||
// Loads parse all json into interface{}
|
||||
func Loads(src string) (int, interface{}, native.ParsingError) {
|
||||
func Loads(src string) (int, interface{}, types.ParsingError) {
|
||||
ps := &Parser{s: src}
|
||||
np, err := ps.Parse()
|
||||
|
||||
|
|
@ -300,8 +301,8 @@ func Loads(src string) (int, interface{}, native.ParsingError) {
|
|||
}
|
||||
}
|
||||
|
||||
// Loads parse all json into interface{}, with numeric nodes casted to json.Number
|
||||
func LoadsUseNumber(src string) (int, interface{}, native.ParsingError) {
|
||||
// LoadsUseNumber parse all json into interface{}, with numeric nodes casted to json.Number
|
||||
func LoadsUseNumber(src string) (int, interface{}, types.ParsingError) {
|
||||
ps := &Parser{s: src}
|
||||
np, err := ps.Parse()
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package ast
|
|||
import (
|
||||
`fmt`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
type Searcher struct {
|
||||
|
|
@ -50,7 +50,7 @@ func (self *Parser) printNear(start int) string {
|
|||
func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
|
||||
self.parser.p = 0
|
||||
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
for _, p := range path {
|
||||
switch p.(type) {
|
||||
case int:
|
||||
|
|
@ -80,7 +80,7 @@ func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
|
|||
return newRawNode(self.parser.s[start:self.parser.p]), nil
|
||||
}
|
||||
|
||||
func (self *Parser) searchKey(match string) native.ParsingError {
|
||||
func (self *Parser) searchKey(match string) types.ParsingError {
|
||||
ns := len(self.s)
|
||||
if err := self.object(); err != 0 {
|
||||
return err
|
||||
|
|
@ -88,23 +88,23 @@ func (self *Parser) searchKey(match string) native.ParsingError {
|
|||
|
||||
/* check for EOF */
|
||||
if self.p = self.lspace(self.p); self.p >= ns {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty object */
|
||||
if self.s[self.p] == '}' {
|
||||
self.p++
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
var njs native.JsonState
|
||||
var err native.ParsingError
|
||||
var njs types.JsonState
|
||||
var err types.ParsingError
|
||||
/* decode each pair */
|
||||
for {
|
||||
|
||||
/* decode the key */
|
||||
if njs = self.decodeValue(); njs.Vt != native.V_STRING {
|
||||
return native.ERR_INVALID_CHAR
|
||||
if njs = self.decodeValue(); njs.Vt != types.V_STRING {
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
|
||||
/* extract the key */
|
||||
|
|
@ -135,7 +135,7 @@ func (self *Parser) searchKey(match string) native.ParsingError {
|
|||
/* check for EOF */
|
||||
self.p = self.lspace(self.p)
|
||||
if self.p >= ns {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -144,14 +144,14 @@ func (self *Parser) searchKey(match string) native.ParsingError {
|
|||
self.p++
|
||||
case '}':
|
||||
self.p++
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
default:
|
||||
return native.ERR_INVALID_CHAR
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) searchIndex(idx int) native.ParsingError {
|
||||
func (self *Parser) searchIndex(idx int) types.ParsingError {
|
||||
ns := len(self.s)
|
||||
if err := self.array(); err != 0 {
|
||||
return err
|
||||
|
|
@ -159,16 +159,16 @@ func (self *Parser) searchIndex(idx int) native.ParsingError {
|
|||
|
||||
/* check for EOF */
|
||||
if self.p = self.lspace(self.p); self.p >= ns {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for empty array */
|
||||
if self.s[self.p] == ']' {
|
||||
self.p++
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
var err native.ParsingError
|
||||
var err types.ParsingError
|
||||
/* allocate array space and parse every element */
|
||||
for i := 0; i < idx; i++ {
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ func (self *Parser) searchIndex(idx int) native.ParsingError {
|
|||
/* check for EOF */
|
||||
self.p = self.lspace(self.p)
|
||||
if self.p >= ns {
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
}
|
||||
|
||||
/* check for the next character */
|
||||
|
|
@ -189,9 +189,9 @@ func (self *Parser) searchIndex(idx int) native.ParsingError {
|
|||
self.p++
|
||||
case ']':
|
||||
self.p++
|
||||
return native.ERR_EOF
|
||||
return types.ERR_EOF
|
||||
default:
|
||||
return native.ERR_INVALID_CHAR
|
||||
return types.ERR_INVALID_CHAR
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ func addr2str(p unsafe.Pointer, n int64) (s string) {
|
|||
return
|
||||
}
|
||||
|
||||
func unquoteBytes(s string, m *[]byte) native.ParsingError {
|
||||
func unquoteBytes(s string, m *[]byte) types.ParsingError {
|
||||
pos := -1
|
||||
slv := (*rt.GoSlice)(unsafe.Pointer(m))
|
||||
str := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
|
|
@ -58,7 +59,7 @@ func unquoteBytes(s string, m *[]byte) native.ParsingError {
|
|||
|
||||
/* check for errors */
|
||||
if ret < 0 {
|
||||
return native.ParsingError(-ret)
|
||||
return types.ParsingError(-ret)
|
||||
}
|
||||
|
||||
/* update the length */
|
||||
|
|
@ -66,7 +67,7 @@ func unquoteBytes(s string, m *[]byte) native.ParsingError {
|
|||
return 0
|
||||
}
|
||||
|
||||
func UnquoteString(s string) (ret string, err native.ParsingError) {
|
||||
func UnquoteString(s string) (ret string, err types.ParsingError) {
|
||||
mm := make([]byte, 0, len(s))
|
||||
err = unquoteBytes(s, &mm)
|
||||
ret = rt.Mem2Str(mm)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
`github.com/bytedance/sonic/internal/caching`
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
)
|
||||
|
|
@ -424,7 +425,7 @@ func (self *_Assembler) base64_error() {
|
|||
func (self *_Assembler) parsing_error() {
|
||||
self.Link(_LB_eof_error) // _eof_error:
|
||||
self.Emit("MOVQ" , _IL, _IC) // MOVQ IL, IC
|
||||
self.Emit("MOVL" , jit.Imm(int64(native.ERR_EOF)), _EP) // MOVL ${native.ERR_EOF}, EP
|
||||
self.Emit("MOVL" , jit.Imm(int64(types.ERR_EOF)), _EP) // MOVL ${types.ERR_EOF}, EP
|
||||
self.Sjmp("JMP" , _LB_parsing_error) // JMP _parsing_error
|
||||
self.Link(_LB_unquote_error) // _unquote_error:
|
||||
self.Emit("SUBQ" , _VAR_sr, _SI) // SUBQ sr, SI
|
||||
|
|
@ -457,7 +458,7 @@ func (self *_Assembler) parsing_error() {
|
|||
self.Link(_LB_char_1_error) // _char_1_error:
|
||||
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
self.Link(_LB_char_0_error) // _char_0_error:
|
||||
self.Emit("MOVL" , jit.Imm(int64(native.ERR_INVALID_CHAR)), _EP) // MOVL ${native.ERR_INVALID_CHAR}, EP
|
||||
self.Emit("MOVL" , jit.Imm(int64(types.ERR_INVALID_CHAR)), _EP) // MOVL ${types.ERR_INVALID_CHAR}, EP
|
||||
self.Link(_LB_parsing_error) // _parsing_error:
|
||||
self.Emit("MOVOU", _ARG_s, _X0) // MOVOU s, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
|
||||
|
|
@ -570,15 +571,15 @@ func init() {
|
|||
}
|
||||
|
||||
func (self *_Assembler) range_single() {
|
||||
self.Emit("VMOVSD" , _VAR_st_Dv, _X0) // VMOVSD st.Dv, X0
|
||||
self.Emit("MOVSD" , _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
|
||||
self.Emit("MOVQ" , _V_max_f32, _AX) // MOVQ _max_f32, AX
|
||||
self.Emit("MOVQ" , jit.Gitab(_I_float32), _ET) // MOVQ ${itab(float32)}, ET
|
||||
self.Emit("MOVQ" , jit.Gtype(_T_float32), _EP) // MOVQ ${type(float32)}, EP
|
||||
self.Emit("VUCOMISD", jit.Ptr(_AX, 0), _X0) // VUCOMISD (AX), X0
|
||||
self.Emit("UCOMISD" , jit.Ptr(_AX, 0), _X0) // UCOMISD (AX), X0
|
||||
self.Sjmp("JA" , _LB_range_error) // JA _range_error
|
||||
self.Emit("MOVQ" , _V_min_f32, _AX) // MOVQ _min_f32, AX
|
||||
self.Emit("VMOVSD" , jit.Ptr(_AX, 0), _X1) // VMOVSD (AX), X1
|
||||
self.Emit("VUCOMISD", _X0, _X1) // VUCOMISD X0, X1
|
||||
self.Emit("MOVSD" , jit.Ptr(_AX, 0), _X1) // MOVSD (AX), X1
|
||||
self.Emit("UCOMISD" , _X0, _X1) // UCOMISD X0, X1
|
||||
self.Sjmp("JA" , _LB_range_error) // JA _range_error
|
||||
self.Emit("CVTSD2SS", _X0, _X0) // CVTSD2SS X0, X0
|
||||
}
|
||||
|
|
@ -634,7 +635,7 @@ func (self *_Assembler) unquote_once(p obj.Addr, n obj.Addr) {
|
|||
self.Emit("XORL" , _R8, _R8) // XORL R8, R8
|
||||
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _ARG_fv) // BTQ ${_F_disable_urc}, fv
|
||||
self.Emit("SETCC", _R8) // SETCC R8
|
||||
self.Emit("SHLQ" , jit.Imm(native.B_UNICODE_REPLACE), _R8) // SHLQ ${native.B_UNICODE_REPLACE}, R8
|
||||
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8
|
||||
self.call(_F_unquote) // CALL unquote
|
||||
self.Emit("MOVQ" , n, _SI) // MOVQ ${n}, SI
|
||||
self.Emit("ADDQ" , jit.Imm(1), _SI) // ADDQ $1, SI
|
||||
|
|
@ -661,11 +662,11 @@ func (self *_Assembler) unquote_twice(p obj.Addr, n obj.Addr) {
|
|||
self.Emit("MOVQ" , n, _SI) // MOVQ ${n}, SI
|
||||
self.Emit("MOVQ" , _DX, p) // MOVQ DX, ${p}
|
||||
self.Emit("LEAQ" , _VAR_sr, _CX) // LEAQ sr, CX
|
||||
self.Emit("MOVL" , jit.Imm(native.F_DOUBLE_UNQUOTE), _R8) // MOVL ${native.F_DOUBLE_UNQUOTE}, R8
|
||||
self.Emit("MOVL" , jit.Imm(types.F_DOUBLE_UNQUOTE), _R8) // MOVL ${types.F_DOUBLE_UNQUOTE}, R8
|
||||
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _ARG_fv) // BTQ ${_F_disable_urc}, AX
|
||||
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
|
||||
self.Emit("SETCC", _AX) // SETCC AX
|
||||
self.Emit("SHLQ" , jit.Imm(native.B_UNICODE_REPLACE), _AX) // SHLQ ${native.B_UNICODE_REPLACE}, AX
|
||||
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _AX) // SHLQ ${types.B_UNICODE_REPLACE}, AX
|
||||
self.Emit("ORQ" , _AX, _R8) // ORQ AX, R8
|
||||
self.call(_F_unquote) // CALL unquote
|
||||
self.Emit("MOVQ" , n, _SI) // MOVQ ${n}, SI
|
||||
|
|
@ -1013,15 +1014,15 @@ func (self *_Assembler) _asm_OP_u64(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single() // RANGE float32
|
||||
self.Emit("VMOVSS", _X0, jit.Ptr(_VP, 0)) // VMOVSS X0, (VP)
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single() // RANGE float32
|
||||
self.Emit("MOVSS", _X0, jit.Ptr(_VP, 0)) // MOVSS X0, (VP)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f64(_ *_Instr) {
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.Emit("VMOVSD", _VAR_st_Dv, _X0) // VMOVSD st.Dv, X0
|
||||
self.Emit("VMOVSD", _X0, jit.Ptr(_VP, 0)) // VMOVSD X0, (VP)
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.Emit("MOVSD", _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
|
||||
self.Emit("MOVSD", _X0, jit.Ptr(_VP, 0)) // MOVSD X0, (VP)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_unquote(_ *_Instr) {
|
||||
|
|
@ -1041,13 +1042,13 @@ func (self *_Assembler) _asm_OP_nil_1(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_nil_2(_ *_Instr) {
|
||||
self.Emit("VPXOR", _X0, _X0, _X0) // VPXOR X0, X0, X0
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_nil_3(_ *_Instr) {
|
||||
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
|
||||
self.Emit("VPXOR", _X0, _X0, _X0) // VPXOR X0, X0, X0
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 16)) // MOVOU X0, 16(VP)
|
||||
}
|
||||
|
|
@ -1133,7 +1134,7 @@ func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
|
|||
func (self *_Assembler) _asm_OP_map_key_f32(p *_Instr) {
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single() // RANGE float32
|
||||
self.Emit("VMOVSS", _X0, _VAR_st_Dv) // VMOVSS X0, st.Dv
|
||||
self.Emit("MOVSS", _X0, _VAR_st_Dv) // MOVSS X0, st.Dv
|
||||
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
|
||||
}
|
||||
|
||||
|
|
@ -1371,7 +1372,7 @@ func (self *_Assembler) _asm_OP_drop_2(_ *_Instr) {
|
|||
self.Emit("SUBQ" , jit.Imm(16), _AX) // SUBQ $16, AX
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 8), _VP) // MOVQ 8(ST)(AX), VP
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
|
||||
self.Emit("VPXOR", _X0, _X0, _X0) // VPXOR X0, X0, X0
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 8)) // MOVOU X0, 8(ST)(AX)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import (
|
|||
|
||||
`github.com/bytedance/sonic/internal/caching`
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/stretchr/testify/assert`
|
||||
`github.com/stretchr/testify/require`
|
||||
|
|
@ -182,26 +182,26 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_str/error_eof",
|
||||
ins: []_Instr{newInsOp(_OP_str)},
|
||||
src: `12345`,
|
||||
err: SyntaxError{Src: `12345`, Pos: 5, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: `12345`, Pos: 5, Code: types.ERR_EOF},
|
||||
val: new(string),
|
||||
}, {
|
||||
key: "_OP_str/error_invalid_escape",
|
||||
ins: []_Instr{newInsOp(_OP_str)},
|
||||
src: `12\g345"`,
|
||||
err: SyntaxError{Src: `12\g345"`, Pos: 3, Code: native.ERR_INVALID_ESCAPE},
|
||||
err: SyntaxError{Src: `12\g345"`, Pos: 3, Code: types.ERR_INVALID_ESCAPE},
|
||||
val: new(string),
|
||||
}, {
|
||||
key: "_OP_str/error_invalid_unicode",
|
||||
ins: []_Instr{newInsOp(_OP_str)},
|
||||
src: `hello\ud800world"`,
|
||||
opt: 1 << _F_disable_urc,
|
||||
err: SyntaxError{Src: `hello\ud800world"`, Pos: 7, Code: native.ERR_INVALID_UNICODE},
|
||||
err: SyntaxError{Src: `hello\ud800world"`, Pos: 7, Code: types.ERR_INVALID_UNICODE},
|
||||
val: new(string),
|
||||
}, {
|
||||
key: "_OP_str/error_invalid_char",
|
||||
ins: []_Instr{newInsOp(_OP_str)},
|
||||
src: `12\u1ggg345"`,
|
||||
err: SyntaxError{Src: `12\u1ggg345"`, Pos: 5, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `12\u1ggg345"`, Pos: 5, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(string),
|
||||
}, {
|
||||
key: "_OP_bin",
|
||||
|
|
@ -213,7 +213,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_bin/error_eof",
|
||||
ins: []_Instr{newInsOp(_OP_bin)},
|
||||
src: `aGVsbG8sIHdvcmxk`,
|
||||
err: SyntaxError{Src: `aGVsbG8sIHdvcmxk`, Pos: 16, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: `aGVsbG8sIHdvcmxk`, Pos: 16, Code: types.ERR_EOF},
|
||||
val: new([]byte),
|
||||
}, {
|
||||
key: "_OP_bin/error_corrupt_input",
|
||||
|
|
@ -243,25 +243,25 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_bool/error_eof_1",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: "tru",
|
||||
err: SyntaxError{Src: `tru`, Pos: 3, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: `tru`, Pos: 3, Code: types.ERR_EOF},
|
||||
val: new(bool),
|
||||
}, {
|
||||
key: "_OP_bool/error_eof_2",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: "fals",
|
||||
err: SyntaxError{Src: `fals`, Pos: 4, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: `fals`, Pos: 4, Code: types.ERR_EOF},
|
||||
val: new(bool),
|
||||
}, {
|
||||
key: "_OP_bool/error_invalid_char_1",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: "falxe",
|
||||
err: SyntaxError{Src: `falxe`, Pos: 3, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `falxe`, Pos: 3, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(bool),
|
||||
}, {
|
||||
key: "_OP_bool/error_invalid_char_2",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: "falsx",
|
||||
err: SyntaxError{Src: `falsx`, Pos: 4, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `falsx`, Pos: 4, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(bool),
|
||||
}, {
|
||||
key: "_OP_num/positive",
|
||||
|
|
@ -279,13 +279,13 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_num/error_eof",
|
||||
ins: []_Instr{newInsOp(_OP_num)},
|
||||
src: "-",
|
||||
err: SyntaxError{Src: `-`, Pos: 1, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: `-`, Pos: 1, Code: types.ERR_EOF},
|
||||
val: new(json.Number),
|
||||
}, {
|
||||
key: "_OP_num/error_invalid_char",
|
||||
ins: []_Instr{newInsOp(_OP_num)},
|
||||
src: "xxx",
|
||||
err: SyntaxError{Src: `xxx`, Pos: 0, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `xxx`, Pos: 0, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(json.Number),
|
||||
}, {
|
||||
key: "_OP_i8",
|
||||
|
|
@ -303,7 +303,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_i8/error_wrong_type",
|
||||
ins: []_Instr{newInsOp(_OP_i8)},
|
||||
src: "12.34",
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: native.ERR_INVALID_NUMBER_FMT},
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(int8),
|
||||
}, {
|
||||
key: "_OP_u8",
|
||||
|
|
@ -321,13 +321,13 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_u8/error_underflow",
|
||||
ins: []_Instr{newInsOp(_OP_u8)},
|
||||
src: "-123",
|
||||
err: SyntaxError{Src: `-123`, Pos: 0, Code: native.ERR_INVALID_NUMBER_FMT},
|
||||
err: SyntaxError{Src: `-123`, Pos: 0, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(uint8),
|
||||
}, {
|
||||
key: "_OP_u8/error_wrong_type",
|
||||
ins: []_Instr{newInsOp(_OP_u8)},
|
||||
src: "12.34",
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: native.ERR_INVALID_NUMBER_FMT},
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(uint8),
|
||||
}, {
|
||||
key: "_OP_f32",
|
||||
|
|
@ -369,7 +369,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_unquote/error_invalid_end",
|
||||
ins: []_Instr{newInsOp(_OP_unquote)},
|
||||
src: `\"te\\\"st"`,
|
||||
err: SyntaxError{Src: `\"te\\\"st"`, Pos: 8, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `\"te\\\"st"`, Pos: 8, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(string),
|
||||
}, {
|
||||
key: "_OP_nil_1",
|
||||
|
|
@ -382,7 +382,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
ins: []_Instr{newInsOp(_OP_nil_2)},
|
||||
src: "",
|
||||
exp: error(nil),
|
||||
val: (func() *error { v := new(error); *v = native.ERR_EOF; return v })(),
|
||||
val: (func() *error { v := new(error); *v = types.ERR_EOF; return v })(),
|
||||
}, {
|
||||
key: "_OP_nil_3",
|
||||
ins: []_Instr{newInsOp(_OP_nil_3)},
|
||||
|
|
@ -623,7 +623,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_lspace/error",
|
||||
ins: []_Instr{newInsOp(_OP_lspace)},
|
||||
src: "",
|
||||
err: SyntaxError{Src: ``, Pos: 0, Code: native.ERR_EOF},
|
||||
err: SyntaxError{Src: ``, Pos: 0, Code: types.ERR_EOF},
|
||||
val: nil,
|
||||
}, {
|
||||
key: "_OP_match_char/correct",
|
||||
|
|
@ -635,7 +635,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_match_char/error",
|
||||
ins: []_Instr{newInsVb(_OP_match_char, 'b')},
|
||||
src: "a",
|
||||
err: SyntaxError{Src: `a`, Pos: 0, Code: native.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `a`, Pos: 0, Code: types.ERR_INVALID_CHAR},
|
||||
val: nil,
|
||||
}, {
|
||||
key: "_OP_switch",
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ import (
|
|||
`strconv`
|
||||
`strings`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
type SyntaxError struct {
|
||||
Pos int
|
||||
Src string
|
||||
Code native.ParsingError
|
||||
Code types.ParsingError
|
||||
}
|
||||
|
||||
func (self SyntaxError) Error() string {
|
||||
|
|
@ -86,7 +86,7 @@ func clamp_zero(v int) int {
|
|||
}
|
||||
}
|
||||
|
||||
func error_wrap(src string, pos int, code native.ParsingError) error {
|
||||
func error_wrap(src string, pos int, code types.ParsingError) error {
|
||||
return SyntaxError {
|
||||
Pos : pos,
|
||||
Src : src,
|
||||
|
|
@ -111,6 +111,6 @@ func error_value(value string, vtype reflect.Type) error {
|
|||
}
|
||||
|
||||
//go:nosplit
|
||||
func throw_invalid_type(vt native.ValueType) {
|
||||
func throw_invalid_type(vt types.ValueType) {
|
||||
throw(fmt.Sprintf("invalid value type: %d", vt))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ package decoder
|
|||
import (
|
||||
`testing`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
func make_err(src string, pos int) SyntaxError {
|
||||
return SyntaxError {
|
||||
Src : src,
|
||||
Pos : pos,
|
||||
Code : native.ERR_INVALID_CHAR,
|
||||
Code : types.ERR_INVALID_CHAR,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
)
|
||||
|
|
@ -112,8 +113,8 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
_V_max = jit.Imm(int64(native.V_MAX))
|
||||
_V_eof = jit.Imm(int64(native.ERR_EOF))
|
||||
_V_max = jit.Imm(int64(types.V_MAX))
|
||||
_V_eof = jit.Imm(int64(types.ERR_EOF))
|
||||
_F_value = jit.Imm(int64(native.S_value))
|
||||
)
|
||||
|
||||
|
|
@ -293,7 +294,7 @@ func (self *_ValueDecoder) instrs() {
|
|||
self.Emit("XORL" , _R8, _R8) // XORL R8, R8
|
||||
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _VP) // BTQ ${_F_disable_urc}, VP
|
||||
self.Emit("SETCC", _R8) // SETCC R8
|
||||
self.Emit("SHLQ" , jit.Imm(native.B_UNICODE_REPLACE), _R8) // SHLQ ${native.B_UNICODE_REPLACE}, R8
|
||||
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8
|
||||
self.call(_F_unquote) // CALL unquote
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_esc_error) // JS _esc_error
|
||||
|
|
@ -309,14 +310,14 @@ func (self *_ValueDecoder) instrs() {
|
|||
|
||||
/* V_DOUBLE */
|
||||
self.Link(_SW_case_V_DOUBLE)
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VP) // BTQ ${_F_use_number}, VP
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("VMOVSD", _VAR_vv_Dv, _X0) // VMOVSD st.Dv, X0
|
||||
self.Emit("VMOVSD", _X0, jit.Ptr(_SP, 0)) // VMOVSD X0, (SP)
|
||||
self.Emit("BTQ" , jit.Imm(_F_use_number), _VP) // BTQ ${_F_use_number}, VP
|
||||
self.Sjmp("JC" , "_use_number") // JC _use_number
|
||||
self.Emit("MOVSD", _VAR_vv_Dv, _X0) // MOVSD st.Dv, X0
|
||||
self.Emit("MOVSD", _X0, jit.Ptr(_SP, 0)) // MOVSD X0, (SP)
|
||||
self.call_go(_F_convT64) // CALL_GO convT64
|
||||
self.Emit("MOVQ" , _T_float64, _RT) // MOVQ ${type(float64)}, RT
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 8), _RV) // MOVQ 8(SP), RV
|
||||
self.Sjmp("JMP" , _LB_done) // JMP _done
|
||||
self.Emit("MOVQ" , _T_float64, _RT) // MOVQ ${type(float64)}, RT
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP, 8), _RV) // MOVQ 8(SP), RV
|
||||
self.Sjmp("JMP" , _LB_done) // JMP _done
|
||||
|
||||
/* V_INTEGER */
|
||||
self.Link(_SW_case_V_INTEGER)
|
||||
|
|
|
|||
|
|
@ -39,15 +39,15 @@
|
|||
#define ERR_INVALID_CHAR $-2
|
||||
|
||||
#define lspace(to) \
|
||||
MOVQ PS, DI \
|
||||
MOVQ PN, SI \
|
||||
MOVQ PI, DX \
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·_subr__lspace(SB), AX \
|
||||
CALL AX \
|
||||
MOVQ AX, PI \
|
||||
TESTQ AX, AX \
|
||||
JNS to \
|
||||
RET \
|
||||
MOVQ PS, DI \
|
||||
MOVQ PN, SI \
|
||||
MOVQ PI, DX \
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_lspace(SB), AX \
|
||||
CALL AX \
|
||||
MOVQ AX, PI \
|
||||
TESTQ AX, AX \
|
||||
JNS to \
|
||||
RET \
|
||||
to:
|
||||
|
||||
#define match_eof(to) \
|
||||
|
|
@ -337,7 +337,7 @@ TEXT decodeObjectKey(SB), NOSPLIT, $120 - 0
|
|||
LEAQ VAR_in, DI
|
||||
LEAQ VAR_in_PI, SI
|
||||
LEAQ VAR_vv, DX
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·_subr__vstring(SB), AX
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_vstring(SB), AX
|
||||
CALL AX
|
||||
MOVQ VAR_in_PI, PI
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ _unquote:
|
|||
BTQ F_DISABLE_URC, FL
|
||||
SETCC R8
|
||||
SHLQ B_UNICODE_REPLACE, R8
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·_subr__unquote(SB), AX
|
||||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_unquote(SB), AX
|
||||
CALL AX
|
||||
TESTQ AX, AX
|
||||
JS _escape_error
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/ast`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/require`
|
||||
|
|
@ -32,7 +32,7 @@ import (
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func decodeInterface(s string, f uint64) (int, interface{}, native.ParsingError)
|
||||
func decodeInterface(s string, f uint64) (int, interface{}, types.ParsingError)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
@ -54,7 +54,7 @@ func TestGeneric_DecodeInterface(t *testing.T) {
|
|||
func TestGeneric_DecodeObjectKeyString(t *testing.T) {
|
||||
r := decodeObjectKeyString(` "hello\u2333world"`, 4)
|
||||
if v := (*rt.GoString)(unsafe.Pointer(&r)).Len; v < 0 {
|
||||
require.NoError(t, native.ParsingError(-v))
|
||||
require.NoError(t, types.ParsingError(-v))
|
||||
}
|
||||
spew.Dump(r)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/caching`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ var (
|
|||
type _Stack struct {
|
||||
sp uintptr
|
||||
sb [_MaxStack]unsafe.Pointer
|
||||
mm native.StateMachine
|
||||
mm types.StateMachine
|
||||
}
|
||||
|
||||
type _Decoder func(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
`strconv`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/cpu`
|
||||
`github.com/bytedance/sonic/internal/jit`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
|
|
@ -115,10 +116,6 @@ var (
|
|||
|
||||
var (
|
||||
_X0 = jit.Reg("X0")
|
||||
_X1 = jit.Reg("X1")
|
||||
)
|
||||
|
||||
var (
|
||||
_Y0 = jit.Reg("Y0")
|
||||
_Y1 = jit.Reg("Y1")
|
||||
_Y2 = jit.Reg("Y2")
|
||||
|
|
@ -411,16 +408,16 @@ func (self *_Assembler) save_state() {
|
|||
}
|
||||
|
||||
func (self *_Assembler) drop_state(decr int64) {
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("SUBQ" , jit.Imm(decr), _AX) // SUBQ $decr, AX
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 8), _SP_x) // MOVQ 8(ST)(AX), SP.x
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 16), _SP_f) // MOVQ 16(ST)(AX), SP.f
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 24), _SP_p) // MOVQ 24(ST)(AX), SP.p
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 32), _SP_q) // MOVQ 32(ST)(AX), SP.q
|
||||
self.Emit("VPXOR" , _Y0, _Y0, _Y0) // VPXOR Y0, Y0, Y0
|
||||
self.Emit("VMOVDQU", _Y0, jit.Sib(_ST, _AX, 1, 8)) // VMOVDQU Y0, 8(ST)(AX)
|
||||
self.Emit("VZEROUPPER") // VZEROUPPER
|
||||
self.Emit("MOVQ" , jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("SUBQ" , jit.Imm(decr), _AX) // SUBQ $decr, AX
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 8), _SP_x) // MOVQ 8(ST)(AX), SP.x
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 16), _SP_f) // MOVQ 16(ST)(AX), SP.f
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 24), _SP_p) // MOVQ 24(ST)(AX), SP.p
|
||||
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 32), _SP_q) // MOVQ 32(ST)(AX), SP.q
|
||||
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
|
||||
self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 8)) // MOVOU X0, 8(ST)(AX)
|
||||
self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 24)) // MOVOU X0, 24(ST)(AX)
|
||||
}
|
||||
|
||||
/** Buffer Helpers **/
|
||||
|
|
@ -654,6 +651,106 @@ func (self *_Assembler) encode_string(fn obj.Addr, doubleQuote bool) {
|
|||
self.close_quote(doubleQuote) // QCLOSE $doubleQuote
|
||||
}
|
||||
|
||||
/** Zero Value Check Routine **/
|
||||
|
||||
func (self *_Assembler) check_zero(nb int, dest int) {
|
||||
i := int64(0)
|
||||
e := int64(nb)
|
||||
|
||||
/* special case: zero-sized value, always empty */
|
||||
if e == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
/* default instructions for AVX2 */
|
||||
vclear := func(v obj.Addr) { self.Emit("VPXOR" , v, v, v) }
|
||||
vset1a := func(a, b obj.Addr) { self.Emit("VPCMPEQB", a, a, b) }
|
||||
vandpb := func(b, a, r obj.Addr) { self.Emit("VPAND" , b, a, r) }
|
||||
vcmpeq := func(b, a, r obj.Addr) { self.Emit("VPCMPEQB", b, a, r) }
|
||||
|
||||
/* fall-back instructions for AVX */
|
||||
if !cpu.HasAVX2 {
|
||||
vclear = func(v obj.Addr) { self.Emit("VXORPS", v, v, v) }
|
||||
vset1a = func(a, b obj.Addr) { self.Emit("VCMPPS", a, a, b, jit.Imm(0x0f)) }
|
||||
vandpb = func(b, a, r obj.Addr) { self.Emit("VANDPS", b, a, r) }
|
||||
vcmpeq = func(b, a, r obj.Addr) { self.Emit("VCMPPS", b, a, r, jit.Imm(0x00)) }
|
||||
}
|
||||
|
||||
/* if n is less than 32 byte, only scalar code will be used;
|
||||
* otherwise AVX is used, so clear Y0, and set Y1 to all 1s */
|
||||
if e >= 32 {
|
||||
vclear(_Y0) // CLEAR Y0
|
||||
vset1a(_Y0, _Y1) // SET1A Y0, Y1
|
||||
}
|
||||
|
||||
/* 128-byte tests */
|
||||
for i <= e - 128 {
|
||||
vcmpeq(jit.Ptr(_SP_p, i + 0), _Y0, _Y2) // CMPEQ i+0(SP.p), Y0, Y2
|
||||
vcmpeq(jit.Ptr(_SP_p, i + 32), _Y0, _Y3) // CMPEQ i+32(SP.p), Y0, Y3
|
||||
vcmpeq(jit.Ptr(_SP_p, i + 64), _Y0, _Y4) // CMPEQ i+64(SP.p), Y0, Y4
|
||||
vcmpeq(jit.Ptr(_SP_p, i + 96), _Y0, _Y5) // CMPEQ i+96(SP.p), Y0, Y5
|
||||
vandpb(_Y3, _Y2, _Y2) // ANDPB Y3, Y2, Y2
|
||||
vandpb(_Y5, _Y4, _Y3) // ANDPB Y5, Y4, Y3
|
||||
vandpb(_Y2, _Y3, _Y3) // ANDPB Y2, Y3, Y3
|
||||
self.Emit("VPTEST", _Y1, _Y3) // VPTEST Y1, Y3
|
||||
self.Sjmp("JNC" , "_not_zero_z_{n}") // JNC _not_zero_z_{n}
|
||||
i += 128
|
||||
}
|
||||
|
||||
/* 32-byte tests */
|
||||
for i <= e - 32 {
|
||||
vcmpeq(jit.Ptr(_SP_p, i), _Y0, _Y2) // CMPEQ i(SP.p), Y0, Y2
|
||||
self.Emit("VPTEST", _Y1, _Y2) // VPTEST Y1, Y2
|
||||
self.Sjmp("JNC" , "_not_zero_z_{n}") // JNC _not_zero_z_{n}
|
||||
i += 32
|
||||
}
|
||||
|
||||
/* VZEROUPPER to avoid AVX-SSE transition penalty */
|
||||
if e >= 32 {
|
||||
self.Emit("VZEROUPPER")
|
||||
}
|
||||
|
||||
/* 8-byte tests */
|
||||
for i <= e - 8 {
|
||||
self.Emit("CMPQ", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPQ i(SP.p), $0
|
||||
self.Sjmp("JNE" , "_not_zero_{n}") // JNE _not_zero_{n}
|
||||
i += 8
|
||||
}
|
||||
|
||||
/* 4 byte test */
|
||||
if i <= e - 4 {
|
||||
self.Emit("CMPL", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPL i(SP.p), $0
|
||||
self.Sjmp("JNE" , "_not_zero_{n}") // JNE _not_zero_{n}
|
||||
i += 4
|
||||
}
|
||||
|
||||
/* 2 byte test */
|
||||
if i <= e - 2 {
|
||||
self.Emit("CMPW", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPW i(SP.p), $0
|
||||
self.Sjmp("JNE" , "_not_zero_{n}") // JNE _not_zero_{n}
|
||||
i += 2
|
||||
}
|
||||
|
||||
/* the last byte */
|
||||
if i < e {
|
||||
self.Emit("CMPB", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPB i(SP.p), $0
|
||||
self.Sjmp("JNE" , "_not_zero_{n}") // JNE _not_zero_{n}
|
||||
}
|
||||
|
||||
/* value is not zero */
|
||||
if e < 32 {
|
||||
self.Xjmp("JMP", dest)
|
||||
self.Link("_not_zero_{n}")
|
||||
return
|
||||
}
|
||||
|
||||
/* VZEROUPPER to avoid AVX-SSE transition penalty */
|
||||
self.Xjmp("JMP", dest)
|
||||
self.Link("_not_zero_z_{n}")
|
||||
self.Emit("VZEROUPPER")
|
||||
self.Link("_not_zero_{n}")
|
||||
}
|
||||
|
||||
/** OpCode Assembler Functions **/
|
||||
|
||||
var (
|
||||
|
|
@ -671,7 +768,7 @@ var (
|
|||
|
||||
var (
|
||||
_F_memmove = jit.Func(memmove)
|
||||
_F_isZeroSafe = jit.Func(isZeroSafe)
|
||||
_F_isZeroTyped = jit.Func(isZeroTyped)
|
||||
_F_mapiternext = jit.Func(mapiternext)
|
||||
_F_mapiterinit = jit.Func(mapiterinit)
|
||||
_F_error_number = jit.Func(error_number)
|
||||
|
|
@ -960,103 +1057,15 @@ func (self *_Assembler) _asm_OP_is_zero_map(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_is_zero_mem(p *_Instr) {
|
||||
i := int64(0)
|
||||
e := int64(p.vlen())
|
||||
|
||||
/* increse the offset, and decide what jumps to use */
|
||||
incr_jump := func(np string, op string, d int64, avx2 bool) {
|
||||
if i += d; avx2 && e >= 32 {
|
||||
self.Sjmp(np, "not_zero_z_{n}")
|
||||
} else if i < e || e >= 32 {
|
||||
self.Sjmp(np, "not_zero_{n}")
|
||||
} else {
|
||||
self.Xjmp(op, p.vi())
|
||||
}
|
||||
}
|
||||
|
||||
/* if n is less than 32 byte, only SSE2 will be used;
|
||||
* otherwise AVX2 is used, so clear Y0, and set Y1 to all 0xff */
|
||||
if e < 32 {
|
||||
self.Emit("VPXOR", _X0, _X0, _X0) // VPXOR X0, X0, X0
|
||||
} else {
|
||||
self.Emit("VPXOR" , _Y0, _Y0, _Y0) // VPXOR Y0, Y0, Y0
|
||||
self.Emit("VPCMPEQB", _Y1, _Y1, _Y1) // VPCMPEQB Y1, Y1, Y1
|
||||
}
|
||||
|
||||
/* 128-byte tests */
|
||||
for i <= e - 128 {
|
||||
self.Emit("VPCMPEQB", jit.Ptr(_SP_p, i + 0), _Y0, _Y2) // VPCMPEQB i+0(SP.p), Y0, Y2
|
||||
self.Emit("VPCMPEQB", jit.Ptr(_SP_p, i + 32), _Y0, _Y3) // VPCMPEQB i+32(SP.p), Y0, Y3
|
||||
self.Emit("VPCMPEQB", jit.Ptr(_SP_p, i + 64), _Y0, _Y4) // VPCMPEQB i+64(SP.p), Y0, Y4
|
||||
self.Emit("VPCMPEQB", jit.Ptr(_SP_p, i + 96), _Y0, _Y5) // VPCMPEQB i+96(SP.p), Y0, Y5
|
||||
self.Emit("VPAND" , _Y2, _Y3, _Y2) // VPAND Y2, Y3, Y2
|
||||
self.Emit("VPAND" , _Y4, _Y5, _Y3) // VPAND Y4, Y5, Y3
|
||||
self.Emit("VPXOR" , _Y3, _Y1, _Y3) // VPXOR Y3, Y1, Y3
|
||||
self.Emit("VPTEST" , _Y2, _Y3) // VPTEST Y2, Y3
|
||||
incr_jump("JNC" , "JC", 128, true) // JNC not_zero_z_{n}
|
||||
}
|
||||
|
||||
/* 32-byte tests */
|
||||
for i <= e - 32 {
|
||||
self.Emit("VPCMPEQB", jit.Ptr(_SP_p, i), _Y0, _Y2) // VPCMPEQB i(SP.p), Y0, Y2
|
||||
self.Emit("VPTEST" , _Y2, _Y1) // VPTEST Y2, Y1
|
||||
incr_jump("JNC" , "JC", 32, true) // JNC not_zero_z_{n}
|
||||
}
|
||||
|
||||
/* VZEROUPPER to avoid AVX-SSE transition penalty */
|
||||
if e >= 32 {
|
||||
self.Emit("VZEROUPPER")
|
||||
}
|
||||
|
||||
/* 16 bytes test */
|
||||
if i <= e - 16 {
|
||||
self.Emit("PCMPEQB" , jit.Ptr(_SP_p, i), _X0, _X1) // PCMPEQB i(SP.p), X0, X1
|
||||
self.Emit("PMOVMSKB", _X1, _AX) // PMOVMSKB X1, AX
|
||||
self.Emit("CMPQ" , jit.Imm(-1), _AX) // CMPQ $-1, AX
|
||||
incr_jump("JNE" , "JE", 16, false) // JNE not_zero_{n}
|
||||
}
|
||||
|
||||
/* 8-byte tests */
|
||||
if i <= e - 8 {
|
||||
self.Emit("CMPQ", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPQ i(SP.p), $0
|
||||
incr_jump("JNE" , "JE", 8, false) // JNE not_zero_{n}
|
||||
}
|
||||
|
||||
/* 4 byte test */
|
||||
if i <= e - 4 {
|
||||
self.Emit("CMPL", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPL i(SP.p), $0
|
||||
incr_jump("JNE" , "JE", 4, false) // JNE not_zero_{n}
|
||||
}
|
||||
|
||||
/* 2 byte test */
|
||||
if i <= e - 2 {
|
||||
self.Emit("CMPW", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPW i(SP.p), $0
|
||||
incr_jump("JNE" , "JE", 2, false) // JNE not_zero_{n}
|
||||
}
|
||||
|
||||
/* the last byte */
|
||||
if i < e {
|
||||
self.Emit("CMPB", jit.Ptr(_SP_p, i), jit.Imm(0)) // CMPB i(SP.p), $0
|
||||
incr_jump("JNE" , "JE", 1, false) // JNE not_zero_{n}
|
||||
}
|
||||
|
||||
/* VZEROUPPER to avoid AVX-SSE transition penalty */
|
||||
if e >= 32 {
|
||||
self.Xjmp("JMP", p.vi())
|
||||
self.Link("not_zero_z_{n}")
|
||||
self.Emit("VZEROUPPER")
|
||||
}
|
||||
|
||||
/* value is not zero */
|
||||
self.Link("not_zero_{n}")
|
||||
self.NOP()
|
||||
self.check_zero(p.vlen(), p.vi())
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_is_zero_safe(p *_Instr) {
|
||||
self.check_zero(p.vlen(), p.vi()) // CHECKZ $p.vlen(), p.vi()
|
||||
self.Emit("MOVQ", jit.Type(p.vt()), _AX) // MOVQ $p.vt(), AX
|
||||
self.Emit("MOVQ", _SP_p, jit.Ptr(_SP, 0)) // MOVQ SP.p, (SP)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
|
||||
self.call_go(_F_isZeroSafe) // CALL_GO isZeroSafe
|
||||
self.call_go(_F_isZeroTyped) // CALL_GO isZeroTyped
|
||||
self.Emit("CMPQ", jit.Ptr(_SP, 16), jit.Imm(0)) // CMPQ 16(SP), $0
|
||||
self.Xjmp("JNE" , p.vi()) // JNE p.vi()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,12 +176,8 @@ func encodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler) error {
|
|||
}
|
||||
}
|
||||
|
||||
func isZeroMem(p unsafe.Pointer, nb int) bool {
|
||||
return native.Lzero(p, nb) == 0
|
||||
}
|
||||
|
||||
func isZeroSafe(p unsafe.Pointer, vt *rt.GoType) bool {
|
||||
if isZeroMem(p, vt.Size()) {
|
||||
if native.Lzero(p, vt.Size()) == 0 {
|
||||
return true
|
||||
} else {
|
||||
return isZeroTyped(p, vt)
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -3,9 +3,10 @@ module github.com/bytedance/sonic
|
|||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20210528150155-e775e1ff0f56
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20210528162528-3c6c11c43ee5
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/json-iterator/go v1.1.10
|
||||
github.com/klauspost/cpuid/v2 v2.0.6
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/gjson v1.8.0
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -1,11 +1,13 @@
|
|||
github.com/chenzhuoyu/base64x v0.0.0-20210528150155-e775e1ff0f56 h1:dwu5dS6rUvkgozhG4LYv4PPs8wu7T9L6D7A2Y1nwHwo=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20210528150155-e775e1ff0f56/go.mod h1:NfDzX8KeqVNX62apij1OkqoeDdq1VR3g0TRZo99kkBA=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20210528162528-3c6c11c43ee5 h1:7AStn2tanqGY99xzW+Ve1p6YYqnRr1m/yswJ4h0BhcY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20210528162528-3c6c11c43ee5/go.mod h1:NfDzX8KeqVNX62apij1OkqoeDdq1VR3g0TRZo99kkBA=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
|
|
|
|||
38
internal/cpu/features.go
Normal file
38
internal/cpu/features.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 cpu
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`os`
|
||||
|
||||
`github.com/klauspost/cpuid/v2`
|
||||
)
|
||||
|
||||
var (
|
||||
HasAVX = cpuid.CPU.Has(cpuid.AVX)
|
||||
HasAVX2 = cpuid.CPU.Has(cpuid.AVX2)
|
||||
)
|
||||
|
||||
func init() {
|
||||
switch v := os.Getenv("SONIC_MODE"); v {
|
||||
case "" : break
|
||||
case "auto" : break
|
||||
case "noavx2" : HasAVX2 = false
|
||||
default : panic(fmt.Sprintf("invalid mode: '%s', should be one of 'auto', 'noavx2'", v))
|
||||
}
|
||||
}
|
||||
|
|
@ -182,7 +182,9 @@ func (self *BaseAssembler) assignOperands(p *obj.Prog, args []obj.Addr) {
|
|||
case 0 :
|
||||
case 1 : p.To = args[0]
|
||||
case 2 : p.To, p.From = args[1], args[0]
|
||||
default : p.To, p.From, p.RestArgs = args[1], args[0], args[2:]
|
||||
case 3 : p.To, p.From, p.RestArgs = args[2], args[0], args[1:2]
|
||||
case 4 : p.To, p.From, p.RestArgs = args[2], args[3], args[:2]
|
||||
default : panic("invalid operands")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
34
internal/jit/backend_test.go
Normal file
34
internal/jit/backend_test.go
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 jit
|
||||
|
||||
import (
|
||||
`testing`
|
||||
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/twitchyliquid64/golang-asm/obj`
|
||||
`github.com/twitchyliquid64/golang-asm/obj/x86`
|
||||
)
|
||||
|
||||
func TestBackend(t *testing.T) {
|
||||
e := newBackend("amd64")
|
||||
p := e.New()
|
||||
p.As = x86.AVPTEST
|
||||
(*BaseAssembler)(nil).assignOperands(p, []obj.Addr{Reg("Y2"), Reg("Y1")})
|
||||
e.Append(p)
|
||||
spew.Dump(e.Assemble())
|
||||
}
|
||||
66
internal/native/avx/fastfloat_amd64_test.go
Normal file
66
internal/native/avx/fastfloat_amd64_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx
|
||||
|
||||
import (
|
||||
`math`
|
||||
`strconv`
|
||||
`testing`
|
||||
|
||||
`github.com/stretchr/testify/assert`
|
||||
)
|
||||
|
||||
func TestFastFloat_Encode(t *testing.T) {
|
||||
var buf [64]byte
|
||||
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
|
||||
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
|
||||
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
|
||||
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
|
||||
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
|
||||
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
|
||||
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
|
||||
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
|
||||
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
|
||||
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
|
||||
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
|
||||
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
|
||||
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
|
||||
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
|
||||
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
|
||||
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
|
||||
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
|
||||
}
|
||||
|
||||
func BenchmarkFastFloat_Encode(b *testing.B) {
|
||||
val := -2.2250738585072014e-308
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib",
|
||||
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
|
||||
}, {
|
||||
name: "FastFloat",
|
||||
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
135
internal/native/avx/fastint_amd64_test.go
Normal file
135
internal/native/avx/fastint_amd64_test.go
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
`testing`
|
||||
|
||||
`github.com/stretchr/testify/assert`
|
||||
)
|
||||
|
||||
func TestFastInt_IntToString(t *testing.T) {
|
||||
var buf [32]byte
|
||||
assert.Equal(t, "0" , string(buf[:__i64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "1" , string(buf[:__i64toa(&buf[0], 1)]))
|
||||
assert.Equal(t, "12" , string(buf[:__i64toa(&buf[0], 12)]))
|
||||
assert.Equal(t, "123" , string(buf[:__i64toa(&buf[0], 123)]))
|
||||
assert.Equal(t, "1234" , string(buf[:__i64toa(&buf[0], 1234)]))
|
||||
assert.Equal(t, "12345" , string(buf[:__i64toa(&buf[0], 12345)]))
|
||||
assert.Equal(t, "123456" , string(buf[:__i64toa(&buf[0], 123456)]))
|
||||
assert.Equal(t, "1234567" , string(buf[:__i64toa(&buf[0], 1234567)]))
|
||||
assert.Equal(t, "12345678" , string(buf[:__i64toa(&buf[0], 12345678)]))
|
||||
assert.Equal(t, "123456789" , string(buf[:__i64toa(&buf[0], 123456789)]))
|
||||
assert.Equal(t, "1234567890" , string(buf[:__i64toa(&buf[0], 1234567890)]))
|
||||
assert.Equal(t, "12345678901" , string(buf[:__i64toa(&buf[0], 12345678901)]))
|
||||
assert.Equal(t, "123456789012" , string(buf[:__i64toa(&buf[0], 123456789012)]))
|
||||
assert.Equal(t, "1234567890123" , string(buf[:__i64toa(&buf[0], 1234567890123)]))
|
||||
assert.Equal(t, "12345678901234" , string(buf[:__i64toa(&buf[0], 12345678901234)]))
|
||||
assert.Equal(t, "123456789012345" , string(buf[:__i64toa(&buf[0], 123456789012345)]))
|
||||
assert.Equal(t, "1234567890123456" , string(buf[:__i64toa(&buf[0], 1234567890123456)]))
|
||||
assert.Equal(t, "12345678901234567" , string(buf[:__i64toa(&buf[0], 12345678901234567)]))
|
||||
assert.Equal(t, "123456789012345678" , string(buf[:__i64toa(&buf[0], 123456789012345678)]))
|
||||
assert.Equal(t, "1234567890123456789" , string(buf[:__i64toa(&buf[0], 1234567890123456789)]))
|
||||
assert.Equal(t, "9223372036854775807" , string(buf[:__i64toa(&buf[0], 9223372036854775807)]))
|
||||
assert.Equal(t, "-1" , string(buf[:__i64toa(&buf[0], -1)]))
|
||||
assert.Equal(t, "-12" , string(buf[:__i64toa(&buf[0], -12)]))
|
||||
assert.Equal(t, "-123" , string(buf[:__i64toa(&buf[0], -123)]))
|
||||
assert.Equal(t, "-1234" , string(buf[:__i64toa(&buf[0], -1234)]))
|
||||
assert.Equal(t, "-12345" , string(buf[:__i64toa(&buf[0], -12345)]))
|
||||
assert.Equal(t, "-123456" , string(buf[:__i64toa(&buf[0], -123456)]))
|
||||
assert.Equal(t, "-1234567" , string(buf[:__i64toa(&buf[0], -1234567)]))
|
||||
assert.Equal(t, "-12345678" , string(buf[:__i64toa(&buf[0], -12345678)]))
|
||||
assert.Equal(t, "-123456789" , string(buf[:__i64toa(&buf[0], -123456789)]))
|
||||
assert.Equal(t, "-1234567890" , string(buf[:__i64toa(&buf[0], -1234567890)]))
|
||||
assert.Equal(t, "-12345678901" , string(buf[:__i64toa(&buf[0], -12345678901)]))
|
||||
assert.Equal(t, "-123456789012" , string(buf[:__i64toa(&buf[0], -123456789012)]))
|
||||
assert.Equal(t, "-1234567890123" , string(buf[:__i64toa(&buf[0], -1234567890123)]))
|
||||
assert.Equal(t, "-12345678901234" , string(buf[:__i64toa(&buf[0], -12345678901234)]))
|
||||
assert.Equal(t, "-123456789012345" , string(buf[:__i64toa(&buf[0], -123456789012345)]))
|
||||
assert.Equal(t, "-1234567890123456" , string(buf[:__i64toa(&buf[0], -1234567890123456)]))
|
||||
assert.Equal(t, "-12345678901234567" , string(buf[:__i64toa(&buf[0], -12345678901234567)]))
|
||||
assert.Equal(t, "-123456789012345678" , string(buf[:__i64toa(&buf[0], -123456789012345678)]))
|
||||
assert.Equal(t, "-1234567890123456789" , string(buf[:__i64toa(&buf[0], -1234567890123456789)]))
|
||||
assert.Equal(t, "-9223372036854775808" , string(buf[:__i64toa(&buf[0], -9223372036854775808)]))
|
||||
}
|
||||
|
||||
func TestFastInt_UintToString(t *testing.T) {
|
||||
var buf [32]byte
|
||||
assert.Equal(t, "0" , string(buf[:__u64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "1" , string(buf[:__u64toa(&buf[0], 1)]))
|
||||
assert.Equal(t, "12" , string(buf[:__u64toa(&buf[0], 12)]))
|
||||
assert.Equal(t, "123" , string(buf[:__u64toa(&buf[0], 123)]))
|
||||
assert.Equal(t, "1234" , string(buf[:__u64toa(&buf[0], 1234)]))
|
||||
assert.Equal(t, "12345" , string(buf[:__u64toa(&buf[0], 12345)]))
|
||||
assert.Equal(t, "123456" , string(buf[:__u64toa(&buf[0], 123456)]))
|
||||
assert.Equal(t, "1234567" , string(buf[:__u64toa(&buf[0], 1234567)]))
|
||||
assert.Equal(t, "12345678" , string(buf[:__u64toa(&buf[0], 12345678)]))
|
||||
assert.Equal(t, "123456789" , string(buf[:__u64toa(&buf[0], 123456789)]))
|
||||
assert.Equal(t, "1234567890" , string(buf[:__u64toa(&buf[0], 1234567890)]))
|
||||
assert.Equal(t, "12345678901" , string(buf[:__u64toa(&buf[0], 12345678901)]))
|
||||
assert.Equal(t, "123456789012" , string(buf[:__u64toa(&buf[0], 123456789012)]))
|
||||
assert.Equal(t, "1234567890123" , string(buf[:__u64toa(&buf[0], 1234567890123)]))
|
||||
assert.Equal(t, "12345678901234" , string(buf[:__u64toa(&buf[0], 12345678901234)]))
|
||||
assert.Equal(t, "123456789012345" , string(buf[:__u64toa(&buf[0], 123456789012345)]))
|
||||
assert.Equal(t, "1234567890123456" , string(buf[:__u64toa(&buf[0], 1234567890123456)]))
|
||||
assert.Equal(t, "12345678901234567" , string(buf[:__u64toa(&buf[0], 12345678901234567)]))
|
||||
assert.Equal(t, "123456789012345678" , string(buf[:__u64toa(&buf[0], 123456789012345678)]))
|
||||
assert.Equal(t, "1234567890123456789" , string(buf[:__u64toa(&buf[0], 1234567890123456789)]))
|
||||
assert.Equal(t, "12345678901234567890" , string(buf[:__u64toa(&buf[0], 12345678901234567890)]))
|
||||
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
|
||||
}
|
||||
|
||||
func BenchmarkFastInt_IntToString(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib-Positive",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
|
||||
}, {
|
||||
name: "StdLib-Negative",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
|
||||
}, {
|
||||
name: "FastInt-Positive",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
|
||||
}, {
|
||||
name: "FastInt-Negative",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFastInt_UintToString(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
|
||||
}, {
|
||||
name: "FastInt",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
100
internal/native/avx/native_amd64.go
Normal file
100
internal/native/avx/native_amd64.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __i64toa(out *byte, val int64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __u64toa(out *byte, val uint64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __f64toa(out *byte, val float64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lzero(p unsafe.Pointer, n int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lquote(buf *string, off int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vstring(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vnumber(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vunsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_one(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_array(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_object(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
|
||||
6246
internal/native/avx/native_amd64.s
Normal file
6246
internal/native/avx/native_amd64.s
Normal file
File diff suppressed because it is too large
Load diff
426
internal/native/avx/native_amd64_test.go
Normal file
426
internal/native/avx/native_amd64_test.go
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx
|
||||
|
||||
import (
|
||||
`encoding/hex`
|
||||
`fmt`
|
||||
`math`
|
||||
`testing`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/assert`
|
||||
`github.com/stretchr/testify/require`
|
||||
)
|
||||
|
||||
func TestNative_Value(t *testing.T) {
|
||||
var v types.JsonState
|
||||
s := ` -12345`
|
||||
p := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
x := __value(p.Ptr, p.Len, 0, &v)
|
||||
assert.Equal(t, 9, x)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
assert.Equal(t, int64(-12345), v.Iv)
|
||||
assert.Equal(t, 3, v.Ep)
|
||||
}
|
||||
|
||||
func TestNative_Unquote(t *testing.T) {
|
||||
s := `hello\b\f\n\r\t\\\"\u2333world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\b\f\n\r\t\\\"\u2333world", string(d))
|
||||
}
|
||||
|
||||
func TestNative_UnquoteError(t *testing.T) {
|
||||
s := `asdf\`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_EOF), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\gqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_ESCAPE), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\u1gggqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_CHAR), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 6, ep)
|
||||
s = `asdf\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 12, ep)
|
||||
s = `asdf\\ud800\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 14, ep)
|
||||
}
|
||||
|
||||
func TestNative_DoubleUnquote(t *testing.T) {
|
||||
s := `hello\\b\\f\\n\\r\\t\\\\\\\"\\u2333world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\b\f\n\r\t\\\"\u2333world", string(d))
|
||||
}
|
||||
|
||||
func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
|
||||
s := `hello\ud800world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\ufffdworld", string(d))
|
||||
s = `hello\ud800\ud800world`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\ufffd\ufffdworld", string(d))
|
||||
}
|
||||
|
||||
func TestNative_Vstring(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := `test"test\n2"`
|
||||
__vstring(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, -1, v.Ep)
|
||||
assert.Equal(t, int64(0), v.Iv)
|
||||
__vstring(&s, &i, &v)
|
||||
assert.Equal(t, 13, i)
|
||||
assert.Equal(t, 9, v.Ep)
|
||||
assert.Equal(t, int64(5), v.Iv)
|
||||
}
|
||||
|
||||
func TestNative_VstringHangUpOnRandomData(t *testing.T) {
|
||||
v, e := hex.DecodeString(
|
||||
"228dc61efd54ef80a908fb6026b7f2d5f92a257ba8b347c995f259eb8685376a" +
|
||||
"8c4500262d9c308b3f3ec2577689cf345d9f86f9b5d18d3e463bec5c22df2d2e" +
|
||||
"4506010eba1dae7278",
|
||||
)
|
||||
assert.Nil(t, e)
|
||||
p := 1
|
||||
s := rt.Mem2Str(v)
|
||||
var js types.JsonState
|
||||
__vstring(&s, &p, &js)
|
||||
fmt.Printf("js: %s\n", spew.Sdump(js))
|
||||
}
|
||||
|
||||
func TestNative_Vnumber(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "1.234e5"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 7, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234e5, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 0.0125, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "100000000000000000000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 100000000000000000000.0, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "999999999999999900000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 999999999999999900000.0, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "-1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, -1.234, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vsigned(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(-1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775807"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MaxInt64), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MinInt64), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 18, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775809"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e-5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vunsigned(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551615"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ^int64(0), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551616"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e-5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_SkipOne(t *testing.T) {
|
||||
p := 0
|
||||
s := ` {"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
|
||||
q := __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 42, p)
|
||||
assert.Equal(t, 1, q)
|
||||
p = 0
|
||||
s = `1 2.5 -3 "asdf\nqwer" true false null {} []`
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 1, p)
|
||||
assert.Equal(t, 0, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 5, p)
|
||||
assert.Equal(t, 2, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 8, p)
|
||||
assert.Equal(t, 6, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 21, p)
|
||||
assert.Equal(t, 9, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 26, p)
|
||||
assert.Equal(t, 22, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 32, p)
|
||||
assert.Equal(t, 27, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 37, p)
|
||||
assert.Equal(t, 33, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 40, p)
|
||||
assert.Equal(t, 38, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 43, p)
|
||||
assert.Equal(t, 41, q)
|
||||
}
|
||||
|
||||
func TestNative_SkipArray(t *testing.T) {
|
||||
p := 0
|
||||
s := `null, true, false, 1, 2.0, -3, {"asdf": "wqer"}],`
|
||||
__skip_array(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 48)
|
||||
}
|
||||
|
||||
func TestNative_SkipObject(t *testing.T) {
|
||||
p := 0
|
||||
s := `"asdf": "wqer"},`
|
||||
__skip_object(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 15)
|
||||
}
|
||||
45
internal/native/avx/native_export_amd64.go
Normal file
45
internal/native/avx/native_export_amd64.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx
|
||||
|
||||
var (
|
||||
S_f64toa = _subr__f64toa
|
||||
S_i64toa = _subr__i64toa
|
||||
S_lquote = _subr__lquote
|
||||
S_u64toa = _subr__u64toa
|
||||
)
|
||||
|
||||
var (
|
||||
S_lspace = _subr__lspace
|
||||
S_unquote = _subr__unquote
|
||||
)
|
||||
|
||||
var (
|
||||
S_value = _subr__value
|
||||
S_vstring = _subr__vstring
|
||||
S_vnumber = _subr__vnumber
|
||||
S_vsigned = _subr__vsigned
|
||||
S_vunsigned = _subr__vunsigned
|
||||
)
|
||||
|
||||
var (
|
||||
S_skip_one = _subr__skip_one
|
||||
S_skip_array = _subr__skip_array
|
||||
S_skip_object = _subr__skip_object
|
||||
)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// +build !noasm !appengine
|
||||
// Code generated by asm2asm, DO NOT EDIT.
|
||||
|
||||
package native
|
||||
package avx
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
|
@ -14,21 +14,21 @@ func ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___()
|
|||
|
||||
var (
|
||||
_func__base = ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___
|
||||
_subr__f64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 2953
|
||||
_subr__i64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 6042
|
||||
_subr__lquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 384
|
||||
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 1266
|
||||
_subr__f64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 2480
|
||||
_subr__i64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5544
|
||||
_subr__lquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 295
|
||||
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 937
|
||||
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14398
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14433
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12845
|
||||
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 6135
|
||||
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 7356
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9076
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11325
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12295
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 10096
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12572
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13958
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13993
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12328
|
||||
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5637
|
||||
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 6825
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 8460
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 10806
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11778
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9464
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12055
|
||||
)
|
||||
|
||||
var (
|
||||
66
internal/native/avx2/fastfloat_amd64_test.go
Normal file
66
internal/native/avx2/fastfloat_amd64_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx2
|
||||
|
||||
import (
|
||||
`math`
|
||||
`strconv`
|
||||
`testing`
|
||||
|
||||
`github.com/stretchr/testify/assert`
|
||||
)
|
||||
|
||||
func TestFastFloat_Encode(t *testing.T) {
|
||||
var buf [64]byte
|
||||
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
|
||||
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
|
||||
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
|
||||
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
|
||||
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
|
||||
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
|
||||
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
|
||||
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
|
||||
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
|
||||
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
|
||||
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
|
||||
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
|
||||
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
|
||||
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
|
||||
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
|
||||
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
|
||||
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
|
||||
}
|
||||
|
||||
func BenchmarkFastFloat_Encode(b *testing.B) {
|
||||
val := -2.2250738585072014e-308
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib",
|
||||
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
|
||||
}, {
|
||||
name: "FastFloat",
|
||||
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
135
internal/native/avx2/fastint_amd64_test.go
Normal file
135
internal/native/avx2/fastint_amd64_test.go
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx2
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
`testing`
|
||||
|
||||
`github.com/stretchr/testify/assert`
|
||||
)
|
||||
|
||||
func TestFastInt_IntToString(t *testing.T) {
|
||||
var buf [32]byte
|
||||
assert.Equal(t, "0" , string(buf[:__i64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "1" , string(buf[:__i64toa(&buf[0], 1)]))
|
||||
assert.Equal(t, "12" , string(buf[:__i64toa(&buf[0], 12)]))
|
||||
assert.Equal(t, "123" , string(buf[:__i64toa(&buf[0], 123)]))
|
||||
assert.Equal(t, "1234" , string(buf[:__i64toa(&buf[0], 1234)]))
|
||||
assert.Equal(t, "12345" , string(buf[:__i64toa(&buf[0], 12345)]))
|
||||
assert.Equal(t, "123456" , string(buf[:__i64toa(&buf[0], 123456)]))
|
||||
assert.Equal(t, "1234567" , string(buf[:__i64toa(&buf[0], 1234567)]))
|
||||
assert.Equal(t, "12345678" , string(buf[:__i64toa(&buf[0], 12345678)]))
|
||||
assert.Equal(t, "123456789" , string(buf[:__i64toa(&buf[0], 123456789)]))
|
||||
assert.Equal(t, "1234567890" , string(buf[:__i64toa(&buf[0], 1234567890)]))
|
||||
assert.Equal(t, "12345678901" , string(buf[:__i64toa(&buf[0], 12345678901)]))
|
||||
assert.Equal(t, "123456789012" , string(buf[:__i64toa(&buf[0], 123456789012)]))
|
||||
assert.Equal(t, "1234567890123" , string(buf[:__i64toa(&buf[0], 1234567890123)]))
|
||||
assert.Equal(t, "12345678901234" , string(buf[:__i64toa(&buf[0], 12345678901234)]))
|
||||
assert.Equal(t, "123456789012345" , string(buf[:__i64toa(&buf[0], 123456789012345)]))
|
||||
assert.Equal(t, "1234567890123456" , string(buf[:__i64toa(&buf[0], 1234567890123456)]))
|
||||
assert.Equal(t, "12345678901234567" , string(buf[:__i64toa(&buf[0], 12345678901234567)]))
|
||||
assert.Equal(t, "123456789012345678" , string(buf[:__i64toa(&buf[0], 123456789012345678)]))
|
||||
assert.Equal(t, "1234567890123456789" , string(buf[:__i64toa(&buf[0], 1234567890123456789)]))
|
||||
assert.Equal(t, "9223372036854775807" , string(buf[:__i64toa(&buf[0], 9223372036854775807)]))
|
||||
assert.Equal(t, "-1" , string(buf[:__i64toa(&buf[0], -1)]))
|
||||
assert.Equal(t, "-12" , string(buf[:__i64toa(&buf[0], -12)]))
|
||||
assert.Equal(t, "-123" , string(buf[:__i64toa(&buf[0], -123)]))
|
||||
assert.Equal(t, "-1234" , string(buf[:__i64toa(&buf[0], -1234)]))
|
||||
assert.Equal(t, "-12345" , string(buf[:__i64toa(&buf[0], -12345)]))
|
||||
assert.Equal(t, "-123456" , string(buf[:__i64toa(&buf[0], -123456)]))
|
||||
assert.Equal(t, "-1234567" , string(buf[:__i64toa(&buf[0], -1234567)]))
|
||||
assert.Equal(t, "-12345678" , string(buf[:__i64toa(&buf[0], -12345678)]))
|
||||
assert.Equal(t, "-123456789" , string(buf[:__i64toa(&buf[0], -123456789)]))
|
||||
assert.Equal(t, "-1234567890" , string(buf[:__i64toa(&buf[0], -1234567890)]))
|
||||
assert.Equal(t, "-12345678901" , string(buf[:__i64toa(&buf[0], -12345678901)]))
|
||||
assert.Equal(t, "-123456789012" , string(buf[:__i64toa(&buf[0], -123456789012)]))
|
||||
assert.Equal(t, "-1234567890123" , string(buf[:__i64toa(&buf[0], -1234567890123)]))
|
||||
assert.Equal(t, "-12345678901234" , string(buf[:__i64toa(&buf[0], -12345678901234)]))
|
||||
assert.Equal(t, "-123456789012345" , string(buf[:__i64toa(&buf[0], -123456789012345)]))
|
||||
assert.Equal(t, "-1234567890123456" , string(buf[:__i64toa(&buf[0], -1234567890123456)]))
|
||||
assert.Equal(t, "-12345678901234567" , string(buf[:__i64toa(&buf[0], -12345678901234567)]))
|
||||
assert.Equal(t, "-123456789012345678" , string(buf[:__i64toa(&buf[0], -123456789012345678)]))
|
||||
assert.Equal(t, "-1234567890123456789" , string(buf[:__i64toa(&buf[0], -1234567890123456789)]))
|
||||
assert.Equal(t, "-9223372036854775808" , string(buf[:__i64toa(&buf[0], -9223372036854775808)]))
|
||||
}
|
||||
|
||||
func TestFastInt_UintToString(t *testing.T) {
|
||||
var buf [32]byte
|
||||
assert.Equal(t, "0" , string(buf[:__u64toa(&buf[0], 0)]))
|
||||
assert.Equal(t, "1" , string(buf[:__u64toa(&buf[0], 1)]))
|
||||
assert.Equal(t, "12" , string(buf[:__u64toa(&buf[0], 12)]))
|
||||
assert.Equal(t, "123" , string(buf[:__u64toa(&buf[0], 123)]))
|
||||
assert.Equal(t, "1234" , string(buf[:__u64toa(&buf[0], 1234)]))
|
||||
assert.Equal(t, "12345" , string(buf[:__u64toa(&buf[0], 12345)]))
|
||||
assert.Equal(t, "123456" , string(buf[:__u64toa(&buf[0], 123456)]))
|
||||
assert.Equal(t, "1234567" , string(buf[:__u64toa(&buf[0], 1234567)]))
|
||||
assert.Equal(t, "12345678" , string(buf[:__u64toa(&buf[0], 12345678)]))
|
||||
assert.Equal(t, "123456789" , string(buf[:__u64toa(&buf[0], 123456789)]))
|
||||
assert.Equal(t, "1234567890" , string(buf[:__u64toa(&buf[0], 1234567890)]))
|
||||
assert.Equal(t, "12345678901" , string(buf[:__u64toa(&buf[0], 12345678901)]))
|
||||
assert.Equal(t, "123456789012" , string(buf[:__u64toa(&buf[0], 123456789012)]))
|
||||
assert.Equal(t, "1234567890123" , string(buf[:__u64toa(&buf[0], 1234567890123)]))
|
||||
assert.Equal(t, "12345678901234" , string(buf[:__u64toa(&buf[0], 12345678901234)]))
|
||||
assert.Equal(t, "123456789012345" , string(buf[:__u64toa(&buf[0], 123456789012345)]))
|
||||
assert.Equal(t, "1234567890123456" , string(buf[:__u64toa(&buf[0], 1234567890123456)]))
|
||||
assert.Equal(t, "12345678901234567" , string(buf[:__u64toa(&buf[0], 12345678901234567)]))
|
||||
assert.Equal(t, "123456789012345678" , string(buf[:__u64toa(&buf[0], 123456789012345678)]))
|
||||
assert.Equal(t, "1234567890123456789" , string(buf[:__u64toa(&buf[0], 1234567890123456789)]))
|
||||
assert.Equal(t, "12345678901234567890" , string(buf[:__u64toa(&buf[0], 12345678901234567890)]))
|
||||
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
|
||||
}
|
||||
|
||||
func BenchmarkFastInt_IntToString(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib-Positive",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
|
||||
}, {
|
||||
name: "StdLib-Negative",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
|
||||
}, {
|
||||
name: "FastInt-Positive",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
|
||||
}, {
|
||||
name: "FastInt-Negative",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFastInt_UintToString(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
test func(*testing.B)
|
||||
}{{
|
||||
name: "StdLib",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
|
||||
}, {
|
||||
name: "FastInt",
|
||||
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
|
||||
}}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, bm.test)
|
||||
}
|
||||
}
|
||||
100
internal/native/avx2/native_amd64.go
Normal file
100
internal/native/avx2/native_amd64.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx2
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __i64toa(out *byte, val int64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __u64toa(out *byte, val uint64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __f64toa(out *byte, val float64) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lzero(p unsafe.Pointer, n int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lquote(buf *string, off int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vstring(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vnumber(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vunsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_one(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_array(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_object(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) (ret int)
|
||||
File diff suppressed because it is too large
Load diff
426
internal/native/avx2/native_amd64_test.go
Normal file
426
internal/native/avx2/native_amd64_test.go
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx2
|
||||
|
||||
import (
|
||||
`encoding/hex`
|
||||
`fmt`
|
||||
`math`
|
||||
`testing`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/assert`
|
||||
`github.com/stretchr/testify/require`
|
||||
)
|
||||
|
||||
func TestNative_Value(t *testing.T) {
|
||||
var v types.JsonState
|
||||
s := ` -12345`
|
||||
p := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
x := __value(p.Ptr, p.Len, 0, &v)
|
||||
assert.Equal(t, 9, x)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
assert.Equal(t, int64(-12345), v.Iv)
|
||||
assert.Equal(t, 3, v.Ep)
|
||||
}
|
||||
|
||||
func TestNative_Unquote(t *testing.T) {
|
||||
s := `hello\b\f\n\r\t\\\"\u2333world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\b\f\n\r\t\\\"\u2333world", string(d))
|
||||
}
|
||||
|
||||
func TestNative_UnquoteError(t *testing.T) {
|
||||
s := `asdf\`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_EOF), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\gqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_ESCAPE), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\u1gggqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_CHAR), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 6, ep)
|
||||
s = `asdf\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 12, ep)
|
||||
s = `asdf\\ud800\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 14, ep)
|
||||
}
|
||||
|
||||
func TestNative_DoubleUnquote(t *testing.T) {
|
||||
s := `hello\\b\\f\\n\\r\\t\\\\\\\"\\u2333world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\b\f\n\r\t\\\"\u2333world", string(d))
|
||||
}
|
||||
|
||||
func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
|
||||
s := `hello\ud800world`
|
||||
d := make([]byte, 0, len(s))
|
||||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\ufffdworld", string(d))
|
||||
s = `hello\ud800\ud800world`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
assert.Equal(t, "hello\ufffd\ufffdworld", string(d))
|
||||
}
|
||||
|
||||
func TestNative_Vstring(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := `test"test\n2"`
|
||||
__vstring(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, -1, v.Ep)
|
||||
assert.Equal(t, int64(0), v.Iv)
|
||||
__vstring(&s, &i, &v)
|
||||
assert.Equal(t, 13, i)
|
||||
assert.Equal(t, 9, v.Ep)
|
||||
assert.Equal(t, int64(5), v.Iv)
|
||||
}
|
||||
|
||||
func TestNative_VstringHangUpOnRandomData(t *testing.T) {
|
||||
v, e := hex.DecodeString(
|
||||
"228dc61efd54ef80a908fb6026b7f2d5f92a257ba8b347c995f259eb8685376a" +
|
||||
"8c4500262d9c308b3f3ec2577689cf345d9f86f9b5d18d3e463bec5c22df2d2e" +
|
||||
"4506010eba1dae7278",
|
||||
)
|
||||
assert.Nil(t, e)
|
||||
p := 1
|
||||
s := rt.Mem2Str(v)
|
||||
var js types.JsonState
|
||||
__vstring(&s, &p, &js)
|
||||
fmt.Printf("js: %s\n", spew.Sdump(js))
|
||||
}
|
||||
|
||||
func TestNative_Vnumber(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "1.234e5"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 7, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234e5, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 0.0125, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "100000000000000000000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 100000000000000000000.0, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "999999999999999900000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 999999999999999900000.0, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "-1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, -1.234, v.Dv)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vsigned(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(-1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775807"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MaxInt64), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MinInt64), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 18, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775809"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e-5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vunsigned(t *testing.T) {
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551615"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ^int64(0), v.Iv)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551616"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e-5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_SkipOne(t *testing.T) {
|
||||
p := 0
|
||||
s := ` {"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
|
||||
q := __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 42, p)
|
||||
assert.Equal(t, 1, q)
|
||||
p = 0
|
||||
s = `1 2.5 -3 "asdf\nqwer" true false null {} []`
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 1, p)
|
||||
assert.Equal(t, 0, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 5, p)
|
||||
assert.Equal(t, 2, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 8, p)
|
||||
assert.Equal(t, 6, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 21, p)
|
||||
assert.Equal(t, 9, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 26, p)
|
||||
assert.Equal(t, 22, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 32, p)
|
||||
assert.Equal(t, 27, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 37, p)
|
||||
assert.Equal(t, 33, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 40, p)
|
||||
assert.Equal(t, 38, q)
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 43, p)
|
||||
assert.Equal(t, 41, q)
|
||||
}
|
||||
|
||||
func TestNative_SkipArray(t *testing.T) {
|
||||
p := 0
|
||||
s := `null, true, false, 1, 2.0, -3, {"asdf": "wqer"}],`
|
||||
__skip_array(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 48)
|
||||
}
|
||||
|
||||
func TestNative_SkipObject(t *testing.T) {
|
||||
p := 0
|
||||
s := `"asdf": "wqer"},`
|
||||
__skip_object(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 15)
|
||||
}
|
||||
45
internal/native/avx2/native_export_amd64.go
Normal file
45
internal/native/avx2/native_export_amd64.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Code generated by Makefile, DO NOT EDIT.
|
||||
|
||||
/*
|
||||
* 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 avx2
|
||||
|
||||
var (
|
||||
S_f64toa = _subr__f64toa
|
||||
S_i64toa = _subr__i64toa
|
||||
S_lquote = _subr__lquote
|
||||
S_u64toa = _subr__u64toa
|
||||
)
|
||||
|
||||
var (
|
||||
S_lspace = _subr__lspace
|
||||
S_unquote = _subr__unquote
|
||||
)
|
||||
|
||||
var (
|
||||
S_value = _subr__value
|
||||
S_vstring = _subr__vstring
|
||||
S_vnumber = _subr__vnumber
|
||||
S_vsigned = _subr__vsigned
|
||||
S_vunsigned = _subr__vunsigned
|
||||
)
|
||||
|
||||
var (
|
||||
S_skip_one = _subr__skip_one
|
||||
S_skip_array = _subr__skip_array
|
||||
S_skip_object = _subr__skip_object
|
||||
)
|
||||
50
internal/native/avx2/native_subr_amd64.go
Normal file
50
internal/native/avx2/native_subr_amd64.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// +build !noasm !appengine
|
||||
// Code generated by asm2asm, DO NOT EDIT.
|
||||
|
||||
package avx2
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection ALL
|
||||
func ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___()
|
||||
|
||||
var (
|
||||
_func__base = ___asm2asm_compiled_code__DO_NOT_CALL_THIS_SYMBOL___
|
||||
_subr__f64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3038
|
||||
_subr__i64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 6102
|
||||
_subr__lquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 376
|
||||
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 1268
|
||||
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14619
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14654
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13066
|
||||
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 6195
|
||||
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 7419
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9196
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11544
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12516
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 10216
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12793
|
||||
)
|
||||
|
||||
var (
|
||||
_ = _subr__f64toa
|
||||
_ = _subr__i64toa
|
||||
_ = _subr__lquote
|
||||
_ = _subr__lspace
|
||||
_ = _subr__lzero
|
||||
_ = _subr__skip_array
|
||||
_ = _subr__skip_object
|
||||
_ = _subr__skip_one
|
||||
_ = _subr__u64toa
|
||||
_ = _subr__unquote
|
||||
_ = _subr__value
|
||||
_ = _subr__vnumber
|
||||
_ = _subr__vsigned
|
||||
_ = _subr__vstring
|
||||
_ = _subr__vunsigned
|
||||
)
|
||||
123
internal/native/dispatch_amd64.go
Normal file
123
internal/native/dispatch_amd64.go
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 native
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/cpu`
|
||||
`github.com/bytedance/sonic/internal/native/avx`
|
||||
`github.com/bytedance/sonic/internal/native/avx2`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
var (
|
||||
S_f64toa uintptr
|
||||
S_i64toa uintptr
|
||||
S_u64toa uintptr
|
||||
S_lquote uintptr
|
||||
S_lspace uintptr
|
||||
S_unquote uintptr
|
||||
)
|
||||
|
||||
var (
|
||||
S_value uintptr
|
||||
S_vstring uintptr
|
||||
S_vnumber uintptr
|
||||
S_vsigned uintptr
|
||||
S_vunsigned uintptr
|
||||
)
|
||||
|
||||
var (
|
||||
S_skip_one uintptr
|
||||
S_skip_array uintptr
|
||||
S_skip_object uintptr
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func Lzero(p unsafe.Pointer, n int) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func Lquote(buf *string, off int) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func Lspace(sp unsafe.Pointer, nb int, off int) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func Value(s unsafe.Pointer, n int, p int, v *types.JsonState) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func SkipOne(s *string, p *int, m *types.StateMachine) int
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func Unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) int
|
||||
|
||||
func useAVX() {
|
||||
S_f64toa = avx.S_f64toa
|
||||
S_i64toa = avx.S_i64toa
|
||||
S_u64toa = avx.S_u64toa
|
||||
S_lquote = avx.S_lquote
|
||||
S_lspace = avx.S_lspace
|
||||
S_unquote = avx.S_unquote
|
||||
S_value = avx.S_value
|
||||
S_vstring = avx.S_vstring
|
||||
S_vnumber = avx.S_vnumber
|
||||
S_vsigned = avx.S_vsigned
|
||||
S_vunsigned = avx.S_vunsigned
|
||||
S_skip_one = avx.S_skip_one
|
||||
S_skip_array = avx.S_skip_array
|
||||
S_skip_object = avx.S_skip_object
|
||||
}
|
||||
|
||||
func useAVX2() {
|
||||
S_f64toa = avx2.S_f64toa
|
||||
S_i64toa = avx2.S_i64toa
|
||||
S_u64toa = avx2.S_u64toa
|
||||
S_lquote = avx2.S_lquote
|
||||
S_lspace = avx2.S_lspace
|
||||
S_unquote = avx2.S_unquote
|
||||
S_value = avx2.S_value
|
||||
S_vstring = avx2.S_vstring
|
||||
S_vnumber = avx2.S_vnumber
|
||||
S_vsigned = avx2.S_vsigned
|
||||
S_vunsigned = avx2.S_vunsigned
|
||||
S_skip_one = avx2.S_skip_one
|
||||
S_skip_array = avx2.S_skip_array
|
||||
S_skip_object = avx2.S_skip_object
|
||||
}
|
||||
|
||||
func init() {
|
||||
if cpu.HasAVX2 {
|
||||
useAVX2()
|
||||
} else if cpu.HasAVX {
|
||||
useAVX()
|
||||
} else {
|
||||
panic("Unsupported CPU, maybe it's too old to run Sonic.")
|
||||
}
|
||||
}
|
||||
55
internal/native/dispatch_amd64.s
Normal file
55
internal/native/dispatch_amd64.s
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// 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 ·Lzero(SB), NOSPLIT, $0 - 24
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__lzero(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__lzero(SB)
|
||||
|
||||
TEXT ·Lquote(SB), NOSPLIT, $0 - 24
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__lquote(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__lquote(SB)
|
||||
|
||||
TEXT ·Lspace(SB), NOSPLIT, $0 - 32
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__lspace(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__lspace(SB)
|
||||
|
||||
TEXT ·Value(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·__value(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__value(SB)
|
||||
|
||||
TEXT ·SkipOne(SB), NOSPLIT, $0 - 32
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__skip_one(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__skip_one(SB)
|
||||
|
||||
TEXT ·Unquote(SB), NOSPLIT, $0 - 48
|
||||
CMPB github·com∕bytedance∕sonic∕internal∕cpu·HasAVX2(SB), $0
|
||||
JE 2(PC)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__unquote(SB)
|
||||
JMP github·com∕bytedance∕sonic∕internal∕native∕avx·__unquote(SB)
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package native
|
||||
package {{PACKAGE}}
|
||||
|
||||
import (
|
||||
`math`
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package native
|
||||
package {{PACKAGE}}
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
|
|
@ -14,10 +14,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package native
|
||||
package {{PACKAGE}}
|
||||
|
||||
import (
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
|
|
@ -53,42 +55,42 @@ func __lspace(sp unsafe.Pointer, nb int, off int) (ret int)
|
|||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __value(s unsafe.Pointer, n int, p int, v *JsonState) (ret int)
|
||||
func __value(s unsafe.Pointer, n int, p int, v *types.JsonState) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vstring(s *string, p *int, v *JsonState)
|
||||
func __vstring(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vnumber(s *string, p *int, v *JsonState)
|
||||
func __vnumber(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vsigned(s *string, p *int, v *JsonState)
|
||||
func __vsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __vunsigned(s *string, p *int, v *JsonState)
|
||||
func __vunsigned(s *string, p *int, v *types.JsonState)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_one(s *string, p *int, m *StateMachine) (ret int)
|
||||
func __skip_one(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_array(s *string, p *int, m *StateMachine) (ret int)
|
||||
func __skip_array(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func __skip_object(s *string, p *int, m *StateMachine) (ret int)
|
||||
func __skip_object(s *string, p *int, m *types.StateMachine) (ret int)
|
||||
|
||||
//go:nosplit
|
||||
//go:noescape
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package native
|
||||
package {{PACKAGE}}
|
||||
|
||||
import (
|
||||
`encoding/hex`
|
||||
|
|
@ -23,6 +23,7 @@ import (
|
|||
`testing`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/assert`
|
||||
|
|
@ -30,12 +31,12 @@ import (
|
|||
)
|
||||
|
||||
func TestNative_Value(t *testing.T) {
|
||||
var v JsonState
|
||||
var v types.JsonState
|
||||
s := ` -12345`
|
||||
p := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
x := __value(p.Ptr, p.Len, 0, &v)
|
||||
assert.Equal(t, 9, x)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
assert.Equal(t, int64(-12345), v.Iv)
|
||||
assert.Equal(t, 3, v.Ep)
|
||||
}
|
||||
|
|
@ -48,7 +49,7 @@ func TestNative_Unquote(t *testing.T) {
|
|||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
if rv < 0 {
|
||||
require.NoError(t, ParsingError(-rv))
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
|
|
@ -62,7 +63,7 @@ func TestNative_UnquoteError(t *testing.T) {
|
|||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(ERR_EOF), rv)
|
||||
assert.Equal(t, -int(types.ERR_EOF), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\gqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
|
|
@ -70,7 +71,7 @@ func TestNative_UnquoteError(t *testing.T) {
|
|||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(ERR_INVALID_ESCAPE), rv)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_ESCAPE), rv)
|
||||
assert.Equal(t, 5, ep)
|
||||
s = `asdf\u1gggqwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
|
|
@ -78,7 +79,7 @@ func TestNative_UnquoteError(t *testing.T) {
|
|||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(ERR_INVALID_CHAR), rv)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_CHAR), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
|
|
@ -86,15 +87,15 @@ func TestNative_UnquoteError(t *testing.T) {
|
|||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 6, ep)
|
||||
s = `asdf\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(ERR_INVALID_UNICODE), rv)
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 7, ep)
|
||||
s = `asdf\ud800\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
|
|
@ -102,15 +103,15 @@ func TestNative_UnquoteError(t *testing.T) {
|
|||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, 0)
|
||||
assert.Equal(t, -int(ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 12, ep)
|
||||
s = `asdf\\ud800\\ud800qwer`
|
||||
d = make([]byte, 0, len(s))
|
||||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(ERR_INVALID_UNICODE), rv)
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
assert.Equal(t, -int(types.ERR_INVALID_UNICODE), rv)
|
||||
assert.Equal(t, 14, ep)
|
||||
}
|
||||
|
||||
|
|
@ -120,9 +121,9 @@ func TestNative_DoubleUnquote(t *testing.T) {
|
|||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, F_DOUBLE_UNQUOTE)
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_DOUBLE_UNQUOTE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, ParsingError(-rv))
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
|
|
@ -135,9 +136,9 @@ func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
|
|||
ep := -1
|
||||
dp := (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp := (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, F_UNICODE_REPLACE)
|
||||
rv := __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, ParsingError(-rv))
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
|
|
@ -147,9 +148,9 @@ func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
|
|||
ep = -1
|
||||
dp = (*rt.GoSlice)(unsafe.Pointer(&d))
|
||||
sp = (*rt.GoString)(unsafe.Pointer(&s))
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, F_UNICODE_REPLACE)
|
||||
rv = __unquote(sp.Ptr, sp.Len, dp.Ptr, &ep, types.F_UNICODE_REPLACE)
|
||||
if rv < 0 {
|
||||
require.NoError(t, ParsingError(-rv))
|
||||
require.NoError(t, types.ParsingError(-rv))
|
||||
}
|
||||
dp.Len = rv
|
||||
assert.Equal(t, -1, ep)
|
||||
|
|
@ -157,7 +158,7 @@ func TestNative_UnquoteUnicodeReplacement(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNative_Vstring(t *testing.T) {
|
||||
var v JsonState
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := `test"test\n2"`
|
||||
__vstring(&s, &i, &v)
|
||||
|
|
@ -179,231 +180,231 @@ func TestNative_VstringHangUpOnRandomData(t *testing.T) {
|
|||
assert.Nil(t, e)
|
||||
p := 1
|
||||
s := rt.Mem2Str(v)
|
||||
var js JsonState
|
||||
var js types.JsonState
|
||||
__vstring(&s, &p, &js)
|
||||
fmt.Printf("js: %s\n", spew.Sdump(js))
|
||||
}
|
||||
|
||||
func TestNative_Vnumber(t *testing.T) {
|
||||
var v JsonState
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "1.234e5"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 7, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 1.234e5, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 0.0125, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "100000000000000000000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 100000000000000000000.0, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "999999999999999900000"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 21, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, 999999999999999900000.0, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
i = 0
|
||||
s = "-1.234"
|
||||
__vnumber(&s, &i, &v)
|
||||
assert.Equal(t, 6, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, -1.234, v.Dv)
|
||||
assert.Equal(t, V_DOUBLE, v.Vt)
|
||||
assert.Equal(t, types.V_DOUBLE, v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vsigned(t *testing.T) {
|
||||
var v JsonState
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(-1234), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775807"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MaxInt64), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(math.MinInt64), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "9223372036854775808"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 18, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-9223372036854775809"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e-5"
|
||||
__vsigned(&s, &i, &v)
|
||||
assert.Equal(t, 5, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_Vunsigned(t *testing.T) {
|
||||
var v JsonState
|
||||
var v types.JsonState
|
||||
i := 0
|
||||
s := "1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, int64(1234), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551615"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 20, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ^int64(0), v.Iv)
|
||||
assert.Equal(t, V_INTEGER, v.Vt)
|
||||
assert.Equal(t, types.V_INTEGER, v.Vt)
|
||||
i = 0
|
||||
s = "18446744073709551616"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 19, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INTEGER_OVERFLOW)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1.234"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "0.0125"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 1, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 4, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
i = 0
|
||||
s = "-1.234e-5"
|
||||
__vunsigned(&s, &i, &v)
|
||||
assert.Equal(t, 0, i)
|
||||
assert.Equal(t, 0, v.Ep)
|
||||
assert.Equal(t, ValueType(-int(ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
assert.Equal(t, types.ValueType(-int(types.ERR_INVALID_NUMBER_FMT)), v.Vt)
|
||||
}
|
||||
|
||||
func TestNative_SkipOne(t *testing.T) {
|
||||
p := 0
|
||||
s := ` {"asdf": [null, true, false, 1, 2.0, -3]}, 1234.5`
|
||||
q := __skip_one(&s, &p, &StateMachine{})
|
||||
q := __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 42, p)
|
||||
assert.Equal(t, 1, q)
|
||||
p = 0
|
||||
s = `1 2.5 -3 "asdf\nqwer" true false null {} []`
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 1, p)
|
||||
assert.Equal(t, 0, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 5, p)
|
||||
assert.Equal(t, 2, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 8, p)
|
||||
assert.Equal(t, 6, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 21, p)
|
||||
assert.Equal(t, 9, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 26, p)
|
||||
assert.Equal(t, 22, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 32, p)
|
||||
assert.Equal(t, 27, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 37, p)
|
||||
assert.Equal(t, 33, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 40, p)
|
||||
assert.Equal(t, 38, q)
|
||||
q = __skip_one(&s, &p, &StateMachine{})
|
||||
q = __skip_one(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, 43, p)
|
||||
assert.Equal(t, 41, q)
|
||||
}
|
||||
|
|
@ -411,13 +412,13 @@ func TestNative_SkipOne(t *testing.T) {
|
|||
func TestNative_SkipArray(t *testing.T) {
|
||||
p := 0
|
||||
s := `null, true, false, 1, 2.0, -3, {"asdf": "wqer"}],`
|
||||
__skip_array(&s, &p, &StateMachine{})
|
||||
__skip_array(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 48)
|
||||
}
|
||||
|
||||
func TestNative_SkipObject(t *testing.T) {
|
||||
p := 0
|
||||
s := `"asdf": "wqer"},`
|
||||
__skip_object(&s, &p, &StateMachine{})
|
||||
__skip_object(&s, &p, &types.StateMachine{})
|
||||
assert.Equal(t, p, 15)
|
||||
}
|
||||
43
internal/native/native_export_amd64.tmpl
Normal file
43
internal/native/native_export_amd64.tmpl
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 {{PACKAGE}}
|
||||
|
||||
var (
|
||||
S_f64toa = _subr__f64toa
|
||||
S_i64toa = _subr__i64toa
|
||||
S_lquote = _subr__lquote
|
||||
S_u64toa = _subr__u64toa
|
||||
)
|
||||
|
||||
var (
|
||||
S_lspace = _subr__lspace
|
||||
S_unquote = _subr__unquote
|
||||
)
|
||||
|
||||
var (
|
||||
S_value = _subr__value
|
||||
S_vstring = _subr__vstring
|
||||
S_vnumber = _subr__vnumber
|
||||
S_vsigned = _subr__vsigned
|
||||
S_vunsigned = _subr__vunsigned
|
||||
)
|
||||
|
||||
var (
|
||||
S_skip_one = _subr__skip_one
|
||||
S_skip_array = _subr__skip_array
|
||||
S_skip_object = _subr__skip_object
|
||||
)
|
||||
|
|
@ -14,11 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package native
|
||||
package types
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`unsafe`
|
||||
)
|
||||
|
||||
type ValueType int
|
||||
|
|
@ -96,53 +95,3 @@ type StateMachine struct {
|
|||
Sp int
|
||||
Vt [MAX_RECURSE]int
|
||||
}
|
||||
|
||||
var (
|
||||
S_f64toa = _subr__f64toa
|
||||
S_i64toa = _subr__i64toa
|
||||
S_lquote = _subr__lquote
|
||||
S_u64toa = _subr__u64toa
|
||||
)
|
||||
|
||||
var (
|
||||
S_lspace = _subr__lspace
|
||||
S_unquote = _subr__unquote
|
||||
)
|
||||
|
||||
var (
|
||||
S_value = _subr__value
|
||||
S_vstring = _subr__vstring
|
||||
S_vnumber = _subr__vnumber
|
||||
S_vsigned = _subr__vsigned
|
||||
S_vunsigned = _subr__vunsigned
|
||||
)
|
||||
|
||||
var (
|
||||
S_skip_one = _subr__skip_one
|
||||
S_skip_array = _subr__skip_array
|
||||
S_skip_object = _subr__skip_object
|
||||
)
|
||||
|
||||
func Lzero(p unsafe.Pointer, n int) int {
|
||||
return __lzero(p, n)
|
||||
}
|
||||
|
||||
func Lquote(buf *string, off int) int {
|
||||
return __lquote(buf, off)
|
||||
}
|
||||
|
||||
func Lspace(sp unsafe.Pointer, nb int, off int) int {
|
||||
return __lspace(sp, nb, off)
|
||||
}
|
||||
|
||||
func Value(s unsafe.Pointer, n int, p int, v *JsonState) int {
|
||||
return __value(s, n, p, v)
|
||||
}
|
||||
|
||||
func SkipOne(s *string, p *int, m *StateMachine) int {
|
||||
return __skip_one(s, p, m)
|
||||
}
|
||||
|
||||
func Unquote(s unsafe.Pointer, nb int, dp unsafe.Pointer, ep *int, flags uint64) int {
|
||||
return __unquote(s, nb, dp, ep, flags)
|
||||
}
|
||||
|
|
@ -16,43 +16,39 @@
|
|||
|
||||
#include "native.h"
|
||||
|
||||
#if USE_SSE
|
||||
#define loop_decl() \
|
||||
size_t v; \
|
||||
size_t n = 0; \
|
||||
const char * p = s; \
|
||||
|
||||
#define loop_m128(func, ...) { \
|
||||
if (nb >= 16) { \
|
||||
if ((v = func(_mm_loadu_si128(as_m128c(p)), ## __VA_ARGS__)) < 16) { \
|
||||
#define loop_simd(size, load, func, ...) { \
|
||||
while (nb >= size) { \
|
||||
if ((v = func(load((const void *)(p)), ## __VA_ARGS__)) < size) { \
|
||||
return n + v; \
|
||||
} else { \
|
||||
n += v; \
|
||||
p += 16; \
|
||||
nb -= 16; \
|
||||
p += size; \
|
||||
nb -= size; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define loop_m256(func, ...) { \
|
||||
while (nb >= 32) { \
|
||||
if ((v = func(_mm256_loadu_si256(as_m256c(p)), ## __VA_ARGS__)) < 32) { \
|
||||
return n + v; \
|
||||
} else { \
|
||||
n += v; \
|
||||
p += 32; \
|
||||
nb -= 32; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#if !USE_AVX2
|
||||
#define loop_zero()
|
||||
#define loop_m256(func, ...)
|
||||
#else
|
||||
#define loop_zero() _mm256_zeroupper();
|
||||
#define loop_m256(func, ...) loop_simd(32, _mm256_loadu_si256, func, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define loop_last(func, ...) { \
|
||||
return func(_mm_loadu_si128(as_m128c(p + nb - 16)), ## __VA_ARGS__) + n + nb - 16; \
|
||||
}
|
||||
#define loop_m128(func, ...) loop_simd(16, _mm_loadu_si128, func, ## __VA_ARGS__)
|
||||
#define loop_last(func, ...) return func(_mm_loadu_si128(as_m128c(p + nb - 16)), ## __VA_ARGS__) + n + nb - 16;
|
||||
|
||||
#define loop_simd(func, ...) { \
|
||||
#define loop_bulk(func, ...) { \
|
||||
loop_decl() \
|
||||
loop_m256(func ## _avx2, ## __VA_ARGS__) \
|
||||
_mm256_zeroupper(); \
|
||||
loop_zero(); \
|
||||
loop_m128(func ## _sse2, ## __VA_ARGS__) \
|
||||
loop_last(func ## _sse2, ## __VA_ARGS__) \
|
||||
}
|
||||
|
|
@ -95,6 +91,7 @@ static inline size_t lspace_sse2(__m128i v0) {
|
|||
return v9;
|
||||
}
|
||||
|
||||
#if USE_AVX2
|
||||
static inline size_t lspace_avx2(__m256i v0) {
|
||||
__m256i v1 = _mm256_cmpeq_epi8 (v0, _mm256_set1_epi8(' '));
|
||||
__m256i v2 = _mm256_cmpeq_epi8 (v0, _mm256_set1_epi8('\t'));
|
||||
|
|
@ -107,6 +104,7 @@ static inline size_t lspace_avx2(__m256i v0) {
|
|||
uint64_t v9 = __builtin_ctzll (~(uint64_t)(v8));
|
||||
return v9;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline size_t lquote_sse2(__m128i v0) {
|
||||
__m128i v1 = _mm_cmpgt_epi8 (v0, _mm_set1_epi8(-1));
|
||||
|
|
@ -121,6 +119,7 @@ static inline size_t lquote_sse2(__m128i v0) {
|
|||
return v9;
|
||||
}
|
||||
|
||||
#if USE_AVX2
|
||||
static inline size_t lquote_avx2(__m256i v0) {
|
||||
__m256i v1 = _mm256_cmpgt_epi8 (v0, _mm256_set1_epi8(-1));
|
||||
__m256i v2 = _mm256_cmpgt_epi8 (v0, _mm256_set1_epi8(31));
|
||||
|
|
@ -133,6 +132,7 @@ static inline size_t lquote_avx2(__m256i v0) {
|
|||
uint64_t v9 = __builtin_ctzll ((uint64_t)v8 | 0xffffffff00000000);
|
||||
return v9;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline size_t strchr2_sse2(__m128i v0, uint64_t c0, uint64_t c1) {
|
||||
__m128i v1 = _mm_cmpeq_epi8 (v0, _mm_set1_epi8((char)c0));
|
||||
|
|
@ -143,6 +143,7 @@ static inline size_t strchr2_sse2(__m128i v0, uint64_t c0, uint64_t c1) {
|
|||
return v5;
|
||||
}
|
||||
|
||||
#if USE_AVX2
|
||||
static inline size_t strchr2_avx2(__m256i v0, uint64_t c0, uint64_t c1) {
|
||||
__m256i v1 = _mm256_cmpeq_epi8 (v0, _mm256_set1_epi8((char)c0));
|
||||
__m256i v2 = _mm256_cmpeq_epi8 (v0, _mm256_set1_epi8((char)c1));
|
||||
|
|
@ -151,127 +152,59 @@ static inline size_t strchr2_avx2(__m256i v0, uint64_t c0, uint64_t c1) {
|
|||
uint64_t v5 = __builtin_ctzll ((uint64_t)v4 | 0xffffffff00000000);
|
||||
return v5;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define do_simd(func, ...) { \
|
||||
if (nb == 0) { \
|
||||
return 0; \
|
||||
} if (nb < 16) { \
|
||||
loop_duff(func, ## __VA_ARGS__) \
|
||||
} else { \
|
||||
loop_bulk(func, ## __VA_ARGS__) \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define is_quote(c) ((c) == '"' || (c) == '\\' || ((c) >= 0 && (c) <= 31))
|
||||
#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
|
||||
|
||||
static inline size_t lspace_p(const char *s, size_t nb) {
|
||||
if (nb == 0) {
|
||||
return 0;
|
||||
} else if (nb < 16) {
|
||||
loop_duff(lspace)
|
||||
} else {
|
||||
loop_simd(lspace)
|
||||
}
|
||||
#if USE_SSE
|
||||
do_simd(lspace)
|
||||
#else
|
||||
size_t i = 0;
|
||||
while (i < nb && !is_space(s[i])) i++;
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline size_t lquote_p(const char *s, size_t nb) {
|
||||
if (nb == 0) {
|
||||
return 0;
|
||||
} else if (nb < 16) {
|
||||
loop_duff(lquote)
|
||||
} else {
|
||||
loop_simd(lquote)
|
||||
}
|
||||
#if USE_SSE
|
||||
do_simd(lquote)
|
||||
#else
|
||||
size_t i = 0;
|
||||
while (i < nb && !is_quote(s[i])) i++;
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline size_t strchr1_p(const char *p, size_t nb, uint64_t ch) {
|
||||
__m256i a;
|
||||
__m256i b;
|
||||
__m256i c;
|
||||
__m256i d;
|
||||
__m256i u;
|
||||
__m256i v;
|
||||
__m256i w;
|
||||
int32_t r;
|
||||
#if USE_SSE
|
||||
int64_t r;
|
||||
uint32_t t;
|
||||
|
||||
/* prepare the vector */
|
||||
__m256i x = _mm256_set1_epi8(ch);
|
||||
ssize_t n = nb;
|
||||
uintptr_t m = (uintptr_t)p;
|
||||
const char * q = p;
|
||||
|
||||
/* check for pointer alignment */
|
||||
if (m & 31) {
|
||||
v = _mm256_load_si256 ((const void *)(m & -32));
|
||||
v = _mm256_cmpeq_epi8 (v, x);
|
||||
r = _mm256_movemask_epi8 (v);
|
||||
|
||||
/* check for match in the first characters */
|
||||
if ((r = r >> (t = m & 31)) != 0) {
|
||||
if ((r = _mm_tzcnt_64(r)) < n) {
|
||||
return r;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* make the pointer aligned */
|
||||
p += 32 - t;
|
||||
n -= 32 - t;
|
||||
}
|
||||
|
||||
/* attempt to compare 128-bytes at a time */
|
||||
while (n >= 128) {
|
||||
a = _mm256_cmpeq_epi8 (_mm256_load_si256((const void *)(p + 0)), x);
|
||||
b = _mm256_cmpeq_epi8 (_mm256_load_si256((const void *)(p + 32)), x);
|
||||
c = _mm256_cmpeq_epi8 (_mm256_load_si256((const void *)(p + 64)), x);
|
||||
d = _mm256_cmpeq_epi8 (_mm256_load_si256((const void *)(p + 96)), x);
|
||||
u = _mm256_or_si256 (a, b);
|
||||
v = _mm256_or_si256 (c, d);
|
||||
w = _mm256_or_si256 (u, v);
|
||||
|
||||
/* check if anything matches */
|
||||
if (_mm256_testz_si256(w, w)) {
|
||||
p += 128;
|
||||
n -= 128;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* match something in the 128-byte region */
|
||||
if ((r = _mm256_movemask_epi8(a)) != 0) {
|
||||
return p - q + _mm_tzcnt_64(r);
|
||||
} else if ((r = _mm256_movemask_epi8(b)) != 0) {
|
||||
return p - q + _mm_tzcnt_64(r) + 32;
|
||||
} else if ((r = _mm256_movemask_epi8(c)) != 0) {
|
||||
return p - q + _mm_tzcnt_64(r) + 64;
|
||||
} else {
|
||||
return p - q + _mm_tzcnt_64(_mm256_movemask_epi8(d)) + 96;
|
||||
}
|
||||
}
|
||||
|
||||
/* check every 32 bytes, at most 4 times */
|
||||
for (int i = 0; i < 4 && n >= 0; i++) {
|
||||
v = _mm256_cmpeq_epi8 (_mm256_load_si256((const void *)p), x);
|
||||
r = _mm256_movemask_epi8 (v);
|
||||
|
||||
/* found something */
|
||||
if (r != 0) {
|
||||
if ((r = _mm_tzcnt_64(r)) >= n) {
|
||||
return -1;
|
||||
} else {
|
||||
return p - q + r;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise advance to next block */
|
||||
p += 32;
|
||||
n -= 32;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return nb;
|
||||
}
|
||||
|
||||
static inline size_t strchr2_p(const char *s, size_t nb, uint64_t c0, uint64_t c1) {
|
||||
if (nb == 0) {
|
||||
return 0;
|
||||
} else if (nb < 16) {
|
||||
loop_duff(strchr2, c0, c1)
|
||||
} else {
|
||||
loop_simd(strchr2, c0, c1)
|
||||
}
|
||||
}
|
||||
|
||||
size_t lzero(const char *p, size_t n) {
|
||||
#if USE_AVX2
|
||||
#define ALIGN_VAL 31
|
||||
#define _mm_or _mm256_or_si256
|
||||
#define _mm_load _mm256_load_si256
|
||||
#define _mm_cmpeq(a, b) _mm256_cmpeq_epi8(a, b)
|
||||
#define _mm_testz(v) _mm256_testz_si256(v, v)
|
||||
#define _mm_movemask(v) _mm256_movemask_epi8(v)
|
||||
__m256i a;
|
||||
__m256i b;
|
||||
__m256i c;
|
||||
|
|
@ -279,47 +212,219 @@ size_t lzero(const char *p, size_t n) {
|
|||
__m256i u;
|
||||
__m256i v;
|
||||
__m256i w;
|
||||
__m256i x = _mm256_set1_epi8(ch);
|
||||
#else
|
||||
#define ALIGN_VAL 15
|
||||
#define _mm_or _mm_or_si128
|
||||
#define _mm_load _mm_load_si128
|
||||
#define _mm_cmpeq(a, b) _mm_cmpeq_epi8(a, b)
|
||||
#define _mm_testz(v) (_mm_movemask_epi8(v) == 0)
|
||||
#define _mm_movemask(v) _mm_movemask_epi8(v)
|
||||
__m128i a;
|
||||
__m128i b;
|
||||
__m128i c;
|
||||
__m128i d;
|
||||
__m128i u;
|
||||
__m128i v;
|
||||
__m128i w;
|
||||
__m128i x = _mm_set1_epi8(ch);
|
||||
#endif
|
||||
|
||||
/* zero vector */
|
||||
size_t r = 0;
|
||||
#define BLOCK_SIZE (ALIGN_VAL + 1)
|
||||
#define BLOCK_MASK (1ull << BLOCK_SIZE)
|
||||
#define BLOCK_LARGE (BLOCK_SIZE * 4)
|
||||
|
||||
/* check for pointer alignment */
|
||||
if (m & ALIGN_VAL) {
|
||||
v = _mm_load ((const void *)(m & -BLOCK_SIZE));
|
||||
v = _mm_cmpeq (v, x);
|
||||
r = _mm_movemask (v);
|
||||
|
||||
/* check for match in the first characters */
|
||||
if ((r >>= (t = m & ALIGN_VAL)) != 0) {
|
||||
if ((r = __builtin_ctzll(r | BLOCK_MASK)) < n) {
|
||||
return r;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* make the pointer aligned */
|
||||
p += BLOCK_SIZE - t;
|
||||
n -= BLOCK_SIZE - t;
|
||||
}
|
||||
|
||||
/* attempt to compare 4 blocks at a time */
|
||||
while (n >= BLOCK_LARGE) {
|
||||
a = _mm_load ((const void *)(p + BLOCK_SIZE * 0));
|
||||
b = _mm_load ((const void *)(p + BLOCK_SIZE * 1));
|
||||
c = _mm_load ((const void *)(p + BLOCK_SIZE * 2));
|
||||
d = _mm_load ((const void *)(p + BLOCK_SIZE * 3));
|
||||
a = _mm_cmpeq (a, x);
|
||||
b = _mm_cmpeq (b, x);
|
||||
c = _mm_cmpeq (c, x);
|
||||
d = _mm_cmpeq (d, x);
|
||||
u = _mm_or (a, b);
|
||||
v = _mm_or (c, d);
|
||||
w = _mm_or (u, v);
|
||||
|
||||
/* check if anything matches */
|
||||
if (_mm_testz(w)) {
|
||||
p += BLOCK_LARGE;
|
||||
n -= BLOCK_LARGE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* match something in the 4-blocks region */
|
||||
if ((r = _mm_movemask(a)) != 0) {
|
||||
return p - q + __builtin_ctzll(r | BLOCK_MASK);
|
||||
} else if ((r = _mm_movemask(b)) != 0) {
|
||||
return p - q + __builtin_ctzll(r | BLOCK_MASK) + BLOCK_SIZE;
|
||||
} else if ((r = _mm_movemask(c)) != 0) {
|
||||
return p - q + __builtin_ctzll(r | BLOCK_MASK) + BLOCK_SIZE * 2;
|
||||
} else {
|
||||
return p - q + __builtin_ctzll(_mm_movemask(d) | BLOCK_MASK) + BLOCK_SIZE * 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* check every block, at most 4 times */
|
||||
for (int i = 0; i < 4 && n >= 0; i++) {
|
||||
v = _mm_load ((const void *)p);
|
||||
v = _mm_cmpeq (v, x);
|
||||
r = _mm_movemask (v);
|
||||
|
||||
/* found something */
|
||||
if (r != 0) {
|
||||
if ((r = __builtin_ctzll(r | BLOCK_MASK)) >= n) {
|
||||
return -1;
|
||||
} else {
|
||||
return p - q + r;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise advance to next block */
|
||||
p += BLOCK_SIZE;
|
||||
n -= BLOCK_SIZE;
|
||||
}
|
||||
|
||||
#undef _mm_load
|
||||
#undef _mm_bitor
|
||||
#undef _mm_cmpeq
|
||||
#undef _mm_testz
|
||||
#undef _mm_movemask
|
||||
#undef ALIGN_VAL
|
||||
#undef BLOCK_SIZE
|
||||
#undef BLOCK_LARGE
|
||||
#else
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (p[i] == ch) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* not found */
|
||||
return nb;
|
||||
}
|
||||
|
||||
static inline size_t strchr2_p(const char *s, size_t nb, uint64_t c0, uint64_t c1) {
|
||||
#if USE_SSE
|
||||
do_simd(strchr2, c0, c1)
|
||||
#else
|
||||
size_t i = 0;
|
||||
while (i < nb && s[i] != c0 && s[i] != c1) i++;
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t lzero(const char *p, size_t n) {
|
||||
#if USE_SSE
|
||||
#if USE_AVX
|
||||
__m256i a;
|
||||
__m256i b;
|
||||
__m256i c;
|
||||
__m256i d;
|
||||
__m256i u;
|
||||
__m256i v;
|
||||
__m256i w;
|
||||
__m256i y = _mm256_set1_epi8(0xff);
|
||||
__m256i z = _mm256_setzero_si256();
|
||||
#define BLOCK_SIZE 32
|
||||
#else
|
||||
__m128i a;
|
||||
__m128i b;
|
||||
__m128i c;
|
||||
__m128i d;
|
||||
__m128i u;
|
||||
__m128i v;
|
||||
__m128i w;
|
||||
__m128i z = _mm_setzero_si128();
|
||||
#define BLOCK_SIZE 16
|
||||
#endif
|
||||
|
||||
/* 128 bytes loop */
|
||||
while (n >= 128) {
|
||||
a = _mm256_cmpeq_epi8 (_mm256_loadu_si256(as_m256c(p + 0)), z);
|
||||
b = _mm256_cmpeq_epi8 (_mm256_loadu_si256(as_m256c(p + 32)), z);
|
||||
c = _mm256_cmpeq_epi8 (_mm256_loadu_si256(as_m256c(p + 64)), z);
|
||||
d = _mm256_cmpeq_epi8 (_mm256_loadu_si256(as_m256c(p + 96)), z);
|
||||
u = _mm256_and_si256 (a, b);
|
||||
v = _mm256_and_si256 (c, d);
|
||||
w = _mm256_xor_si256 (v, y);
|
||||
#if USE_AVX2
|
||||
#define _mm_load _mm256_load_si256
|
||||
#define _mm_and(a, b) _mm256_and_si256(a, b)
|
||||
#define _mm_cmpeq(a, b) _mm256_cmpeq_epi8(a, b)
|
||||
#define _mm_testinz(v) (!_mm256_testc_si256(v, y))
|
||||
#elif USE_AVX
|
||||
#define _mm_load _mm256_load_si256
|
||||
#define _mm_and(a, b) _mm256_and_ps((__m256)a, (__m256)b)
|
||||
#define _mm_cmpeq(a, b) _mm256_cmp_ps(a, b, _CMP_EQ_OQ)
|
||||
#define _mm_testinz(v) (!_mm256_testc_si256(v, y))
|
||||
#else
|
||||
#define _mm_load _mm_load_si128
|
||||
#define _mm_and(a, b) _mm_and_si128(a, b)
|
||||
#define _mm_cmpeq(a, b) _mm_cmpeq_epi8(a, b)
|
||||
#define _mm_testinz(v) (_mm_movemask_epi8(v) != 0xffff)
|
||||
#endif
|
||||
|
||||
/* multi-block loop */
|
||||
while (n >= BLOCK_SIZE * 4) {
|
||||
a = _mm_load ((const void *)(p + BLOCK_SIZE * 0));
|
||||
b = _mm_load ((const void *)(p + BLOCK_SIZE * 1));
|
||||
c = _mm_load ((const void *)(p + BLOCK_SIZE * 2));
|
||||
d = _mm_load ((const void *)(p + BLOCK_SIZE * 3));
|
||||
a = _mm_cmpeq (a, z);
|
||||
b = _mm_cmpeq (b, z);
|
||||
c = _mm_cmpeq (c, z);
|
||||
d = _mm_cmpeq (d, z);
|
||||
u = _mm_and (a, b);
|
||||
v = _mm_and (c, d);
|
||||
w = _mm_and (u, v);
|
||||
|
||||
/* test for zeros */
|
||||
if (!_mm256_testc_si256(u, w)) {
|
||||
if (_mm_testinz(w)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* move to next block */
|
||||
p += 128;
|
||||
n -= 128;
|
||||
p += BLOCK_SIZE * 4;
|
||||
n -= BLOCK_SIZE * 4;
|
||||
}
|
||||
|
||||
/* 32 bytes loop */
|
||||
while (n >= 32) {
|
||||
a = _mm256_loadu_si256 (as_m256c(p));
|
||||
b = _mm256_cmpeq_epi8 (a, z);
|
||||
/* single block loop */
|
||||
while (n >= BLOCK_SIZE) {
|
||||
a = _mm_load ((const void *)(p));
|
||||
b = _mm_cmpeq (a, z);
|
||||
|
||||
/* test for zeros */
|
||||
if (!_mm256_testc_si256(b, y)) {
|
||||
if (_mm_testinz(b)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* move to next block */
|
||||
p += 32;
|
||||
n -= 32;
|
||||
p += BLOCK_SIZE;
|
||||
n -= BLOCK_SIZE;
|
||||
}
|
||||
|
||||
#undef _mm_load
|
||||
#undef _mm_cmpeq
|
||||
#undef _mm_bitand
|
||||
#undef _mm_testinz
|
||||
#undef BLOCK_SIZE
|
||||
#endif
|
||||
|
||||
/* 8 bytes loop */
|
||||
while (n >= 8) {
|
||||
if (*(uint64_t *)p) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "native.h"
|
||||
|
||||
#if USE_SSE
|
||||
|
||||
static const char Digits[200] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
|
||||
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
|
||||
|
|
@ -221,6 +223,8 @@ static inline int u64toa_xlarge_sse2(char *out, uint64_t val) {
|
|||
return n + 16;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int i64toa(char *out, int64_t val) {
|
||||
if (likely(val >= 0)) {
|
||||
return u64toa(out, (uint64_t)val);
|
||||
|
|
@ -230,6 +234,8 @@ int i64toa(char *out, int64_t val) {
|
|||
}
|
||||
}
|
||||
|
||||
#if USE_SSE
|
||||
|
||||
int u64toa(char *out, uint64_t val) {
|
||||
if (likely(val < 10000)) {
|
||||
return u32toa_small(out, (uint32_t)val);
|
||||
|
|
@ -241,3 +247,29 @@ int u64toa(char *out, uint64_t val) {
|
|||
return u64toa_xlarge_sse2(out, val);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int u64toa(char *out, uint64_t val) {
|
||||
char c;
|
||||
long n = 0;
|
||||
uint64_t v = val;
|
||||
|
||||
/* convert each digit */
|
||||
while (val) {
|
||||
out[n++] = v % 10 + '0';
|
||||
v /= 10;
|
||||
}
|
||||
|
||||
/* reverse the output */
|
||||
for (long i = 0; i < n / 2; i++) {
|
||||
c = out[i];
|
||||
out[i] = out[n - i - 1];
|
||||
out[n - i - 1] = c;
|
||||
}
|
||||
|
||||
/* all done */
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,55 +28,60 @@ static const char _UnquoteTab[256] = {
|
|||
['\\'] = '\\',
|
||||
};
|
||||
|
||||
#define memcchr_p32_avx2() \
|
||||
while (n >= 32) { \
|
||||
u = _mm256_loadu_si256 ((const void *)s); \
|
||||
v = _mm256_cmpeq_epi8 (u, b); \
|
||||
_mm256_storeu_si256 ((void *)p, u); \
|
||||
\
|
||||
/* check for matches */ \
|
||||
if ((r = _mm256_movemask_epi8(v)) != 0) { \
|
||||
return s - q + _mm_tzcnt_64(r); \
|
||||
} \
|
||||
\
|
||||
/* move to the next 32 bytes */ \
|
||||
s += 32; \
|
||||
p += 32; \
|
||||
n -= 32; \
|
||||
} \
|
||||
|
||||
#define memcchr_p32_sse2() \
|
||||
if (n >= 16) { \
|
||||
x = _mm_loadu_si128 ((const void *)s); \
|
||||
y = _mm_cmpeq_epi8 (x, a); \
|
||||
_mm_storeu_si128 ((void *)p, x); \
|
||||
\
|
||||
/* check for matches */ \
|
||||
if ((r = _mm_movemask_epi8(y)) != 0) { \
|
||||
return s - q + _mm_tzcnt_64(r); \
|
||||
} \
|
||||
\
|
||||
/* move to the next 16 bytes */ \
|
||||
s += 16; \
|
||||
p += 16; \
|
||||
n -= 16; \
|
||||
}
|
||||
|
||||
static inline ssize_t memcchr_p32(const char *s, ssize_t nb, char *p) {
|
||||
int32_t r;
|
||||
__m128i x;
|
||||
__m128i y;
|
||||
__m256i u;
|
||||
__m256i v;
|
||||
__m128i a = _mm_set1_epi8('\\');
|
||||
__m256i b = _mm256_set1_epi8('\\');
|
||||
int64_t r;
|
||||
ssize_t n = nb;
|
||||
const char * q = s;
|
||||
|
||||
/* scan & copy with SIMD */
|
||||
memcchr_p32_avx2();
|
||||
#if USE_AVX2
|
||||
__m256i u;
|
||||
__m256i v;
|
||||
__m256i b = _mm256_set1_epi8('\\');
|
||||
|
||||
/* process every 32 bytes */
|
||||
while (n >= 32) {
|
||||
u = _mm256_loadu_si256 ((const void *)s);
|
||||
v = _mm256_cmpeq_epi8 (u, b);
|
||||
_mm256_storeu_si256 ((void *)p, u);
|
||||
|
||||
/* check for matches */
|
||||
if ((r = _mm256_movemask_epi8(v)) != 0) {
|
||||
return s - q + __builtin_ctzll(r | (1ull << 32));
|
||||
}
|
||||
|
||||
/* move to the next 32 bytes */
|
||||
s += 32;
|
||||
p += 32;
|
||||
n -= 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_AVX2
|
||||
_mm256_zeroupper();
|
||||
memcchr_p32_sse2();
|
||||
#endif
|
||||
|
||||
#if USE_SSE
|
||||
__m128i x;
|
||||
__m128i y;
|
||||
__m128i a = _mm_set1_epi8('\\');
|
||||
|
||||
/* process every 16 bytes */
|
||||
while (n >= 16) {
|
||||
x = _mm_loadu_si128 ((const void *)s);
|
||||
y = _mm_cmpeq_epi8 (x, a);
|
||||
_mm_storeu_si128 ((void *)p, x);
|
||||
|
||||
/* check for matches */
|
||||
if ((r = _mm_movemask_epi8(y)) != 0) {
|
||||
return s - q + __builtin_ctzll(r | (1 << 16));
|
||||
}
|
||||
|
||||
/* move to the next 16 bytes */
|
||||
s += 16;
|
||||
p += 16;
|
||||
n -= 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* remaining bytes, do with scalar code */
|
||||
while (n--) {
|
||||
|
|
@ -91,9 +96,6 @@ static inline ssize_t memcchr_p32(const char *s, ssize_t nb, char *p) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
#undef memcchr_p32_avx2
|
||||
#undef memcchr_p32_sse2
|
||||
|
||||
#define ALL_01h (~0ul / 255)
|
||||
#define ALL_7fh (ALL_01h * 127)
|
||||
#define ALL_80h (ALL_01h * 128)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 75fa4e6f2ee3ee4049724fe2a3806fbf119d0667
|
||||
Subproject commit 38a813682862252de3d1a016c90755467bff0ee9
|
||||
Loading…
Reference in a new issue