github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/encoder/debug_go117.go (about)

     1  //go:build go1.17 && !go1.22
     2  // +build go1.17,!go1.22
     3  
     4  /*
     5   * Copyright 2021 ByteDance Inc.
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package encoder
    21  
    22  import (
    23  	"fmt"
    24  	"os"
    25  	"runtime"
    26  	"strings"
    27  	"unsafe"
    28  
    29  	"github.com/goshafaq/sonic/internal/jit"
    30  	"github.com/twitchyliquid64/golang-asm/obj"
    31  )
    32  
    33  const _FP_debug = 128
    34  
    35  var (
    36  	debugSyncGC   = os.Getenv("SONIC_SYNC_GC") != ""
    37  	debugAsyncGC  = os.Getenv("SONIC_NO_ASYNC_GC") == ""
    38  	debugCheckPtr = os.Getenv("SONIC_CHECK_POINTER") != ""
    39  )
    40  
    41  var (
    42  	_Instr_End = newInsOp(_OP_is_nil)
    43  
    44  	_F_gc      = jit.Func(gc)
    45  	_F_println = jit.Func(println_wrapper)
    46  	_F_print   = jit.Func(print)
    47  )
    48  
    49  func (self *_Assembler) dsave(r ...obj.Addr) {
    50  	for i, v := range r {
    51  		if i > _FP_debug/8-1 {
    52  			panic("too many registers to save")
    53  		} else {
    54  			self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8))
    55  		}
    56  	}
    57  }
    58  
    59  func (self *_Assembler) dload(r ...obj.Addr) {
    60  	for i, v := range r {
    61  		if i > _FP_debug/8-1 {
    62  			panic("too many registers to load")
    63  		} else {
    64  			self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8), v)
    65  		}
    66  	}
    67  }
    68  
    69  func println_wrapper(i int, op1 int, op2 int) {
    70  	println(i, " Intrs ", op1, _OpNames[op1], "next: ", op2, _OpNames[op2])
    71  }
    72  
    73  func print(i int) {
    74  	println(i)
    75  }
    76  
    77  func gc() {
    78  	if !debugSyncGC {
    79  		return
    80  	}
    81  	runtime.GC()
    82  	// debug.FreeOSMemory()
    83  }
    84  
    85  func (self *_Assembler) dcall(fn obj.Addr) {
    86  	self.Emit("MOVQ", fn, _R10) // MOVQ ${fn}, R10
    87  	self.Rjmp("CALL", _R10)     // CALL R10
    88  }
    89  
    90  func (self *_Assembler) debug_gc() {
    91  	if !debugSyncGC {
    92  		return
    93  	}
    94  	self.dsave(_REG_debug...)
    95  	self.dcall(_F_gc)
    96  	self.dload(_REG_debug...)
    97  }
    98  
    99  func (self *_Assembler) debug_instr(i int, v *_Instr) {
   100  	if debugSyncGC {
   101  		if i+1 == len(self.p) {
   102  			self.print_gc(i, v, &_Instr_End)
   103  		} else {
   104  			next := &(self.p[i+1])
   105  			self.print_gc(i, v, next)
   106  			name := _OpNames[next.op()]
   107  			if strings.Contains(name, "save") {
   108  				return
   109  			}
   110  		}
   111  		// self.debug_gc()
   112  	}
   113  }
   114  
   115  //go:noescape
   116  //go:linkname checkptrBase runtime.checkptrBase
   117  func checkptrBase(p unsafe.Pointer) uintptr
   118  
   119  //go:noescape
   120  //go:linkname findObject runtime.findObject
   121  func findObject(p, refBase, refOff uintptr) (base uintptr, s unsafe.Pointer, objIndex uintptr)
   122  
   123  var (
   124  	_F_checkptr = jit.Func(checkptr)
   125  	_F_printptr = jit.Func(printptr)
   126  )
   127  
   128  var (
   129  	_R10 = jit.Reg("R10")
   130  )
   131  var _REG_debug = []obj.Addr{
   132  	jit.Reg("AX"),
   133  	jit.Reg("BX"),
   134  	jit.Reg("CX"),
   135  	jit.Reg("DX"),
   136  	jit.Reg("DI"),
   137  	jit.Reg("SI"),
   138  	jit.Reg("BP"),
   139  	jit.Reg("SP"),
   140  	jit.Reg("R8"),
   141  	jit.Reg("R9"),
   142  	jit.Reg("R10"),
   143  	jit.Reg("R11"),
   144  	jit.Reg("R12"),
   145  	jit.Reg("R13"),
   146  	jit.Reg("R14"),
   147  	jit.Reg("R15"),
   148  }
   149  
   150  func checkptr(ptr uintptr) {
   151  	if ptr == 0 {
   152  		return
   153  	}
   154  	fmt.Printf("pointer: %x\n", ptr)
   155  	f := checkptrBase(unsafe.Pointer(uintptr(ptr)))
   156  	if f == 0 {
   157  		fmt.Printf("! unknown-based pointer: %x\n", ptr)
   158  	} else if f == 1 {
   159  		fmt.Printf("! stack pointer: %x\n", ptr)
   160  	} else {
   161  		fmt.Printf("base: %x\n", f)
   162  	}
   163  	findobj(ptr)
   164  }
   165  
   166  func findobj(ptr uintptr) {
   167  	base, s, objIndex := findObject(ptr, 0, 0)
   168  	if s != nil && base == 0 {
   169  		fmt.Printf("! invalid pointer: %x\n", ptr)
   170  	}
   171  	fmt.Printf("objIndex: %d\n", objIndex)
   172  }
   173  
   174  func (self *_Assembler) check_ptr(ptr obj.Addr, lea bool) {
   175  	if !debugCheckPtr {
   176  		return
   177  	}
   178  
   179  	self.dsave(_REG_debug...)
   180  	if lea {
   181  		self.Emit("LEAQ", ptr, _R10)
   182  	} else {
   183  		self.Emit("MOVQ", ptr, _R10)
   184  	}
   185  	self.Emit("MOVQ", _R10, jit.Ptr(_SP, 0))
   186  	self.dcall(_F_checkptr)
   187  	self.dload(_REG_debug...)
   188  }
   189  
   190  func printptr(i int, ptr uintptr) {
   191  	fmt.Printf("[%d] ptr: %x\n", i, ptr)
   192  }
   193  
   194  func (self *_Assembler) print_ptr(i int, ptr obj.Addr, lea bool) {
   195  	self.dsave(_REG_debug...)
   196  	if lea {
   197  		self.Emit("LEAQ", ptr, _R10)
   198  	} else {
   199  		self.Emit("MOVQ", ptr, _R10)
   200  	}
   201  
   202  	self.Emit("MOVQ", jit.Imm(int64(i)), _AX)
   203  	self.Emit("MOVQ", _R10, _BX)
   204  	self.dcall(_F_printptr)
   205  	self.dload(_REG_debug...)
   206  }