From bf9d8b4ad9f579cd1beb740289a1f4b6545d0c84 Mon Sep 17 00:00:00 2001 From: shupiaoyang Date: Tue, 2 Dec 2025 10:45:46 +0800 Subject: [PATCH] Add goexperiment.StepOpt2 and optimize runtime step function --- src/internal/goexperiment/exp_stepopt_off.go | 8 ++++ src/internal/goexperiment/exp_stepopt_on.go | 8 ++++ src/internal/goexperiment/flags.go | 3 ++ src/runtime/symtab.go | 47 ++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/internal/goexperiment/exp_stepopt_off.go create mode 100644 src/internal/goexperiment/exp_stepopt_on.go diff --git a/src/internal/goexperiment/exp_stepopt_off.go b/src/internal/goexperiment/exp_stepopt_off.go new file mode 100644 index 000000000..bca12c06e --- /dev/null +++ b/src/internal/goexperiment/exp_stepopt_off.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.stepopt + +package goexperiment + +const StepOpt = false +const StepOptInt = 0 diff --git a/src/internal/goexperiment/exp_stepopt_on.go b/src/internal/goexperiment/exp_stepopt_on.go new file mode 100644 index 000000000..957d2daac --- /dev/null +++ b/src/internal/goexperiment/exp_stepopt_on.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.stepopt + +package goexperiment + +const StepOpt = true +const StepOptInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index ac85fc800..4b3b0f8ab 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -131,4 +131,7 @@ type Flags struct { // Kunpeng malloc prefetch optimization. PrefetchMalloc bool + + // StepOpt enables optimization for func step in package runtime + StepOpt bool } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 8c6ef2b4f..608ec524a 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -7,6 +7,7 @@ package runtime import ( "internal/abi" "internal/goarch" + "internal/goexperiment" "internal/runtime/atomic" "internal/runtime/sys" "unsafe" @@ -1246,6 +1247,9 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { // step advances to the next pc, value pair in the encoded table. func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) { + if goexperiment.StepOpt { + return stepOpt(p, pc, val, first) + } // For both uvdelta and pcdelta, the common case (~70%) // is that they are a single byte. If so, avoid calling readvarint. uvdelta := uint32(p[0]) @@ -1269,6 +1273,49 @@ func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) return p, true } +func stepOpt(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) { + // For both uvdelta and pcdelta, the common case (~70%) + // is that they are a single byte. If so, avoid calling readvarint. + var n uint32 + uvdelta := uint32(p[0]) + if uvdelta == 0 && !first { + return nil, false + } + if uvdelta&0x80 == 0 { + n = 1 + *val += int32(-(uvdelta & 1) ^ (uvdelta >> 1)) + p = p[n:] + } else { + a := uint32(p[1]) + if a&0x80 == 0 { + uvdelta = (uvdelta & 0x7f) | (a << 7) + n = 2 + } else { + n, uvdelta = readvarint(p) + } + *val += int32(-(uvdelta & 1) ^ (uvdelta >> 1)) + p = p[n:] + } + + pcdelta := uint32(p[0]) // load 2-byte once + if pcdelta&0x80 == 0 { + n = 1 + *pc += uintptr((pcdelta & 0xff) * sys.PCQuantum) + p = p[n:] + } else { + a := uint32(p[1]) + if a&0x80 == 0 { + pcdelta = (pcdelta & 0x7f) | (a << 7) + n = 2 + } else { + n, pcdelta = readvarint(p) + } + p = p[n:] + *pc += uintptr(pcdelta * sys.PCQuantum) + } + return p, true +} + // readvarint reads a varint from p. func readvarint(p []byte) (read uint32, val uint32) { var v, shift, n uint32 -- Gitee