debug_go117.go (4814B)
1 // +build go1.17,!go1.21 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 encoder 20 21 import ( 22 `fmt` 23 `os` 24 `runtime` 25 `strings` 26 `unsafe` 27 28 `github.com/bytedance/sonic/internal/jit` 29 `github.com/twitchyliquid64/golang-asm/obj` 30 ) 31 32 const _FP_debug = 128 33 34 var ( 35 debugSyncGC = os.Getenv("SONIC_SYNC_GC") != "" 36 debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == "" 37 debugCheckPtr = os.Getenv("SONIC_CHECK_POINTER") != "" 38 ) 39 40 var ( 41 _Instr_End = newInsOp(_OP_is_nil) 42 43 _F_gc = jit.Func(gc) 44 _F_println = jit.Func(println_wrapper) 45 _F_print = jit.Func(print) 46 ) 47 48 func (self *_Assembler) dsave(r ...obj.Addr) { 49 for i, v := range r { 50 if i > _FP_debug / 8 - 1 { 51 panic("too many registers to save") 52 } else { 53 self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs + _FP_saves + _FP_locals + int64(i) * 8)) 54 } 55 } 56 } 57 58 func (self *_Assembler) dload(r ...obj.Addr) { 59 for i, v := range r { 60 if i > _FP_debug / 8 - 1 { 61 panic("too many registers to load") 62 } else { 63 self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs + _FP_saves + _FP_locals + int64(i) * 8), v) 64 } 65 } 66 } 67 68 func println_wrapper(i int, op1 int, op2 int){ 69 println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2]) 70 } 71 72 func print(i int){ 73 println(i) 74 } 75 76 func gc() { 77 if !debugSyncGC { 78 return 79 } 80 runtime.GC() 81 // debug.FreeOSMemory() 82 } 83 84 func (self *_Assembler) dcall(fn obj.Addr) { 85 self.Emit("MOVQ", fn, _R10) // MOVQ ${fn}, R10 86 self.Rjmp("CALL", _R10) // CALL R10 87 } 88 89 func (self *_Assembler) debug_gc() { 90 if !debugSyncGC { 91 return 92 } 93 self.dsave(_REG_debug...) 94 self.dcall(_F_gc) 95 self.dload(_REG_debug...) 96 } 97 98 func (self *_Assembler) debug_instr(i int, v *_Instr) { 99 if debugSyncGC { 100 if i+1 == len(self.p) { 101 self.print_gc(i, v, &_Instr_End) 102 } else { 103 next := &(self.p[i+1]) 104 self.print_gc(i, v, next) 105 name := _OpNames[next.op()] 106 if strings.Contains(name, "save") { 107 return 108 } 109 } 110 // self.debug_gc() 111 } 112 } 113 114 //go:noescape 115 //go:linkname checkptrBase runtime.checkptrBase 116 func checkptrBase(p unsafe.Pointer) uintptr 117 118 //go:noescape 119 //go:linkname findObject runtime.findObject 120 func findObject(p, refBase, refOff uintptr) (base uintptr, s unsafe.Pointer, objIndex uintptr) 121 122 var ( 123 _F_checkptr = jit.Func(checkptr) 124 _F_printptr = jit.Func(printptr) 125 ) 126 127 var ( 128 _R10 = jit.Reg("R10") 129 ) 130 var _REG_debug = []obj.Addr { 131 jit.Reg("AX"), 132 jit.Reg("BX"), 133 jit.Reg("CX"), 134 jit.Reg("DX"), 135 jit.Reg("DI"), 136 jit.Reg("SI"), 137 jit.Reg("BP"), 138 jit.Reg("SP"), 139 jit.Reg("R8"), 140 jit.Reg("R9"), 141 jit.Reg("R10"), 142 jit.Reg("R11"), 143 jit.Reg("R12"), 144 jit.Reg("R13"), 145 jit.Reg("R14"), 146 jit.Reg("R15"), 147 } 148 149 func checkptr(ptr uintptr) { 150 if ptr == 0 { 151 return 152 } 153 fmt.Printf("pointer: %x\n", ptr) 154 f := checkptrBase(unsafe.Pointer(uintptr(ptr))) 155 if f == 0 { 156 fmt.Printf("! unknown-based pointer: %x\n", ptr) 157 } else if f == 1 { 158 fmt.Printf("! stack pointer: %x\n", ptr) 159 } else { 160 fmt.Printf("base: %x\n", f) 161 } 162 findobj(ptr) 163 } 164 165 func findobj(ptr uintptr) { 166 base, s, objIndex := findObject(ptr, 0, 0) 167 if s != nil && base == 0 { 168 fmt.Printf("! invalid pointer: %x\n", ptr) 169 } 170 fmt.Printf("objIndex: %d\n", objIndex) 171 } 172 173 func (self *_Assembler) check_ptr(ptr obj.Addr, lea bool) { 174 if !debugCheckPtr { 175 return 176 } 177 178 self.dsave(_REG_debug...) 179 if lea { 180 self.Emit("LEAQ", ptr, _R10) 181 } else { 182 self.Emit("MOVQ", ptr, _R10) 183 } 184 self.Emit("MOVQ", _R10, jit.Ptr(_SP, 0)) 185 self.dcall(_F_checkptr) 186 self.dload(_REG_debug...) 187 } 188 189 func printptr(i int, ptr uintptr) { 190 fmt.Printf("[%d] ptr: %x\n", i, ptr) 191 } 192 193 func (self *_Assembler) print_ptr(i int, ptr obj.Addr, lea bool) { 194 self.dsave(_REG_debug...) 195 if lea { 196 self.Emit("LEAQ", ptr, _R10) 197 } else { 198 self.Emit("MOVQ", ptr, _R10) 199 } 200 201 self.Emit("MOVQ", jit.Imm(int64(i)), _AX) 202 self.Emit("MOVQ", _R10, _BX) 203 self.dcall(_F_printptr) 204 self.dload(_REG_debug...) 205 }