github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/asm_stubs_amd64_go121.go (about)

     1  // +build go1.21,!go1.23
     2  
     3  // Copyright 2023 CloudWeGo Authors
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package decoder
    18  
    19  import (
    20      `strconv`
    21      `unsafe`
    22  
    23      `github.com/bytedance/sonic/internal/jit`
    24      `github.com/twitchyliquid64/golang-asm/obj`
    25      `github.com/twitchyliquid64/golang-asm/obj/x86`
    26  )
    27  
    28  //go:linkname _runtime_writeBarrier runtime.writeBarrier
    29  var _runtime_writeBarrier uintptr
    30  
    31  //go:nosplit
    32  //go:linkname gcWriteBarrier2 runtime.gcWriteBarrier2
    33  func gcWriteBarrier2()
    34  
    35  // Notice: gcWriteBarrier must use R11 register!!
    36  var _R11 = _IC
    37  
    38  var (
    39      _V_writeBarrier = jit.Imm(int64(uintptr(unsafe.Pointer(&_runtime_writeBarrier))))
    40  
    41      _F_gcWriteBarrier2 = jit.Func(gcWriteBarrier2)
    42  )
    43  
    44  func (self *_Assembler) WritePtrAX(i int, rec obj.Addr, saveDI bool) {
    45      self.Emit("MOVQ", _V_writeBarrier, _R9)
    46      self.Emit("CMPL", jit.Ptr(_R9, 0), jit.Imm(0))
    47      self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
    48      if saveDI {
    49          self.save(_DI, _R11)
    50      } else {
    51          self.save(_R11)
    52      }
    53      self.Emit("MOVQ", _F_gcWriteBarrier2, _R11)  
    54      self.Rjmp("CALL", _R11)  
    55      self.Emit("MOVQ", _AX, jit.Ptr(_R11, 0))
    56      self.Emit("MOVQ", rec, _DI)
    57      self.Emit("MOVQ", _DI, jit.Ptr(_R11, 8))
    58      if saveDI {
    59          self.load(_DI, _R11)
    60      } else {
    61          self.load(_R11)
    62      }   
    63      self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
    64      self.Emit("MOVQ", _AX, rec)
    65  }
    66  
    67  func (self *_Assembler) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool, saveAX bool) {
    68      if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
    69          panic("rec contains AX!")
    70      }
    71      self.Emit("MOVQ", _V_writeBarrier, _R9)
    72      self.Emit("CMPL", jit.Ptr(_R9, 0), jit.Imm(0))
    73      self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
    74      if saveAX {
    75          self.save(_AX, _R11)
    76      } else {
    77          self.save(_R11)
    78      }
    79      self.Emit("MOVQ", _F_gcWriteBarrier2, _R11)  
    80      self.Rjmp("CALL", _R11)  
    81      self.Emit("MOVQ", ptr, jit.Ptr(_R11, 0))
    82      self.Emit("MOVQ", rec, _AX)
    83      self.Emit("MOVQ", _AX, jit.Ptr(_R11, 8))
    84      if saveAX {
    85          self.load(_AX, _R11)
    86      } else {
    87          self.load(_R11)
    88      }   
    89      self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
    90      self.Emit("MOVQ", ptr, rec)
    91  }
    92  
    93  func (self *_ValueDecoder) WritePtrAX(i int, rec obj.Addr, saveDI bool) {
    94      self.Emit("MOVQ", _V_writeBarrier, _R9)
    95      self.Emit("CMPL", jit.Ptr(_R9, 0), jit.Imm(0))
    96      self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
    97      if saveDI {
    98          self.save(_DI, _R11)
    99      } else {
   100          self.save(_R11)
   101      }
   102      self.Emit("MOVQ", _F_gcWriteBarrier2, _R11)  
   103      self.Rjmp("CALL", _R11)   
   104      self.Emit("MOVQ", _AX, jit.Ptr(_R11, 0))
   105      self.Emit("MOVQ", rec, _DI)
   106      self.Emit("MOVQ", _DI, jit.Ptr(_R11, 8))
   107      if saveDI {
   108          self.load(_DI, _R11)
   109      } else {
   110          self.load(_R11)
   111      }   
   112      self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
   113      self.Emit("MOVQ", _AX, rec)
   114  }
   115  
   116  func (self *_ValueDecoder) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool) {
   117      if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
   118          panic("rec contains AX!")
   119      }
   120      self.Emit("MOVQ", _V_writeBarrier, _AX)
   121      self.Emit("CMPL", jit.Ptr(_AX, 0), jit.Imm(0))
   122      self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
   123      self.save(_R11)
   124      self.Emit("MOVQ", _F_gcWriteBarrier2, _R11)  
   125      self.Rjmp("CALL", _R11)     
   126      self.Emit("MOVQ", ptr, jit.Ptr(_R11, 0))
   127      self.Emit("MOVQ", rec, _AX)
   128      self.Emit("MOVQ", _AX, jit.Ptr(_R11, 8))
   129      self.load(_R11)  
   130      self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
   131      self.Emit("MOVQ", ptr, rec)
   132  }