Enable Boundary Check Elimination by pointer arithmetic

This commit is contained in:
Masaaki Goshima 2021-02-06 01:09:24 +09:00
parent f1664b5c1f
commit b3e93b7040
4 changed files with 29 additions and 19 deletions

View File

@ -1,5 +1,7 @@
package json
import "unsafe"
var (
isWhiteSpace = [256]bool{}
)
@ -11,6 +13,10 @@ func init() {
isWhiteSpace['\r'] = true
}
func char(ptr unsafe.Pointer, offset int64) byte {
return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
}
func skipWhiteSpace(buf []byte, cursor int64) int64 {
LOOP:
if isWhiteSpace[buf[cursor]] {

View File

@ -130,8 +130,9 @@ ERROR:
}
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch buf[cursor] {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
continue
@ -139,14 +140,14 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
start := cursor
cursor++
LOOP:
if numTable[buf[cursor]] {
if numTable[char(b, cursor)] {
cursor++
goto LOOP
}
num := buf[start:cursor]
return num, cursor, nil
default:
return nil, 0, d.typeError([]byte{buf[cursor]}, cursor)
return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor)
}
}
}

View File

@ -249,11 +249,12 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
case '"':
cursor++
start := cursor
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch buf[cursor] {
switch char(b, cursor) {
case '\\':
cursor++
switch buf[cursor] {
switch char(b, cursor) {
case '"':
buf[cursor] = '"'
buf = append(buf[:cursor-1], buf[cursor:]...)

View File

@ -120,13 +120,14 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
field *structFieldSet
curBit int8 = math.MaxInt8
)
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch buf[cursor] {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case '"':
cursor++
c := buf[cursor]
c := char(b, cursor)
switch c {
case '"':
cursor++
@ -138,7 +139,7 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
bitmap := d.keyBitmapInt8
keyBitmapLen := len(bitmap)
for {
c := buf[cursor]
c := char(b, cursor)
switch c {
case '"':
x := uint64(curBit & -curBit)
@ -152,13 +153,13 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
if keyIdx >= keyBitmapLen {
for {
cursor++
switch buf[cursor] {
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if buf[cursor] == nul {
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul:
@ -170,13 +171,13 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
if curBit == 0 {
for {
cursor++
switch buf[cursor] {
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if buf[cursor] == nul {
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul:
@ -199,13 +200,14 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
field *structFieldSet
curBit int16 = math.MaxInt16
)
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch buf[cursor] {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case '"':
cursor++
c := buf[cursor]
c := char(b, cursor)
switch c {
case '"':
cursor++
@ -217,7 +219,7 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
bitmap := d.keyBitmapInt16
keyBitmapLen := len(bitmap)
for {
c := buf[cursor]
c := char(b, cursor)
switch c {
case '"':
x := uint64(curBit & -curBit)
@ -231,13 +233,13 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
if keyIdx >= keyBitmapLen {
for {
cursor++
switch buf[cursor] {
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if buf[cursor] == nul {
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul:
@ -249,13 +251,13 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
if curBit == 0 {
for {
cursor++
switch buf[cursor] {
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if buf[cursor] == nul {
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul: