Skip to content

Commit c2483a5

Browse files
committed
cmd, runtime: eliminate runtime.no_pointers_stackmap
runtime.no_pointers_stackmap is an odd beast. It is defined in a Go file, populated by assembly, used by the GC, and its address is magic used by async pre-emption to ascertain whether a routine was implemented in assembly. A subsequent change will force all GC data into the go.func.* linker symbol. runtime.no_pointers_stackmap is GC data, so it must go there. Yet it also needs to go into rodata, for the runtime address trick. This change eliminates it entirely. Replace the runtime address check with the newly introduced asm funcflag. Handle the assembly macro as magic, similarly to our handling of go_args_stackmap. This allows the no_pointers_stackmap to be identical in all ways to other gclocals stackmaps, including content-addressability. Change-Id: Id2f20a262cfab0719beb88e6342984ec4b196268 Reviewed-on: https://go-review.googlesource.com/c/go/+/353672 Trust: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
1 parent a8d78fa commit c2483a5

File tree

4 files changed

+22
-19
lines changed

4 files changed

+22
-19
lines changed

src/cmd/internal/obj/plist.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,28 @@ func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string
5454
if curtext == nil { // func _() {}
5555
continue
5656
}
57-
if p.To.Sym.Name == "go_args_stackmap" {
57+
switch p.To.Sym.Name {
58+
case "go_args_stackmap":
5859
if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps {
5960
ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
6061
}
6162
p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
63+
case "no_pointers_stackmap":
64+
if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_LocalsPointerMaps {
65+
ctxt.Diag("FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps")
66+
}
67+
// funcdata for functions with no local variables in frame.
68+
// Define two zero-length bitmaps, because the same index is used
69+
// for the local variables as for the argument frame, and assembly
70+
// frames have two argument bitmaps, one without results and one with results.
71+
// Write []uint32{2, 0}.
72+
b := make([]byte, 8)
73+
ctxt.Arch.ByteOrder.PutUint32(b, 2)
74+
s := ctxt.GCLocalsSym(b)
75+
if !s.OnList() {
76+
ctxt.Globl(s, int64(len(s.P)), int(RODATA|DUPOK))
77+
}
78+
p.To.Sym = s
6279
}
6380

6481
}

src/runtime/asm.s

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44

55
#include "textflag.h"
66

7-
// funcdata for functions with no local variables in frame.
8-
// Define two zero-length bitmaps, because the same index is used
9-
// for the local variables as for the argument frame, and assembly
10-
// frames have two argument bitmaps, one without results and one with results.
11-
DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2
12-
DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0
13-
GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8
14-
157
#ifndef GOARCH_amd64
168
TEXT ·sigpanic0(SB),NOSPLIT,$0-0
179
JMP ·sigpanic<ABIInternal>(SB)

src/runtime/funcdata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
// NO_LOCAL_POINTERS indicates that the assembly function stores
4646
// no pointers to heap objects in its local stack variables.
47-
#define NO_LOCAL_POINTERS FUNCDATA $FUNCDATA_LocalsPointerMaps, runtime·no_pointers_stackmap(SB)
47+
#define NO_LOCAL_POINTERS FUNCDATA $FUNCDATA_LocalsPointerMaps, no_pointers_stackmap(SB)
4848

4949
// ArgsSizeUnknown is set in Func.argsize to mark all functions
5050
// whose argument size is unknown (C vararg functions, and

src/runtime/preempt.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import (
5656
"internal/abi"
5757
"internal/goarch"
5858
"runtime/internal/atomic"
59-
"unsafe"
6059
)
6160

6261
type suspendGState struct {
@@ -405,12 +404,9 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) {
405404
// functions (except at calls).
406405
return false, 0
407406
}
408-
if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || fd == unsafe.Pointer(&no_pointers_stackmap) {
409-
// This is assembly code. Don't assume it's
410-
// well-formed. We identify assembly code by
411-
// checking that it has either no stack map, or
412-
// no_pointers_stackmap, which is the stack map
413-
// for ones marked as NO_LOCAL_POINTERS.
407+
if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || f.flag&funcFlag_ASM != 0 {
408+
// This is assembly code. Don't assume it's well-formed.
409+
// TODO: Empirically we still need the fd == nil check. Why?
414410
//
415411
// TODO: Are there cases that are safe but don't have a
416412
// locals pointer map, like empty frame functions?
@@ -455,5 +451,3 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) {
455451
}
456452
return true, pc
457453
}
458-
459-
var no_pointers_stackmap uint64 // defined in assembly, for NO_LOCAL_POINTERS macro

0 commit comments

Comments
 (0)