diff --git a/ast/api.go b/ast/api.go index 316a62a9d..4f58eb104 100644 --- a/ast/api.go +++ b/ast/api.go @@ -61,7 +61,7 @@ func quote(buf *[]byte, val string) { } // double buf size - *b = growslice(typeByte, *b, b.Cap*2) + *b = rt.GrowSlice(typeByte, *b, b.Cap*2) // ret is the complement of consumed input ret = ^ret // update input buffer diff --git a/ast/stubs_go120.go b/ast/stubs.go similarity index 89% rename from ast/stubs_go120.go rename to ast/stubs.go index 6f830529d..ae08f33d6 100644 --- a/ast/stubs_go120.go +++ b/ast/stubs.go @@ -1,5 +1,3 @@ -// +build go1.20 - /* * Copyright 2021 ByteDance Inc. * @@ -34,10 +32,6 @@ func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) //goland:noinspection GoUnusedParameter func unsafe_NewArray(typ *rt.GoType, n int) unsafe.Pointer -//go:linkname growslice reflect.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:nosplit func mem2ptr(s []byte) unsafe.Pointer { return (*rt.GoSlice)(unsafe.Pointer(&s)).Ptr diff --git a/ast/stubs_go115.go b/ast/stubs_go115.go deleted file mode 100644 index 37b9451f0..000000000 --- a/ast/stubs_go115.go +++ /dev/null @@ -1,55 +0,0 @@ -// +build !go1.20 - -/* - * 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 ast - -import ( - `unsafe` - `unicode/utf8` - - `github.com/bytedance/sonic/internal/rt` -) - -//go:noescape -//go:linkname memmove runtime.memmove -//goland:noinspection GoUnusedParameter -func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) - -//go:linkname unsafe_NewArray reflect.unsafe_NewArray -//goland:noinspection GoUnusedParameter -func unsafe_NewArray(typ *rt.GoType, n int) unsafe.Pointer - -//go:linkname growslice runtime.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - -//go:nosplit -func mem2ptr(s []byte) unsafe.Pointer { - return (*rt.GoSlice)(unsafe.Pointer(&s)).Ptr -} - -var ( - //go:linkname safeSet encoding/json.safeSet - safeSet [utf8.RuneSelf]bool - - //go:linkname hex encoding/json.hex - hex string -) - -//go:linkname unquoteBytes encoding/json.unquoteBytes -func unquoteBytes(s []byte) (t []byte, ok bool) \ No newline at end of file diff --git a/internal/decoder/assembler_regabi_amd64.go b/internal/decoder/assembler_regabi_amd64.go index 6c6fde91a..04babdf52 100644 --- a/internal/decoder/assembler_regabi_amd64.go +++ b/internal/decoder/assembler_regabi_amd64.go @@ -1146,7 +1146,7 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { var ( _F_memequal = jit.Func(memequal) _F_memmove = jit.Func(memmove) - _F_growslice = jit.Func(growslice) + _F_growslice = jit.Func(rt.GrowSlice) _F_makeslice = jit.Func(makeslice) _F_makemap_small = jit.Func(makemap_small) _F_mapassign_fast64 = jit.Func(mapassign_fast64) diff --git a/internal/decoder/assembler_stkabi_amd64.go b/internal/decoder/assembler_stkabi_amd64.go index 9e2acc23f..5dbe4cbf8 100644 --- a/internal/decoder/assembler_stkabi_amd64.go +++ b/internal/decoder/assembler_stkabi_amd64.go @@ -1148,7 +1148,7 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { var ( _F_memequal = jit.Func(memequal) _F_memmove = jit.Func(memmove) - _F_growslice = jit.Func(growslice) + _F_growslice = jit.Func(rt.GrowSlice) _F_makeslice = jit.Func(makeslice) _F_makemap_small = jit.Func(makemap_small) _F_mapassign_fast64 = jit.Func(mapassign_fast64) diff --git a/internal/decoder/stubs_go116.go b/internal/decoder/stubs_go116.go index b02eb2b8b..0253342c3 100644 --- a/internal/decoder/stubs_go116.go +++ b/internal/decoder/stubs_go116.go @@ -72,11 +72,6 @@ func mallocgc(size uintptr, typ *rt.GoType, needzero bool) unsafe.Pointer //goland:noinspection GoUnusedParameter func makeslice(et *rt.GoType, len int, cap int) unsafe.Pointer -//go:noescape -//go:linkname growslice runtime.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname makemap_small runtime.makemap_small func makemap_small() unsafe.Pointer diff --git a/internal/decoder/stubs_go120.go b/internal/decoder/stubs_go120.go index 870e25390..488369a56 100644 --- a/internal/decoder/stubs_go120.go +++ b/internal/decoder/stubs_go120.go @@ -72,11 +72,6 @@ func mallocgc(size uintptr, typ *rt.GoType, needzero bool) unsafe.Pointer //goland:noinspection GoUnusedParameter func makeslice(et *rt.GoType, len int, cap int) unsafe.Pointer -//go:noescape -//go:linkname growslice reflect.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname makemap_small runtime.makemap_small func makemap_small() unsafe.Pointer diff --git a/internal/encoder/assembler_regabi_amd64.go b/internal/encoder/assembler_regabi_amd64.go index 330b68817..4a372f0f0 100644 --- a/internal/encoder/assembler_regabi_amd64.go +++ b/internal/encoder/assembler_regabi_amd64.go @@ -592,7 +592,7 @@ func (self *_Assembler) call_marshaler_v(fn obj.Addr, it *rt.GoType, vt reflect. var ( _T_byte = jit.Type(byteType) - _F_growslice = jit.Func(growslice) + _F_growslice = jit.Func(rt.GrowSlice) ) // AX must saving n diff --git a/internal/encoder/assembler_stkabi_amd64.go b/internal/encoder/assembler_stkabi_amd64.go index 89dafc84e..c506ea607 100644 --- a/internal/encoder/assembler_stkabi_amd64.go +++ b/internal/encoder/assembler_stkabi_amd64.go @@ -574,7 +574,7 @@ func (self *_Assembler) call_marshaler_v(fn obj.Addr, it *rt.GoType, vt reflect. var ( _T_byte = jit.Type(byteType) - _F_growslice = jit.Func(growslice) + _F_growslice = jit.Func(rt.GrowSlice) ) func (self *_Assembler) more_space() { diff --git a/internal/encoder/mapiter.go b/internal/encoder/mapiter.go index 8a322b3af..63b04f9e4 100644 --- a/internal/encoder/mapiter.go +++ b/internal/encoder/mapiter.go @@ -176,7 +176,7 @@ func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, erro /* pre-allocate space if needed */ if m.Count > it.kv.Cap { - it.kv = growslice(iteratorPair, it.kv, m.Count) + it.kv = rt.GrowSlice(iteratorPair, it.kv, m.Count) } /* dump all the key-value pairs */ diff --git a/internal/encoder/primitives.go b/internal/encoder/primitives.go index 94f1c3dc6..51b2fbc29 100644 --- a/internal/encoder/primitives.go +++ b/internal/encoder/primitives.go @@ -59,7 +59,7 @@ func encodeString(buf *[]byte, val string) error { /* not enough space, grow the slice and try again */ sidx += ^nb - *pbuf = growslice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2) + *pbuf = rt.GrowSlice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2) } /* closing quote */ @@ -122,7 +122,7 @@ func htmlEscape(dst []byte, src []byte) []byte { /* grow dst if it is shorter */ if cap(dst) - len(dst) < len(src) + types.BufPaddingSize { cap := len(src) * 3 / 2 + types.BufPaddingSize - *dbuf = growslice(typeByte, *dbuf, cap) + *dbuf = rt.GrowSlice(typeByte, *dbuf, cap) } for sidx < sbuf.Len { @@ -140,7 +140,7 @@ func htmlEscape(dst []byte, src []byte) []byte { /* not enough space, grow the slice and try again */ sidx += ^nb - *dbuf = growslice(typeByte, *dbuf, dbuf.Cap * 2) + *dbuf = rt.GrowSlice(typeByte, *dbuf, dbuf.Cap * 2) } return dst } diff --git a/internal/encoder/stubs_go116.go b/internal/encoder/stubs_go116.go index 84c186fcf..80e4db913 100644 --- a/internal/encoder/stubs_go116.go +++ b/internal/encoder/stubs_go116.go @@ -34,10 +34,6 @@ var _subr__b64encode uintptr //goland:noinspection GoUnusedParameter func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) -//go:linkname growslice runtime.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname mapiternext runtime.mapiternext //goland:noinspection GoUnusedParameter func mapiternext(it *rt.GoMapIterator) diff --git a/internal/encoder/stubs_go117.go b/internal/encoder/stubs_go117.go index 6e56aca00..de38d0b3c 100644 --- a/internal/encoder/stubs_go117.go +++ b/internal/encoder/stubs_go117.go @@ -34,10 +34,6 @@ var _subr__b64encode uintptr //goland:noinspection GoUnusedParameter func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) -//go:linkname growslice runtime.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname mapiternext runtime.mapiternext //goland:noinspection GoUnusedParameter func mapiternext(it *rt.GoMapIterator) diff --git a/internal/encoder/stubs_go120.go b/internal/encoder/stubs_go120.go index 2b5e79bb6..8b6ac77de 100644 --- a/internal/encoder/stubs_go120.go +++ b/internal/encoder/stubs_go120.go @@ -34,10 +34,6 @@ var _subr__b64encode uintptr //goland:noinspection GoUnusedParameter func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) -//go:linkname growslice reflect.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname mapiternext runtime.mapiternext //goland:noinspection GoUnusedParameter func mapiternext(it *rt.GoMapIterator) diff --git a/internal/encoder/stubs_go121.go b/internal/encoder/stubs_go121.go index 89ae5d210..eff606b26 100644 --- a/internal/encoder/stubs_go121.go +++ b/internal/encoder/stubs_go121.go @@ -34,10 +34,6 @@ var _subr__b64encode uintptr //goland:noinspection GoUnusedParameter func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr) -//go:linkname growslice reflect.growslice -//goland:noinspection GoUnusedParameter -func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice - //go:linkname mapiternext runtime.mapiternext //goland:noinspection GoUnusedParameter func mapiternext(it *rt.GoMapIterator) diff --git a/internal/rt/fastmem.go b/internal/rt/fastmem.go index a68d98aff..af0468f40 100644 --- a/internal/rt/fastmem.go +++ b/internal/rt/fastmem.go @@ -122,4 +122,4 @@ func StrFrom(p unsafe.Pointer, n int64) (s string) { func NoEscape(p unsafe.Pointer) unsafe.Pointer { x := uintptr(p) return unsafe.Pointer(x ^ 0) -} \ No newline at end of file +} diff --git a/internal/rt/fastvalue.go b/internal/rt/fastvalue.go index 6657220ab..c4393763a 100644 --- a/internal/rt/fastvalue.go +++ b/internal/rt/fastvalue.go @@ -240,4 +240,4 @@ func GetFuncPC(fn interface{}) uintptr { panic("not a function") } return *(*uintptr)(ft.Value) -} \ No newline at end of file +} diff --git a/internal/rt/stackmap.go b/internal/rt/stackmap.go index 84ed9a95f..024912029 100644 --- a/internal/rt/stackmap.go +++ b/internal/rt/stackmap.go @@ -178,4 +178,4 @@ func (self *StackMapBuilder) AddFields(n int, ptr bool) { } else { self.b.AppendMany(n, 0) } -} \ No newline at end of file +} diff --git a/internal/rt/stub_go116.go b/internal/rt/stub_go116.go new file mode 100644 index 000000000..cd366b354 --- /dev/null +++ b/internal/rt/stub_go116.go @@ -0,0 +1,23 @@ +// +build go1.16,!go1.20 + +// 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 +// +// https://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 rt + +import _ "unsafe" + +//go:linkname GrowSlice runtime.growslice +//goland:noinspection GoUnusedParameter +func GrowSlice(et *GoType, old GoSlice, cap int) GoSlice \ No newline at end of file diff --git a/internal/rt/stub_go120.go b/internal/rt/stub_go120.go new file mode 100644 index 000000000..bc95fda73 --- /dev/null +++ b/internal/rt/stub_go120.go @@ -0,0 +1,29 @@ +// +build go1.20 + +// 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 +// +// https://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 rt + +import "unsafe" + +func GrowSlice(et *GoType, old GoSlice, cap int) GoSlice { + s := growslice(old.Ptr, cap, old.Cap, cap - old.Len, et) + s.Len = old.Len + return s +} + +//go:linkname growslice runtime.growslice +//goland:noinspection GoUnusedParameter +func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *GoType) GoSlice diff --git a/internal/rt/stub_test.go b/internal/rt/stub_test.go new file mode 100644 index 000000000..8f527539c --- /dev/null +++ b/internal/rt/stub_test.go @@ -0,0 +1,32 @@ +// 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 +// +// https://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 rt + +import ( + "testing" + "unsafe" +) + +func TestGrowSlic(t *testing.T) { + et := UnpackEface(byte(0)).Type + n := make([]byte, 1, 1024) + println("n len:", len(n), "cap:", cap(n)) + v := GrowSlice(et, *(*GoSlice)(unsafe.Pointer(&n)), 1025) + println("v len:", v.Len, "cap:", v.Cap) + // according to go growslice rule, the next cap must be at most 1.5x of old.Cap + if v.Cap > 1536 { + t.Fatal(v.Cap) + } +}