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