github.com/tencent/goom@v1.0.1/internal/bytecode/memory/icache_arm64.go (about)

     1  package memory
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  
     7  	"github.com/tencent/goom/internal/logger"
     8  	"github.com/tencent/goom/internal/unexports"
     9  )
    10  
    11  // 指令生成相关
    12  // nolint
    13  const (
    14  	_0b1      = 1  // 0b1
    15  	_0b10     = 2  // 0b10
    16  	_0b11     = 3  // 0b11
    17  	_0b100101 = 37 // 0b100101
    18  	_X0       = 0  // X0 寄存器
    19  	_X1       = 1  // X1 寄存器
    20  )
    21  
    22  // cacheSize 需要失效的缓存长度, 一般情况不会超过这个数
    23  const cacheSize = 2 * 1024
    24  
    25  // clearFuncCache 缓存已经生成的函数
    26  var clearFuncCache func(uintptr)
    27  
    28  // ClearICache 清除指令缓存
    29  func ClearICache(addr uintptr) {
    30  	if clearFuncCache != nil {
    31  		clearFuncCache(addr)
    32  		return
    33  	}
    34  	if ok := initClearICacheFunc(); !ok {
    35  		return
    36  	}
    37  	clearFuncCache(addr)
    38  }
    39  
    40  // initClearICacheFunc 初始化 clearFuncCache
    41  func initClearICacheFunc() bool {
    42  	f, err := makeFunc()
    43  	if err != nil {
    44  		clearFuncCache = func(uintptr) {}
    45  		logger.Warningf("ClearICache failed: %v", err)
    46  		return false
    47  	}
    48  	clearFuncCache = f
    49  	return true
    50  }
    51  
    52  // makeFunc 构造 clearICacheIns 的函数实例
    53  func makeFunc() (func(uintptr), error) {
    54  	code := make([]byte, 0, 256)
    55  	code = append(code, insPadding...)
    56  	code = append(code, movAddr(_X1, uintptr(cacheSize))...)
    57  	code = append(code, clearICacheIns...)
    58  	code = append(code, clearICacheIns1...)
    59  	code = append(code, clearICacheIns2...)
    60  
    61  	var (
    62  		addr uintptr
    63  		err  error
    64  	)
    65  	if addr, err = WriteICacheFn(code); err != nil {
    66  		return nil, err
    67  	}
    68  	var f func(uintptr)
    69  	fn := unexports.NewFuncWithCodePtr(reflect.TypeOf(f), addr).Interface()
    70  	return (fn).(func(uintptr)), nil
    71  }
    72  
    73  // WriteICacheFn 写入 icache clear 函数数据
    74  //
    75  //go:linkname WriteICacheFn github.com/tencent/goom/internal/bytecode/stub.WriteICacheFn
    76  func WriteICacheFn([]byte) (uintptr, error)
    77  
    78  // movAddr 生成 mov x[?] [addr] 四个指令
    79  func movAddr(r uint32, addr uintptr) (value []byte) {
    80  	res := make([]byte, 0, 24)
    81  	d0d1 := addr & 0xFFFF
    82  	d2d3 := addr >> 16 & 0xFFFF
    83  	d4d5 := addr >> 32 & 0xFFFF
    84  	d6d7 := addr >> 48 & 0xFFFF
    85  
    86  	res = append(res, movImm(r, _0b10, 0, d0d1)...) // MOVZ x0, double[16:0]
    87  	res = append(res, movImm(r, _0b11, 1, d2d3)...) // MOVK x0, double[32:16]
    88  	res = append(res, movImm(r, _0b11, 2, d4d5)...) // MOVK x0, double[48:32]
    89  	res = append(res, movImm(r, _0b11, 3, d6d7)...) // MOVK x0, double[64:48]
    90  	return res
    91  }
    92  
    93  // movImm 动态生成 mov 指令
    94  // r 寄存器 X0~x27
    95  // opc 操作数, MOVZ/MOVK
    96  // shift 寄存器高低位段
    97  // val 值数据
    98  func movImm(r uint32, opc, shift int, val uintptr) []byte {
    99  	var m uint32 = r           // rd
   100  	m |= uint32(val) << 5      // imm16
   101  	m |= uint32(shift&3) << 21 // hw
   102  	m |= _0b100101 << 23       // const
   103  	m |= uint32(opc&0x3) << 29 // opc
   104  	m |= _0b1 << 31            // sf
   105  	res := make([]byte, 4)
   106  	*(*uint32)(unsafe.Pointer(&res[0])) = m
   107  	return res
   108  }