github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/decoder/asm_stubs_amd64_go116.go (about) 1 //go:build go1.16 && !go1.17 2 // +build go1.16,!go1.17 3 4 // Copyright 2023 CloudWeGo Authors 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 package decoder 19 20 import ( 21 "strconv" 22 _ "unsafe" 23 24 "github.com/goshafaq/sonic/internal/jit" 25 "github.com/goshafaq/sonic/internal/rt" 26 "github.com/twitchyliquid64/golang-asm/obj" 27 "github.com/twitchyliquid64/golang-asm/obj/x86" 28 ) 29 30 var _runtime_writeBarrier uintptr = rt.GcwbAddr() 31 32 //go:linkname gcWriteBarrierAX runtime.gcWriteBarrier 33 func gcWriteBarrierAX() 34 35 var ( 36 _V_writeBarrier = jit.Imm(int64(_runtime_writeBarrier)) 37 38 _F_gcWriteBarrierAX = jit.Func(gcWriteBarrierAX) 39 ) 40 41 func (self *_Assembler) WritePtrAX(i int, rec obj.Addr, saveDI bool) { 42 self.Emit("MOVQ", _V_writeBarrier, _R10) 43 self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0)) 44 self.Sjmp("JE", "_no_writeBarrier"+strconv.Itoa(i)+"_{n}") 45 if saveDI { 46 self.save(_DI) 47 } 48 self.Emit("LEAQ", rec, _DI) 49 self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX 50 self.Rjmp("CALL", _R10) 51 if saveDI { 52 self.load(_DI) 53 } 54 self.Sjmp("JMP", "_end_writeBarrier"+strconv.Itoa(i)+"_{n}") 55 self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}") 56 self.Emit("MOVQ", _AX, rec) 57 self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}") 58 } 59 60 func (self *_Assembler) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool, saveAX bool) { 61 if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX { 62 panic("rec contains AX!") 63 } 64 self.Emit("MOVQ", _V_writeBarrier, _R10) 65 self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0)) 66 self.Sjmp("JE", "_no_writeBarrier"+strconv.Itoa(i)+"_{n}") 67 if saveAX { 68 self.Emit("XCHGQ", ptr, _AX) 69 } else { 70 self.Emit("MOVQ", ptr, _AX) 71 } 72 if saveDI { 73 self.save(_DI) 74 } 75 self.Emit("LEAQ", rec, _DI) 76 self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX 77 self.Rjmp("CALL", _R10) 78 if saveDI { 79 self.load(_DI) 80 } 81 if saveAX { 82 self.Emit("XCHGQ", ptr, _AX) 83 } 84 self.Sjmp("JMP", "_end_writeBarrier"+strconv.Itoa(i)+"_{n}") 85 self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}") 86 self.Emit("MOVQ", ptr, rec) 87 self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}") 88 } 89 90 func (self *_ValueDecoder) WritePtrAX(i int, rec obj.Addr, saveDI bool) { 91 self.Emit("MOVQ", _V_writeBarrier, _R10) 92 self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0)) 93 self.Sjmp("JE", "_no_writeBarrier"+strconv.Itoa(i)+"_{n}") 94 if saveDI { 95 self.save(_DI) 96 } 97 self.Emit("LEAQ", rec, _DI) 98 self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX 99 self.Rjmp("CALL", _R10) 100 if saveDI { 101 self.load(_DI) 102 } 103 self.Sjmp("JMP", "_end_writeBarrier"+strconv.Itoa(i)+"_{n}") 104 self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}") 105 self.Emit("MOVQ", _AX, rec) 106 self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}") 107 } 108 109 func (self *_ValueDecoder) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool) { 110 if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX { 111 panic("rec contains AX!") 112 } 113 self.Emit("MOVQ", _V_writeBarrier, _R10) 114 self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0)) 115 self.Sjmp("JE", "_no_writeBarrier"+strconv.Itoa(i)+"_{n}") 116 self.Emit("MOVQ", ptr, _AX) 117 if saveDI { 118 self.save(_DI) 119 } 120 self.Emit("LEAQ", rec, _DI) 121 self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX 122 self.Rjmp("CALL", _R10) 123 if saveDI { 124 self.load(_DI) 125 } 126 self.Sjmp("JMP", "_end_writeBarrier"+strconv.Itoa(i)+"_{n}") 127 self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}") 128 self.Emit("MOVQ", ptr, rec) 129 self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}") 130 }