stackmap.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. package rt
  17. import (
  18. `fmt`
  19. `strings`
  20. `unsafe`
  21. )
  22. type Bitmap struct {
  23. N int
  24. B []byte
  25. }
  26. func (self *Bitmap) grow() {
  27. if self.N >= len(self.B) * 8 {
  28. self.B = append(self.B, 0)
  29. }
  30. }
  31. func (self *Bitmap) mark(i int, bv int) {
  32. if bv != 0 {
  33. self.B[i / 8] |= 1 << (i % 8)
  34. } else {
  35. self.B[i / 8] &^= 1 << (i % 8)
  36. }
  37. }
  38. func (self *Bitmap) Set(i int, bv int) {
  39. if i >= self.N {
  40. panic("bitmap: invalid bit position")
  41. } else {
  42. self.mark(i, bv)
  43. }
  44. }
  45. func (self *Bitmap) Append(bv int) {
  46. self.grow()
  47. self.mark(self.N, bv)
  48. self.N++
  49. }
  50. func (self *Bitmap) AppendMany(n int, bv int) {
  51. for i := 0; i < n; i++ {
  52. self.Append(bv)
  53. }
  54. }
  55. func (b *Bitmap) String() string {
  56. var buf strings.Builder
  57. for _, byteVal := range b.B {
  58. fmt.Fprintf(&buf, "%08b ", byteVal)
  59. }
  60. return fmt.Sprintf("Bits: %s(total %d bits, %d bytes)", buf.String(), b.N, len(b.B))
  61. }
  62. type BitVec struct {
  63. N uintptr
  64. B unsafe.Pointer
  65. }
  66. func (self BitVec) Bit(i uintptr) byte {
  67. return (*(*byte)(unsafe.Pointer(uintptr(self.B) + i / 8)) >> (i % 8)) & 1
  68. }
  69. func (self BitVec) String() string {
  70. var i uintptr
  71. var v []string
  72. /* add each bit */
  73. for i = 0; i < self.N; i++ {
  74. v = append(v, fmt.Sprintf("%d", self.Bit(i)))
  75. }
  76. /* join them together */
  77. return fmt.Sprintf(
  78. "BitVec { %s }",
  79. strings.Join(v, ", "),
  80. )
  81. }
  82. /*
  83. reference Golang 1.22.0 code:
  84. ```
  85. args := bitvec.New(int32(maxArgs / int64(types.PtrSize)))
  86. aoff := objw.Uint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
  87. aoff = objw.Uint32(&argsSymTmp, aoff, uint32(args.N)) // number of bits in each bitmap
  88. locals := bitvec.New(int32(maxLocals / int64(types.PtrSize)))
  89. loff := objw.Uint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
  90. loff = objw.Uint32(&liveSymTmp, loff, uint32(locals.N)) // number of bits in each bitmap
  91. for _, live := range lv.stackMaps {
  92. args.Clear()
  93. locals.Clear()
  94. lv.pointerMap(live, lv.vars, args, locals)
  95. aoff = objw.BitVec(&argsSymTmp, aoff, args)
  96. loff = objw.BitVec(&liveSymTmp, loff, locals)
  97. }
  98. ```
  99. */
  100. type StackMap struct {
  101. // number of bitmaps
  102. N int32
  103. // number of bits of each bitmap
  104. L int32
  105. // bitmap1, bitmap2, ... bitmapN
  106. B [1]byte
  107. }
  108. func (self *StackMap) Get(i int) BitVec {
  109. return BitVec {
  110. N: uintptr(self.L),
  111. B: unsafe.Pointer(uintptr(unsafe.Pointer(&self.B)) + uintptr(i * self.BitmapBytes())),
  112. }
  113. }
  114. func (self *StackMap) String() string {
  115. sb := strings.Builder{}
  116. sb.WriteString("StackMap {")
  117. /* dump every stack map */
  118. for i := 0; i < int(self.N); i++ {
  119. sb.WriteRune('\n')
  120. sb.WriteString(" " + self.Get(i).String())
  121. }
  122. /* close the stackmap */
  123. sb.WriteString("\n}")
  124. return sb.String()
  125. }
  126. func (self *StackMap) BitmapLen() int {
  127. return int(self.L)
  128. }
  129. func (self *StackMap) BitmapBytes() int {
  130. return int(self.L + 7) >> 3
  131. }
  132. func (self *StackMap) BitmapNums() int {
  133. return int(self.N)
  134. }
  135. func (self *StackMap) StackMapHeaderSize() int {
  136. return int(unsafe.Sizeof(self.L)) + int(unsafe.Sizeof(self.N))
  137. }
  138. func (self *StackMap) MarshalBinary() ([]byte, error) {
  139. size := self.BinaryLen()
  140. return BytesFrom(unsafe.Pointer(self), size, size), nil
  141. }
  142. func (self *StackMap) BinaryLen() int {
  143. return self.StackMapHeaderSize() + self.BitmapBytes() * self.BitmapNums()
  144. }
  145. var (
  146. byteType = UnpackEface(byte(0)).Type
  147. )
  148. const (
  149. _StackMapSize = unsafe.Sizeof(StackMap{})
  150. )
  151. //go:linkname mallocgc runtime.mallocgc
  152. //goland:noinspection GoUnusedParameter
  153. func mallocgc(nb uintptr, vt *GoType, zero bool) unsafe.Pointer
  154. type StackMapBuilder struct {
  155. b Bitmap
  156. }
  157. //go:nocheckptr
  158. func (self *StackMapBuilder) Build() (p *StackMap) {
  159. nb := len(self.b.B)
  160. allocatedSize := _StackMapSize + uintptr(nb) - 1
  161. bm := mallocgc(allocatedSize, byteType, false)
  162. /* initialize as 1 bitmap of N bits */
  163. p = (*StackMap)(bm)
  164. p.N, p.L = 1, int32(self.b.N)
  165. copy(BytesFrom(unsafe.Pointer(&p.B), nb, nb), self.b.B)
  166. /* assert length */
  167. if allocatedSize < uintptr(p.BinaryLen()) {
  168. panic(fmt.Sprintf("stackmap allocation too small: allocated %d, required %d", allocatedSize, p.BinaryLen()))
  169. }
  170. return
  171. }
  172. func (self *StackMapBuilder) AddField(ptr bool) {
  173. if ptr {
  174. self.b.Append(1)
  175. } else {
  176. self.b.Append(0)
  177. }
  178. }
  179. func (self *StackMapBuilder) AddFields(n int, ptr bool) {
  180. if ptr {
  181. self.b.AppendMany(n, 1)
  182. } else {
  183. self.b.AppendMany(n, 0)
  184. }
  185. }