diff options
Diffstat (limited to 'vendor/github.com/bytedance/sonic/internal/rt/gcwb.go')
-rw-r--r-- | vendor/github.com/bytedance/sonic/internal/rt/gcwb.go | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/github.com/bytedance/sonic/internal/rt/gcwb.go b/vendor/github.com/bytedance/sonic/internal/rt/gcwb.go new file mode 100644 index 000000000..c3217c899 --- /dev/null +++ b/vendor/github.com/bytedance/sonic/internal/rt/gcwb.go @@ -0,0 +1,124 @@ +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rt + +import ( + `os` + `sync/atomic` + `unsafe` + + `golang.org/x/arch/x86/x86asm` +) + +const ( + _MaxInstr = 15 +) + +func isvar(arg x86asm.Arg) bool { + v, ok := arg.(x86asm.Mem) + return ok && v.Base == x86asm.RIP +} + +func iszero(arg x86asm.Arg) bool { + v, ok := arg.(x86asm.Imm) + return ok && v == 0 +} + +func GcwbAddr() uintptr { + var err error + var off uintptr + var ins x86asm.Inst + + /* get the function address */ + pc := uintptr(0) + fp := FuncAddr(atomic.StorePointer) + + /* search within the first 16 instructions */ + for i := 0; i < 16; i++ { + mem := unsafe.Pointer(uintptr(fp) + pc) + buf := BytesFrom(mem, _MaxInstr, _MaxInstr) + + /* disassemble the instruction */ + if ins, err = x86asm.Decode(buf, 64); err != nil { + panic("gcwbaddr: " + err.Error()) + } + + /* check for a byte comparison with zero */ + if ins.Op == x86asm.CMP && ins.MemBytes == 1 && isvar(ins.Args[0]) && iszero(ins.Args[1]) { + off = pc + uintptr(ins.Len) + uintptr(ins.Args[0].(x86asm.Mem).Disp) + break + } + + /* move to next instruction */ + nb := ins.Len + pc += uintptr(nb) + } + + /* check for address */ + if off == 0 { + panic("gcwbaddr: could not locate the variable `writeBarrier`") + } else { + return uintptr(fp) + off + } +} + +// StopProfiling is used to stop traceback introduced by SIGPROF while native code is running. +// WARN: this option is only a workaround for traceback issue (https://github.com/bytedance/sonic/issues/310), +// and will be dropped when the issue is fixed. +var StopProfiling = os.Getenv("SONIC_STOP_PROFILING") != "" + +// WARN: must be aligned with runtime.Prof +// type Prof struct { +// signalLock uint32 +// hz int32 +// } + +var ( + // // go:linkname runtimeProf runtime.prof + // runtimeProf Prof + + // count of native-C calls + yieldCount uint32 + + // previous value of runtimeProf.hz + oldHz int32 +) + +//go:nosplit +func MoreStack(size uintptr) + +func StopProf() + +// func StopProf() { +// atomic.AddUint32(&yieldCount, 1) +// if runtimeProf.hz != 0 { +// oldHz = runtimeProf.hz +// runtimeProf.hz = 0 +// } +// } + +func StartProf() + +// func StartProf() { +// atomic.AddUint32(&yieldCount, ^uint32(0)) +// if yieldCount == 0 && runtimeProf.hz == 0 { +// if oldHz == 0 { +// oldHz = 100 +// } +// runtimeProf.hz = oldHz +// } +// } |