From 395d6b5005b8e3854aa628ad98757dc053a8549c Mon Sep 17 00:00:00 2001 From: chenyifan Date: Tue, 18 Nov 2025 19:35:07 +0800 Subject: [PATCH] Add goexperiment.StepOpt2 for optimized step function in runtime --- src/internal/goexperiment/exp_stepopt2_off.go | 8 ++++ src/internal/goexperiment/exp_stepopt2_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_stepopt2_off.go create mode 100644 src/internal/goexperiment/exp_stepopt2_on.go diff --git a/src/internal/goexperiment/exp_stepopt2_off.go b/src/internal/goexperiment/exp_stepopt2_off.go new file mode 100644 index 000000000..7a06da83f --- /dev/null +++ b/src/internal/goexperiment/exp_stepopt2_off.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.stepopt2 + +package goexperiment + +const StepOpt2 = false +const StepOpt2Int = 0 diff --git a/src/internal/goexperiment/exp_stepopt2_on.go b/src/internal/goexperiment/exp_stepopt2_on.go new file mode 100644 index 000000000..1cd2d7d60 --- /dev/null +++ b/src/internal/goexperiment/exp_stepopt2_on.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.stepopt2 + +package goexperiment + +const StepOpt2 = true +const StepOpt2Int = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 87ddd355f..f39a282fe 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -115,4 +115,7 @@ type Flags struct { //PageNum enables 128k span size PageNum bool + + // StepOpt2 enables optimization for func step in package runtime + StepOpt2 bool } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index b47f2d839..ef2163447 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -7,6 +7,7 @@ package runtime import ( "internal/abi" "internal/goarch" + "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -1069,6 +1070,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.StepOpt2 { + return step_exp2(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]) @@ -1092,6 +1096,49 @@ func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) return p, true } +func step_exp2(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