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 package json
import "unsafe"
var ( var (
isWhiteSpace = [256]bool{} isWhiteSpace = [256]bool{}
) )
@ -11,6 +13,10 @@ func init() {
isWhiteSpace['\r'] = true 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 { func skipWhiteSpace(buf []byte, cursor int64) int64 {
LOOP: LOOP:
if isWhiteSpace[buf[cursor]] { if isWhiteSpace[buf[cursor]] {

View File

@ -130,8 +130,9 @@ ERROR:
} }
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
switch buf[cursor] { switch char(b, cursor) {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++ cursor++
continue continue
@ -139,14 +140,14 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
start := cursor start := cursor
cursor++ cursor++
LOOP: LOOP:
if numTable[buf[cursor]] { if numTable[char(b, cursor)] {
cursor++ cursor++
goto LOOP goto LOOP
} }
num := buf[start:cursor] num := buf[start:cursor]
return num, cursor, nil return num, cursor, nil
default: 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 '"': case '"':
cursor++ cursor++
start := cursor start := cursor
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
switch buf[cursor] { switch char(b, cursor) {
case '\\': case '\\':
cursor++ cursor++
switch buf[cursor] { switch char(b, cursor) {
case '"': case '"':
buf[cursor] = '"' buf[cursor] = '"'
buf = append(buf[:cursor-1], 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 field *structFieldSet
curBit int8 = math.MaxInt8 curBit int8 = math.MaxInt8
) )
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
switch buf[cursor] { switch char(b, cursor) {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++ cursor++
case '"': case '"':
cursor++ cursor++
c := buf[cursor] c := char(b, cursor)
switch c { switch c {
case '"': case '"':
cursor++ cursor++
@ -138,7 +139,7 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
bitmap := d.keyBitmapInt8 bitmap := d.keyBitmapInt8
keyBitmapLen := len(bitmap) keyBitmapLen := len(bitmap)
for { for {
c := buf[cursor] c := char(b, cursor)
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) x := uint64(curBit & -curBit)
@ -152,13 +153,13 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
if keyIdx >= keyBitmapLen { if keyIdx >= keyBitmapLen {
for { for {
cursor++ cursor++
switch buf[cursor] { switch char(b, cursor) {
case '"': case '"':
cursor++ cursor++
return cursor, field, nil return cursor, field, nil
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
case nul: case nul:
@ -170,13 +171,13 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
if curBit == 0 { if curBit == 0 {
for { for {
cursor++ cursor++
switch buf[cursor] { switch char(b, cursor) {
case '"': case '"':
cursor++ cursor++
return cursor, field, nil return cursor, field, nil
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
case nul: case nul:
@ -199,13 +200,14 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
field *structFieldSet field *structFieldSet
curBit int16 = math.MaxInt16 curBit int16 = math.MaxInt16
) )
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
switch buf[cursor] { switch char(b, cursor) {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++ cursor++
case '"': case '"':
cursor++ cursor++
c := buf[cursor] c := char(b, cursor)
switch c { switch c {
case '"': case '"':
cursor++ cursor++
@ -217,7 +219,7 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
bitmap := d.keyBitmapInt16 bitmap := d.keyBitmapInt16
keyBitmapLen := len(bitmap) keyBitmapLen := len(bitmap)
for { for {
c := buf[cursor] c := char(b, cursor)
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) x := uint64(curBit & -curBit)
@ -231,13 +233,13 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
if keyIdx >= keyBitmapLen { if keyIdx >= keyBitmapLen {
for { for {
cursor++ cursor++
switch buf[cursor] { switch char(b, cursor) {
case '"': case '"':
cursor++ cursor++
return cursor, field, nil return cursor, field, nil
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
case nul: case nul:
@ -249,13 +251,13 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
if curBit == 0 { if curBit == 0 {
for { for {
cursor++ cursor++
switch buf[cursor] { switch char(b, cursor) {
case '"': case '"':
cursor++ cursor++
return cursor, field, nil return cursor, field, nil
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
case nul: case nul: