Skip to content

Commit

Permalink
feat: new reflect impl for non-amd64 arch
Browse files Browse the repository at this point in the history
use `FRUGAL_NO_JIT` env var to enable the reflect impl on amd64
  • Loading branch information
xiaost committed Jul 8, 2024
1 parent 3c44689 commit b626e1b
Show file tree
Hide file tree
Showing 30 changed files with 3,482 additions and 256 deletions.
10 changes: 10 additions & 0 deletions frugal.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,31 @@ package frugal
import (
"github.com/cloudwego/frugal/internal/binary/decoder"
"github.com/cloudwego/frugal/internal/binary/encoder"
"github.com/cloudwego/frugal/internal/reflect"
"github.com/cloudwego/frugal/iov"
)

// EncodedSize measures the encoded size of val.
func EncodedSize(val interface{}) int {
if nojit {
return reflect.EncodedSize(val)
}
return encoder.EncodedSize(val)
}

// EncodeObject serializes val into buf with Thrift Binary Protocol, with optional Zero-Copy iov.BufferWriter.
// buf must be large enough to contain the entire serialization result.
func EncodeObject(buf []byte, mem iov.BufferWriter, val interface{}) (int, error) {
if nojit {
return reflect.Encode(buf, val) // TODO: impl iov.BufferWriter
}
return encoder.EncodeObject(buf, mem, val)
}

// DecodeObject deserializes buf into val with Thrift Binary Protocol.
func DecodeObject(buf []byte, val interface{}) (int, error) {
if nojit {
return reflect.Decode(buf, val)
}
return decoder.DecodeObject(buf, val)
}
28 changes: 28 additions & 0 deletions internal/reflect/backport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2024 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package reflect

import (
"reflect"
"unsafe"
)

// rvUnsafePointer backports rv.UnsafePointer for go1.17
// TODO: remove this func and use rv.UnsafePointer() directly when >= go1.18
func rvUnsafePointer(rv reflect.Value) unsafe.Pointer {
return unsafe.Pointer(rv.Pointer())
}
44 changes: 44 additions & 0 deletions internal/reflect/bitset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2024 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package reflect

import "sync"

type bitset struct {
data [1024]uint64 // 635536 bits for field id
}

var bitsetPool = sync.Pool{
New: func() interface{} {
return &bitset{}
},
}

func (s *bitset) set(i uint16) {
x, y := i>>8, i&7 // i/64, i%64
s.data[x] |= 1 << y
}

func (s *bitset) unset(i uint16) {
x, y := i>>8, i&7 // i/64, i%64
s.data[x] &= ^(1 << y)
}

func (s *bitset) test(i uint16) bool {
x, y := i>>8, i&7 // i/64, i%64
return (s.data[x] & (1 << y)) != 0
}
44 changes: 44 additions & 0 deletions internal/reflect/bitset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2024 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package reflect

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestBitset(t *testing.T) {
s := &bitset{}
for i := uint16(0); i < ^uint16(0); i++ {
if i%2 == 0 {
s.set(i)
}
if i%4 == 0 {
s.unset(i)
}
}
for i := uint16(0); i < ^uint16(0); i++ {
if i%4 == 0 {
require.False(t, s.test(i))
} else if i%2 == 0 {
require.True(t, s.test(i))
} else {
require.False(t, s.test(i))
}
}
}
Loading

0 comments on commit b626e1b

Please sign in to comment.