1 // +build go1.21,!go1.25
2 3 /*
4 * Copyright 2021 ByteDance Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 19 package rt
20 21 import (
22 `sync/atomic`
23 `unsafe`
24 25 `golang.org/x/arch/x86/x86asm`
26 )
27 28 //go:linkname GcWriteBarrier2 runtime.gcWriteBarrier2
29 func GcWriteBarrier2()
30 31 //go:linkname RuntimeWriteBarrier runtime.writeBarrier
32 var RuntimeWriteBarrier uintptr
33 34 const (
35 _MaxInstr = 15
36 )
37 38 func isvar(arg x86asm.Arg) bool {
39 v, ok := arg.(x86asm.Mem)
40 return ok && v.Base == x86asm.RIP
41 }
42 43 func iszero(arg x86asm.Arg) bool {
44 v, ok := arg.(x86asm.Imm)
45 return ok && v == 0
46 }
47 48 func GcwbAddr() uintptr {
49 var err error
50 var off uintptr
51 var ins x86asm.Inst
52 53 /* get the function address */
54 pc := uintptr(0)
55 fp := FuncAddr(atomic.StorePointer)
56 57 /* search within the first 16 instructions */
58 for i := 0; i < 16; i++ {
59 mem := unsafe.Pointer(uintptr(fp) + pc)
60 buf := BytesFrom(mem, _MaxInstr, _MaxInstr)
61 62 /* disassemble the instruction */
63 if ins, err = x86asm.Decode(buf, 64); err != nil {
64 panic("gcwbaddr: " + err.Error())
65 }
66 67 /* check for a byte comparison with zero */
68 if ins.Op == x86asm.CMP && ins.MemBytes == 1 && isvar(ins.Args[0]) && iszero(ins.Args[1]) {
69 off = pc + uintptr(ins.Len) + uintptr(ins.Args[0].(x86asm.Mem).Disp)
70 break
71 }
72 73 /* move to next instruction */
74 nb := ins.Len
75 pc += uintptr(nb)
76 }
77 78 /* check for address */
79 if off == 0 {
80 panic("gcwbaddr: could not locate the variable `writeBarrier`")
81 } else {
82 return uintptr(fp) + off
83 }
84 }
85 86