stackmap.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. // var (
  56. // _stackMapLock = sync.Mutex{}
  57. // _stackMapCache = make(map[*StackMap]struct{})
  58. // )
  59. type BitVec struct {
  60. N uintptr
  61. B unsafe.Pointer
  62. }
  63. func (self BitVec) Bit(i uintptr) byte {
  64. return (*(*byte)(unsafe.Pointer(uintptr(self.B) + i / 8)) >> (i % 8)) & 1
  65. }
  66. func (self BitVec) String() string {
  67. var i uintptr
  68. var v []string
  69. /* add each bit */
  70. for i = 0; i < self.N; i++ {
  71. v = append(v, fmt.Sprintf("%d", self.Bit(i)))
  72. }
  73. /* join them together */
  74. return fmt.Sprintf(
  75. "BitVec { %s }",
  76. strings.Join(v, ", "),
  77. )
  78. }
  79. type StackMap struct {
  80. N int32
  81. L int32
  82. B [1]byte
  83. }
  84. // func (self *StackMap) add() {
  85. // _stackMapLock.Lock()
  86. // _stackMapCache[self] = struct{}{}
  87. // _stackMapLock.Unlock()
  88. // }
  89. func (self *StackMap) Pin() uintptr {
  90. // self.add()
  91. return uintptr(unsafe.Pointer(self))
  92. }
  93. func (self *StackMap) Get(i int32) BitVec {
  94. return BitVec {
  95. N: uintptr(self.L),
  96. B: unsafe.Pointer(uintptr(unsafe.Pointer(&self.B)) + uintptr(i * ((self.L + 7) >> 3))),
  97. }
  98. }
  99. func (self *StackMap) String() string {
  100. sb := strings.Builder{}
  101. sb.WriteString("StackMap {")
  102. /* dump every stack map */
  103. for i := int32(0); i < self.N; i++ {
  104. sb.WriteRune('\n')
  105. sb.WriteString(" " + self.Get(i).String())
  106. }
  107. /* close the stackmap */
  108. sb.WriteString("\n}")
  109. return sb.String()
  110. }
  111. func (self *StackMap) MarshalBinary() ([]byte, error) {
  112. size := int(self.N) * int(self.L) + int(unsafe.Sizeof(self.L)) + int(unsafe.Sizeof(self.N))
  113. return BytesFrom(unsafe.Pointer(self), size, size), nil
  114. }
  115. var (
  116. byteType = UnpackEface(byte(0)).Type
  117. )
  118. const (
  119. _StackMapSize = unsafe.Sizeof(StackMap{})
  120. )
  121. //go:linkname mallocgc runtime.mallocgc
  122. //goland:noinspection GoUnusedParameter
  123. func mallocgc(nb uintptr, vt *GoType, zero bool) unsafe.Pointer
  124. type StackMapBuilder struct {
  125. b Bitmap
  126. }
  127. //go:nocheckptr
  128. func (self *StackMapBuilder) Build() (p *StackMap) {
  129. nb := len(self.b.B)
  130. bm := mallocgc(_StackMapSize + uintptr(nb) - 1, byteType, false)
  131. /* initialize as 1 bitmap of N bits */
  132. p = (*StackMap)(bm)
  133. p.N, p.L = 1, int32(self.b.N)
  134. copy(BytesFrom(unsafe.Pointer(&p.B), nb, nb), self.b.B)
  135. return
  136. }
  137. func (self *StackMapBuilder) AddField(ptr bool) {
  138. if ptr {
  139. self.b.Append(1)
  140. } else {
  141. self.b.Append(0)
  142. }
  143. }
  144. func (self *StackMapBuilder) AddFields(n int, ptr bool) {
  145. if ptr {
  146. self.b.AppendMany(n, 1)
  147. } else {
  148. self.b.AppendMany(n, 0)
  149. }
  150. }