github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/rt/stackmap.go (about) 1 /** 2 * Copyright 2023 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 "fmt" 21 "strings" 22 "unsafe" 23 ) 24 25 type Bitmap struct { 26 N int 27 B []byte 28 } 29 30 func (self *Bitmap) grow() { 31 if self.N >= len(self.B)*8 { 32 self.B = append(self.B, 0) 33 } 34 } 35 36 func (self *Bitmap) mark(i int, bv int) { 37 if bv != 0 { 38 self.B[i/8] |= 1 << (i % 8) 39 } else { 40 self.B[i/8] &^= 1 << (i % 8) 41 } 42 } 43 44 func (self *Bitmap) Set(i int, bv int) { 45 if i >= self.N { 46 panic("bitmap: invalid bit position") 47 } else { 48 self.mark(i, bv) 49 } 50 } 51 52 func (self *Bitmap) Append(bv int) { 53 self.grow() 54 self.mark(self.N, bv) 55 self.N++ 56 } 57 58 func (self *Bitmap) AppendMany(n int, bv int) { 59 for i := 0; i < n; i++ { 60 self.Append(bv) 61 } 62 } 63 64 // var ( 65 // _stackMapLock = sync.Mutex{} 66 // _stackMapCache = make(map[*StackMap]struct{}) 67 // ) 68 69 type BitVec struct { 70 N uintptr 71 B unsafe.Pointer 72 } 73 74 func (self BitVec) Bit(i uintptr) byte { 75 return (*(*byte)(unsafe.Pointer(uintptr(self.B) + i/8)) >> (i % 8)) & 1 76 } 77 78 func (self BitVec) String() string { 79 var i uintptr 80 var v []string 81 82 /* add each bit */ 83 for i = 0; i < self.N; i++ { 84 v = append(v, fmt.Sprintf("%d", self.Bit(i))) 85 } 86 87 /* join them together */ 88 return fmt.Sprintf( 89 "BitVec { %s }", 90 strings.Join(v, ", "), 91 ) 92 } 93 94 type StackMap struct { 95 N int32 96 L int32 97 B [1]byte 98 } 99 100 // func (self *StackMap) add() { 101 // _stackMapLock.Lock() 102 // _stackMapCache[self] = struct{}{} 103 // _stackMapLock.Unlock() 104 // } 105 106 func (self *StackMap) Pin() uintptr { 107 // self.add() 108 return uintptr(unsafe.Pointer(self)) 109 } 110 111 func (self *StackMap) Get(i int32) BitVec { 112 return BitVec{ 113 N: uintptr(self.L), 114 B: unsafe.Pointer(uintptr(unsafe.Pointer(&self.B)) + uintptr(i*((self.L+7)>>3))), 115 } 116 } 117 118 func (self *StackMap) String() string { 119 sb := strings.Builder{} 120 sb.WriteString("StackMap {") 121 122 /* dump every stack map */ 123 for i := int32(0); i < self.N; i++ { 124 sb.WriteRune('\n') 125 sb.WriteString(" " + self.Get(i).String()) 126 } 127 128 /* close the stackmap */ 129 sb.WriteString("\n}") 130 return sb.String() 131 } 132 133 func (self *StackMap) MarshalBinary() ([]byte, error) { 134 size := int(self.N)*int(self.L) + int(unsafe.Sizeof(self.L)) + int(unsafe.Sizeof(self.N)) 135 return BytesFrom(unsafe.Pointer(self), size, size), nil 136 } 137 138 var ( 139 byteType = UnpackEface(byte(0)).Type 140 ) 141 142 const ( 143 _StackMapSize = unsafe.Sizeof(StackMap{}) 144 ) 145 146 //go:linkname mallocgc runtime.mallocgc 147 //goland:noinspection GoUnusedParameter 148 func mallocgc(nb uintptr, vt *GoType, zero bool) unsafe.Pointer 149 150 type StackMapBuilder struct { 151 b Bitmap 152 } 153 154 //go:nocheckptr 155 func (self *StackMapBuilder) Build() (p *StackMap) { 156 nb := len(self.b.B) 157 bm := mallocgc(_StackMapSize+uintptr(nb)-1, byteType, false) 158 159 /* initialize as 1 bitmap of N bits */ 160 p = (*StackMap)(bm) 161 p.N, p.L = 1, int32(self.b.N) 162 copy(BytesFrom(unsafe.Pointer(&p.B), nb, nb), self.b.B) 163 return 164 } 165 166 func (self *StackMapBuilder) AddField(ptr bool) { 167 if ptr { 168 self.b.Append(1) 169 } else { 170 self.b.Append(0) 171 } 172 } 173 174 func (self *StackMapBuilder) AddFields(n int, ptr bool) { 175 if ptr { 176 self.b.AppendMany(n, 1) 177 } else { 178 self.b.AppendMany(n, 0) 179 } 180 }