github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/stubs.go (about) 1 // MIT License 2 // 3 // Copyright (c) 2021 Xiantu Li 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 package json 24 25 import ( 26 "unsafe" 27 ) 28 29 //go:linkname strhash runtime.strhash 30 func strhash(p unsafe.Pointer, h uintptr) uintptr 31 32 //go:linkname memequal runtime.memequal 33 func memequal(a, b unsafe.Pointer, size uintptr) bool 34 35 //go:linkname reflect_mapassign_faststr reflect.mapassign_faststr 36 func reflect_mapassign_faststr(t *maptype, h *hmap, key string, elem unsafe.Pointer) 37 38 //go:linkname reflect_typedmemmove reflect.typedmemmove 39 func reflect_typedmemmove(typ *GoType, dst, src unsafe.Pointer) 40 41 //go:linkname unsafe_New reflect.unsafe_New 42 func unsafe_New(*GoType) unsafe.Pointer 43 44 //go:linkname unsafe_NewArray reflect.unsafe_NewArray 45 func unsafe_NewArray(typ *GoType, n int) unsafe.Pointer 46 47 //go:linkname reflect_ifaceE2I runtime.reflect_ifaceE2I 48 func reflect_ifaceE2I(inter *interfacetype, e GoEface, dst *GoIface) 49 50 //go:linkname roundupsize runtime.roundupsize 51 func roundupsize(size uintptr) uintptr 52 53 // //go:linkname mapassign runtime.makemap 54 // func makemap(t *GoType, h unsafe.Pointer, k unsafe.Pointer) unsafe.Pointer 55 56 //go:linkname bucketShift runtime.bucketShift 57 func bucketShift(b uint8) uintptr 58 59 //go:linkname overLoadFactor runtime.overLoadFactor 60 func overLoadFactor(count int, B uint8) bool 61 62 //go:linkname reflect_memclrNoHeapPointers reflect.memclrNoHeapPointers 63 func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) 64 65 //go:linkname memclrHasPointers runtime.memclrHasPointers 66 func memclrHasPointers(ptr unsafe.Pointer, n uintptr) 67 68 //go:linkname makeBucketArray runtime.makeBucketArray 69 func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets unsafe.Pointer, nextOverflow *bmap) 70 71 /* 72 func makemap(t *GoType, hint int, h *hmap) *hmap { 73 if h == nil { 74 h = new(hmap) 75 } 76 h.hash0 = fastrand() 77 78 // Find the size parameter B which will hold the requested # of elements. 79 // For hint < 0 overLoadFactor returns false since hint < bucketCnt. 80 B := uint8(0) 81 for overLoadFactor(hint, B) { 82 B++ 83 } 84 h.B = B 85 86 // allocate initial hash table 87 // if B == 0, the buckets field is allocated lazily later (in mapassign) 88 // If hint is large zeroing this memory could take a while. 89 if h.B != 0 { 90 var nextOverflow *bmap 91 h.buckets, nextOverflow = makeBucketArray(t, h.B, nil) 92 if nextOverflow != nil { 93 h.extra = new(mapextra) 94 h.extra.nextOverflow = nextOverflow 95 } 96 } 97 98 return h 99 }//*/ 100 101 // A header for a Go map. 102 type hmap struct { 103 // Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go. 104 // Make sure this stays in sync with the compiler's definition. 105 count int // # live cells == size of map. Must be first (used by len() builtin) 106 flags uint8 107 B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items) 108 noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details 109 hash0 uint32 // hash seed 110 111 buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0. 112 oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing 113 nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated) 114 115 extra *mapextra // optional fields 116 } 117 118 // A bucket for a Go map. 119 type bmap struct { 120 tophash [8]uint8 121 } 122 123 const ptrSize = 4 << (^uintptr(0) >> 63) 124 125 func (b *bmap) setoverflow(t *maptype, ovf *bmap) { 126 *(**bmap)(pointerOffset(unsafe.Pointer(b), uintptr(t.bucketsize)-ptrSize)) = ovf 127 } 128 129 type maptype struct { 130 typ GoType 131 key *GoType 132 elem *GoType 133 bucket *GoType // internal type representing a hash bucket 134 // function for hashing keys (ptr to key, seed) -> hash 135 hasher func(unsafe.Pointer, uintptr) uintptr 136 keysize uint8 // size of key slot 137 elemsize uint8 // size of elem slot 138 bucketsize uint16 // size of bucket 139 flags uint32 140 } 141 142 type mapextra struct { 143 // If both key and elem do not contain pointers and are inline, then we mark bucket 144 // type as containing no pointers. This avoids scanning such maps. 145 // However, bmap.overflow is a pointer. In order to keep overflow buckets 146 // alive, we store pointers to all overflow buckets in hmap.extra.overflow and hmap.extra.oldoverflow. 147 // overflow and oldoverflow are only used if key and elem do not contain pointers. 148 // overflow contains overflow buckets for hmap.buckets. 149 // oldoverflow contains overflow buckets for hmap.oldbuckets. 150 // The indirection allows to store a pointer to the slice in hiter. 151 overflow *[]*bmap 152 oldoverflow *[]*bmap 153 154 // nextOverflow holds a pointer to a free overflow bucket. 155 nextOverflow *bmap 156 } 157 158 // 通过 pool 集中分配大内存,再切分给 map 使用,边多次神池 map 内存 159 func makeMapEface(hint int) (m map[string]interface{}) { 160 if hint > 18 { 161 m = make(map[string]interface{}, hint) 162 } else { 163 // m = make(map[string]interface{}) 164 h := imapPool.Get() 165 h.hash0 = hmapimp.hash0 166 m = *(*map[string]interface{})(unsafe.Pointer(&h)) 167 B := uint8(0) 168 for overLoadFactor(hint, B) { 169 B++ 170 } 171 h.B = B 172 base := bucketShift(B) 173 nbuckets := base 174 if B >= 4 { 175 nbuckets += bucketShift(B - 4) 176 sz := mapGoType.bucket.Size * nbuckets 177 up := roundupsize(sz) 178 if up != sz { 179 nbuckets = up / mapGoType.bucket.Size 180 } 181 } 182 bs := poolMapArrayInterface.Get().(*[]byte) 183 l := nbuckets * mapGoType.bucket.Size 184 if len(*bs) < int(l) { 185 bs = poolMapArrayInterface.New().(*[]byte) 186 } 187 h.buckets = unsafe.Pointer(&(*bs)[0]) 188 if len(*bs) > int(l) { 189 *bs = (*bs)[l:] 190 poolMapArrayInterface.Put(bs) 191 } 192 193 var nextOverflow *bmap 194 // h.buckets, nextOverflow = makeBucketArray(mapGoType, h.B, h.buckets) 195 if base != nbuckets { 196 nextOverflow = (*bmap)(pointerOffset(h.buckets, base*uintptr(mapGoType.bucketsize))) 197 last := (*bmap)(pointerOffset(h.buckets, (nbuckets-1)*uintptr(mapGoType.bucketsize))) 198 last.setoverflow(mapGoType, (*bmap)(h.buckets)) 199 } 200 if nextOverflow != nil { 201 h.extra = new(mapextra) 202 h.extra.nextOverflow = nextOverflow 203 } 204 } 205 return 206 }