]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: change funcinl sentinel value from 0 to ^0
authorJosh Bleecher Snyder <josharian@gmail.com>
Tue, 21 Sep 2021 20:48:23 +0000 (13:48 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 27 Sep 2021 20:58:24 +0000 (20:58 +0000)
_func and funcinl are type-punned.
We distinguish them at runtime by inspecting the first word.

Prior to this change, we used 0 as the sentinel value
that means that a Func is a funcinl.
That worked because _func's first word is the functions' entry PC,
and 0 is not a valid PC. I plan to make *_func's entry PC relative
to the containing module. As a result, 0 will be a valid value,
for the first function in the module.

Switch to ^0 as the new sentinel value, which is neither a valid
entry PC nor a valid PC offset.

Change-Id: I4c718523a083ed6edd57767c3548640681993522
Reviewed-on: https://go-review.googlesource.com/c/go/+/351459
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/runtime/runtime2.go
src/runtime/symtab.go

index 04bd5cb88746d88f4109947f84f80f2efed614dc..442042eb16ed71ac265b0489ccbde0be6078783e 100644 (file)
@@ -879,8 +879,8 @@ type _func struct {
 // A *Func can be either a *_func or a *funcinl, and they are distinguished
 // by the first uintptr.
 type funcinl struct {
-       zero  uintptr // set to 0 to distinguish from _func
-       entry uintptr // entry of the real (the "outermost") frame.
+       ones  uintptr // set to ^0 to distinguish from _func
+       entry uintptr // entry of the real (the "outermost") frame
        name  string
        file  string
        line  int
index 6236643cebc7b641b9f769daab68c258a2a52e3e..0f4ad5ab955b7146d3fe10381afc9534da1890bd 100644 (file)
@@ -650,6 +650,7 @@ func FuncForPC(pc uintptr) *Func {
                        name := funcnameFromNameoff(f, inltree[ix].func_)
                        file, line := funcline(f, pc)
                        fi := &funcinl{
+                               ones:  ^uintptr(0),
                                entry: f.entry, // entry of the real (the outermost) function.
                                name:  name,
                                file:  file,
@@ -667,7 +668,7 @@ func (f *Func) Name() string {
                return ""
        }
        fn := f.raw()
-       if fn.entry == 0 { // inlined version
+       if fn.isInlined() { // inlined version
                fi := (*funcinl)(unsafe.Pointer(fn))
                return fi.name
        }
@@ -677,7 +678,7 @@ func (f *Func) Name() string {
 // Entry returns the entry address of the function.
 func (f *Func) Entry() uintptr {
        fn := f.raw()
-       if fn.entry == 0 { // inlined version
+       if fn.isInlined() { // inlined version
                fi := (*funcinl)(unsafe.Pointer(fn))
                return fi.entry
        }
@@ -690,7 +691,7 @@ func (f *Func) Entry() uintptr {
 // counter within f.
 func (f *Func) FileLine(pc uintptr) (file string, line int) {
        fn := f.raw()
-       if fn.entry == 0 { // inlined version
+       if fn.isInlined() { // inlined version
                fi := (*funcinl)(unsafe.Pointer(fn))
                return fi.file, fi.line
        }
@@ -728,6 +729,11 @@ func (f funcInfo) _Func() *Func {
        return (*Func)(unsafe.Pointer(f._func))
 }
 
+// isInlined reports whether f should be re-interpreted as a *funcinl.
+func (f *_func) isInlined() bool {
+       return f.entry == ^uintptr(0) // see comment for funcinl.ones
+}
+
 // findfunc looks up function metadata for a PC.
 //
 // It is nosplit because it's part of the isgoexception