fastmem.go raw
1 /*
2 * Copyright 2021 ByteDance Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package rt
18
19 import (
20 "reflect"
21 "unsafe"
22
23 "github.com/bytedance/sonic/option"
24 )
25
26 //go:nosplit
27 func Get16(v []byte) int16 {
28 return *(*int16)((*GoSlice)(unsafe.Pointer(&v)).Ptr)
29 }
30
31 //go:nosplit
32 func Get32(v []byte) int32 {
33 return *(*int32)((*GoSlice)(unsafe.Pointer(&v)).Ptr)
34 }
35
36 //go:nosplit
37 func Get64(v []byte) int64 {
38 return *(*int64)((*GoSlice)(unsafe.Pointer(&v)).Ptr)
39 }
40
41 //go:nosplit
42 func Mem2Str(v []byte) (s string) {
43 (*GoString)(unsafe.Pointer(&s)).Len = (*GoSlice)(unsafe.Pointer(&v)).Len
44 (*GoString)(unsafe.Pointer(&s)).Ptr = (*GoSlice)(unsafe.Pointer(&v)).Ptr
45 return
46 }
47
48 //go:nosplit
49 func Str2Mem(s string) (v []byte) {
50 (*GoSlice)(unsafe.Pointer(&v)).Cap = (*GoString)(unsafe.Pointer(&s)).Len
51 (*GoSlice)(unsafe.Pointer(&v)).Len = (*GoString)(unsafe.Pointer(&s)).Len
52 (*GoSlice)(unsafe.Pointer(&v)).Ptr = (*GoString)(unsafe.Pointer(&s)).Ptr
53 return
54 }
55
56 func BytesFrom(p unsafe.Pointer, n int, c int) (r []byte) {
57 (*GoSlice)(unsafe.Pointer(&r)).Ptr = p
58 (*GoSlice)(unsafe.Pointer(&r)).Len = n
59 (*GoSlice)(unsafe.Pointer(&r)).Cap = c
60 return
61 }
62
63 func FuncAddr(f interface{}) unsafe.Pointer {
64 if vv := UnpackEface(f); vv.Type.Kind() != reflect.Func {
65 panic("f is not a function")
66 } else {
67 return *(*unsafe.Pointer)(vv.Value)
68 }
69 }
70
71 //go:nocheckptr
72 func IndexChar(src string, index int) unsafe.Pointer {
73 return unsafe.Pointer(uintptr((*GoString)(unsafe.Pointer(&src)).Ptr) + uintptr(index))
74 }
75
76 //go:nocheckptr
77 func IndexByte(ptr []byte, index int) unsafe.Pointer {
78 return unsafe.Pointer(uintptr((*GoSlice)(unsafe.Pointer(&ptr)).Ptr) + uintptr(index))
79 }
80
81 func GuardSlice(buf *[]byte, n int) {
82 c := cap(*buf)
83 l := len(*buf)
84 if c-l < n {
85 c = c>>1 + n + l
86 if c < 32 {
87 c = 32
88 }
89 tmp := make([]byte, l, c)
90 copy(tmp, *buf)
91 *buf = tmp
92 }
93 }
94
95 func GuardSlice2(buf []byte, n int) []byte {
96 c := cap(buf)
97 l := len(buf)
98 if c-l < n {
99 c = c>>1 + n + l
100 if c < 32 {
101 c = 32
102 }
103 tmp := make([]byte, l, c)
104 copy(tmp, buf)
105 buf = tmp
106 }
107 return buf
108 }
109
110 //go:nosplit
111 func Ptr2SlicePtr(s unsafe.Pointer, l int, c int) unsafe.Pointer {
112 slice := &GoSlice{
113 Ptr: s,
114 Len: l,
115 Cap: c,
116 }
117 return unsafe.Pointer(slice)
118 }
119
120 //go:nosplit
121 func StrPtr(s string) unsafe.Pointer {
122 return (*GoString)(unsafe.Pointer(&s)).Ptr
123 }
124
125 //go:nosplit
126 func StrFrom(p unsafe.Pointer, n int64) (s string) {
127 (*GoString)(unsafe.Pointer(&s)).Ptr = p
128 (*GoString)(unsafe.Pointer(&s)).Len = int(n)
129 return
130 }
131
132 // NoEscape hides a pointer from escape analysis. NoEscape is
133 // the identity function but escape analysis doesn't think the
134 // output depends on the input. NoEscape is inlined and currently
135 // compiles down to zero instructions.
136 // USE CAREFULLY!
137 //go:nosplit
138 //goland:noinspection GoVetUnsafePointer
139 func NoEscape(p unsafe.Pointer) unsafe.Pointer {
140 x := uintptr(p)
141 return unsafe.Pointer(x ^ 0)
142 }
143
144 //go:nosplit
145 func MoreStack(size uintptr)
146
147 //go:nosplit
148 func Add(ptr unsafe.Pointer, off uintptr) unsafe.Pointer {
149 return unsafe.Pointer(uintptr(ptr) + off)
150 }
151
152 // CanSizeResue
153 func CanSizeResue(cap int) bool {
154 return cap <= int(option.LimitBufferSize)
155 }
156