Skip to content

Commit 4378967

Browse files
authored
fix(jit): no panic when I2I failure of NocopyWriter (#63)
1 parent a1e494c commit 4378967

6 files changed

Lines changed: 35 additions & 11 deletions

File tree

internal/jit/encoder/bucket.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ func (self _Bucket) String() string {
3333
return rt.StringFrom(self.p, int(self.v))
3434
}
3535

36-
var (
37-
bucketPool sync.Pool
38-
)
36+
var bucketPool sync.Pool
3937

4038
const (
4139
_BucketSize = unsafe.Sizeof(_Bucket{})

internal/jit/encoder/compiler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ func (self *Program) i64(op OpCode, iv int64) { self.ins(Instr{Op: op, Iv: iv})
136136
func (self *Program) str(op OpCode, sv string) {
137137
self.ins(Instr{Op: op, Iv: int64(len(sv)), Pr: rt.StringPtr(sv)})
138138
}
139+
139140
func (self *Program) rtt(op OpCode, vt reflect.Type) {
140141
self.ins(Instr{Op: op, Pr: unsafe.Pointer(rt.UnpackType(vt))})
141142
}

internal/jit/encoder/encoder.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ var (
4141
TypeCount uint64 = 0
4242
)
4343

44-
var (
45-
programCache = utils.CreateProgramCache()
46-
)
44+
var programCache = utils.CreateProgramCache()
4745

4846
func encode(vt *rt.GoType, buf unsafe.Pointer, len int, mem thrift.NocopyWriter, p unsafe.Pointer, rs *RuntimeState, st int) (int, error) {
4947
if enc, err := resolve(vt); err != nil {
@@ -65,9 +63,7 @@ func resolve(vt *rt.GoType) (Encoder, error) {
6563
/* record the cache miss, and compile the type */
6664
atomic.AddUint64(&MissCount, 1)
6765
val, err = programCache.Compute(vt, compile)
68-
69-
/* check for errors */
70-
if err != nil {
66+
/* check for errors */ if err != nil {
7167
return nil, err
7268
}
7369

@@ -118,6 +114,15 @@ func EncodeObject(buf []byte, mem thrift.NocopyWriter, val interface{}) (ret int
118114
efv := rt.UnpackEface(val)
119115
out := (*rt.GoSlice)(unsafe.Pointer(&buf))
120116

117+
if mem == nil {
118+
// starting from go1.22,
119+
// even though `mem`==nil, it may equal to (0x0, 0xc0000fe1e0).
120+
// it keeps original data pointer with itab = nil.
121+
// this would cause JIT panic when we only use data pointer to call its methods.
122+
// updating `mem` to nil, (0x0, 0xc0000fe1e0) -> (0x0, 0x0), is a quick fix for this case.
123+
mem = nil
124+
}
125+
121126
/* check for indirect types */
122127
if efv.Type.IsIndirect() {
123128
ret, err = encode(efv.Type, out.Ptr, out.Len, mem, efv.Value, rst, 0)

internal/jit/encoder/encoder_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/base64"
2222
"testing"
2323

24+
"github.com/cloudwego/gopkg/protocol/thrift"
2425
"github.com/davecgh/go-spew/spew"
2526
"github.com/stretchr/testify/require"
2627
)
@@ -64,6 +65,25 @@ func TestEncoder_Encode(t *testing.T) {
6465
println("Base64 Encoded Message:", base64.StdEncoding.EncodeToString(mm.Bytes()))
6566
}
6667

68+
func TestEncoder_Encode_NocopyWriter(t *testing.T) {
69+
p := &TranslatorTestStruct{
70+
H: make([]byte, 16<<10), // it should trigger NocopyWriter
71+
}
72+
sz := EncodedSize(p)
73+
require.Less(t, 16<<10, sz)
74+
75+
b := make([]byte, sz)
76+
77+
var w interface{} = &bytes.Buffer{}
78+
// for >=go1.22, nw != (0x0, 0x0)
79+
// it keeps data pointer with nil itab like (0x0,0xc0000fe1e0)
80+
nw, _ := w.(thrift.NocopyWriter)
81+
82+
ret, err := EncodeObject(b, nw, p)
83+
require.Equal(t, sz, ret)
84+
require.NoError(t, err)
85+
}
86+
6787
type StructSeekTest struct {
6888
H StructSeekTestSubStruct `frugal:"0,default,StructSeekTestSubStruct"`
6989
O []int8 `frugal:"1,default,list<i8>"`

internal/jit/encoder/optimizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func Optimize(p Program) Program {
216216
}
217217

218218
/* sort the blocks by entry point */
219-
sort.Slice(ctx.buf, func(i int, j int) bool {
219+
sort.Slice(ctx.buf, func(i, j int) bool {
220220
return ctx.buf[i].Src < ctx.buf[j].Src
221221
})
222222

internal/jit/encoder/translator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ func translate_OP_unique_int(p *hir.Builder) {
539539
}
540540
}
541541

542-
func translate_OP_unique_small(p *hir.Builder, nb int64, dv int64, ld func(hir.PointerRegister, int64, hir.GenericRegister) *hir.Ir) {
542+
func translate_OP_unique_small(p *hir.Builder, nb, dv int64, ld func(hir.PointerRegister, int64, hir.GenericRegister) *hir.Ir) {
543543
p.ADDPI(RS, BmOffset, ET)
544544
p.BZERO(nb, ET)
545545
p.LP(WP, 0, EP)

0 commit comments

Comments
 (0)