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  }