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  }