]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] all: merge master (798ec73) into dev.typeparams
authorMatthew Dempsky <mdempsky@google.com>
Thu, 22 Jul 2021 19:50:30 +0000 (12:50 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 22 Jul 2021 19:50:31 +0000 (12:50 -0700)
Merge List:

+ 2021-07-22 798ec73519 runtime: don't clear timerModifiedEarliest if adjustTimers is 0
+ 2021-07-22 fdb45acd1f runtime: move mem profile sampling into m-acquired section
+ 2021-07-21 3e48c0381f reflect: add missing copyright header
+ 2021-07-21 48c88f1b1b reflect: add Value.CanConvert
+ 2021-07-20 9e26569293 cmd/go: don't add C compiler ID to hash for standard library
+ 2021-07-20 d568e6e075 runtime/debug: skip TestPanicOnFault on netbsd/arm

Change-Id: I87e1cd4614bb3b00807f18dfdd02664dcaecaebd

1  2 
src/cmd/go/go_test.go
src/reflect/all_test.go
src/reflect/value.go
src/runtime/malloc.go
src/runtime/runtime2.go
src/runtime/time.go

diff --combined src/cmd/go/go_test.go
index eaafe79235263b040011e438c81c9c307b466e78,6ce276537babd88765937e1f7ec0f3c98cc5ac68..b13191f678ddb9f4ea8671768a800067185882e0
@@@ -806,9 -806,7 +806,9 @@@ func TestNewReleaseRebuildsStalePackage
                "src/internal/abi",
                "src/internal/bytealg",
                "src/internal/cpu",
 +              "src/internal/goarch",
                "src/internal/goexperiment",
 +              "src/internal/goos",
                "src/math/bits",
                "src/unsafe",
                filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
@@@ -2850,3 -2848,35 +2850,35 @@@ func TestExecInDeletedDir(t *testing.T
        // `go version` should not fail
        tg.run("version")
  }
+ // A missing C compiler should not force the net package to be stale.
+ // Issue 47215.
+ func TestMissingCC(t *testing.T) {
+       if !canCgo {
+               t.Skip("test is only meaningful on systems with cgo")
+       }
+       cc := os.Getenv("CC")
+       if cc == "" {
+               cc = "gcc"
+       }
+       if filepath.IsAbs(cc) {
+               t.Skipf(`"CC" (%s) is an absolute path`, cc)
+       }
+       _, err := exec.LookPath(cc)
+       if err != nil {
+               t.Skipf(`"CC" (%s) not on PATH`, cc)
+       }
+       tg := testgo(t)
+       defer tg.cleanup()
+       netStale, _ := tg.isStale("net")
+       if netStale {
+               t.Skip(`skipping test because "net" package is currently stale`)
+       }
+       tg.setenv("PATH", "") // No C compiler on PATH.
+       netStale, _ = tg.isStale("net")
+       if netStale {
+               t.Error(`clearing "PATH" causes "net" to be stale`)
+       }
+ }
diff --combined src/reflect/all_test.go
index e3faa31c1f7559710dc88c2766552b34fd5faf65,eac27e886f21d6c8d8325d50ad5e9c615457d929..5e5e4c1e6040893688f9c19d18b6863483553ae2
@@@ -10,7 -10,6 +10,7 @@@ import 
        "flag"
        "fmt"
        "go/token"
 +      "internal/goarch"
        "io"
        "math"
        "math/rand"
@@@ -4305,6 -4304,9 +4305,9 @@@ func TestConvert(t *testing.T) 
  
                // vout1 represents the in value converted to the in type.
                v1 := tt.in
+               if !v1.CanConvert(t1) {
+                       t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t1)
+               }
                vout1 := v1.Convert(t1)
                out1 := vout1.Interface()
                if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
                }
  
                // vout2 represents the in value converted to the out type.
+               if !v1.CanConvert(t2) {
+                       t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t2)
+               }
                vout2 := v1.Convert(t2)
                out2 := vout2.Interface()
                if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
@@@ -4372,6 -4377,9 +4378,9 @@@ func TestConvertPanic(t *testing.T) 
        if !v.Type().ConvertibleTo(pt) {
                t.Errorf("[]byte should be convertible to *[8]byte")
        }
+       if v.CanConvert(pt) {
+               t.Errorf("slice with length 4 should not be convertible to *[8]byte")
+       }
        shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() {
                _ = v.Convert(pt)
        })
@@@ -6458,10 -6466,10 +6467,10 @@@ func clobber() 
  
  func TestFuncLayout(t *testing.T) {
        align := func(x uintptr) uintptr {
 -              return (x + PtrSize - 1) &^ (PtrSize - 1)
 +              return (x + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
        }
        var r []byte
 -      if PtrSize == 4 {
 +      if goarch.PtrSize == 4 {
                r = []byte{0, 0, 0, 1}
        } else {
                r = []byte{0, 0, 1}
        tests := []test{
                {
                        typ:       ValueOf(func(a, b string) string { return "" }).Type(),
 -                      size:      6 * PtrSize,
 -                      argsize:   4 * PtrSize,
 -                      retOffset: 4 * PtrSize,
 +                      size:      6 * goarch.PtrSize,
 +                      argsize:   4 * goarch.PtrSize,
 +                      retOffset: 4 * goarch.PtrSize,
                        stack:     []byte{1, 0, 1, 0, 1},
                        gc:        []byte{1, 0, 1, 0, 1},
                },
                {
                        typ:       ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
 -                      size:      align(align(3*4) + PtrSize + 2),
 -                      argsize:   align(3*4) + PtrSize + 2,
 -                      retOffset: align(align(3*4) + PtrSize + 2),
 +                      size:      align(align(3*4) + goarch.PtrSize + 2),
 +                      argsize:   align(3*4) + goarch.PtrSize + 2,
 +                      retOffset: align(align(3*4) + goarch.PtrSize + 2),
                        stack:     r,
                        gc:        r,
                },
                {
                        typ:       ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
 -                      size:      4 * PtrSize,
 -                      argsize:   4 * PtrSize,
 -                      retOffset: 4 * PtrSize,
 +                      size:      4 * goarch.PtrSize,
 +                      argsize:   4 * goarch.PtrSize,
 +                      retOffset: 4 * goarch.PtrSize,
                        stack:     []byte{1, 0, 1, 1},
                        gc:        []byte{1, 0, 1, 1},
                },
                {
                        typ:       ValueOf(func(a S) {}).Type(),
 -                      size:      4 * PtrSize,
 -                      argsize:   4 * PtrSize,
 -                      retOffset: 4 * PtrSize,
 +                      size:      4 * goarch.PtrSize,
 +                      argsize:   4 * goarch.PtrSize,
 +                      retOffset: 4 * goarch.PtrSize,
                        stack:     []byte{0, 0, 1, 1},
                        gc:        []byte{0, 0, 1, 1},
                },
                {
                        rcvr:      ValueOf((*byte)(nil)).Type(),
                        typ:       ValueOf(func(a uintptr, b *int) {}).Type(),
 -                      size:      3 * PtrSize,
 -                      argsize:   3 * PtrSize,
 -                      retOffset: 3 * PtrSize,
 +                      size:      3 * goarch.PtrSize,
 +                      argsize:   3 * goarch.PtrSize,
 +                      retOffset: 3 * goarch.PtrSize,
                        stack:     []byte{1, 0, 1},
                        gc:        []byte{1, 0, 1},
                },
                {
                        typ:       ValueOf(func(a uintptr) {}).Type(),
 -                      size:      PtrSize,
 -                      argsize:   PtrSize,
 -                      retOffset: PtrSize,
 +                      size:      goarch.PtrSize,
 +                      argsize:   goarch.PtrSize,
 +                      retOffset: goarch.PtrSize,
                        stack:     []byte{},
                        gc:        []byte{},
                },
                {
                        typ:       ValueOf(func() uintptr { return 0 }).Type(),
 -                      size:      PtrSize,
 +                      size:      goarch.PtrSize,
                        argsize:   0,
                        retOffset: 0,
                        stack:     []byte{},
                {
                        rcvr:      ValueOf(uintptr(0)).Type(),
                        typ:       ValueOf(func(a uintptr) {}).Type(),
 -                      size:      2 * PtrSize,
 -                      argsize:   2 * PtrSize,
 -                      retOffset: 2 * PtrSize,
 +                      size:      2 * goarch.PtrSize,
 +                      argsize:   2 * goarch.PtrSize,
 +                      retOffset: 2 * goarch.PtrSize,
                        stack:     []byte{1},
                        gc:        []byte{1},
                        // Note: this one is tricky, as the receiver is not a pointer. But we
@@@ -6748,7 -6756,7 +6757,7 @@@ func TestGCBits(t *testing.T) 
        verifyGCBits(t, TypeOf(([][10000]Xscalar)(nil)), lit(1))
        verifyGCBits(t, SliceOf(ArrayOf(10000, Tscalar)), lit(1))
  
 -      hdr := make([]byte, 8/PtrSize)
 +      hdr := make([]byte, 8/goarch.PtrSize)
  
        verifyMapBucket := func(t *testing.T, k, e Type, m interface{}, want []byte) {
                verifyGCBits(t, MapBucketOf(k, e), want)
                join(hdr, rep(8, lit(0, 1)), rep(8, lit(1)), lit(1)))
        verifyMapBucket(t, Tint64, Tptr,
                map[int64]Xptr(nil),
 -              join(hdr, rep(8, rep(8/PtrSize, lit(0))), rep(8, lit(1)), lit(1)))
 +              join(hdr, rep(8, rep(8/goarch.PtrSize, lit(0))), rep(8, lit(1)), lit(1)))
        verifyMapBucket(t,
                Tscalar, Tscalar,
                map[Xscalar]Xscalar(nil),
                map[[2]Xscalarptr][3]Xptrscalar(nil),
                join(hdr, rep(8*2, lit(0, 1)), rep(8*3, lit(1, 0)), lit(1)))
        verifyMapBucket(t,
 -              ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar),
 -              map[[64 / PtrSize]Xscalarptr][64 / PtrSize]Xptrscalar(nil),
 -              join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8*64/PtrSize, lit(1, 0)), lit(1)))
 +              ArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar),
 +              map[[64 / goarch.PtrSize]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil),
 +              join(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1)))
        verifyMapBucket(t,
 -              ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar),
 -              map[[64/PtrSize + 1]Xscalarptr][64 / PtrSize]Xptrscalar(nil),
 -              join(hdr, rep(8, lit(1)), rep(8*64/PtrSize, lit(1, 0)), lit(1)))
 +              ArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar),
 +              map[[64/goarch.PtrSize + 1]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil),
 +              join(hdr, rep(8, lit(1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1)))
        verifyMapBucket(t,
 -              ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar),
 -              map[[64 / PtrSize]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil),
 -              join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1)))
 +              ArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar),
 +              map[[64 / goarch.PtrSize]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil),
 +              join(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1)))
        verifyMapBucket(t,
 -              ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar),
 -              map[[64/PtrSize + 1]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil),
 +              ArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar),
 +              map[[64/goarch.PtrSize + 1]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil),
                join(hdr, rep(8, lit(1)), rep(8, lit(1)), lit(1)))
  }
  
diff --combined src/reflect/value.go
index 7589966e222a8b2e45786dd2d338634b99f9678f,6f878eba5b0411af35e44d27ea6a64a2205248e7..b4b2d2e38b86be46918b85cdab6dcb4289f098ef
@@@ -6,7 -6,6 +6,7 @@@ package reflec
  
  import (
        "internal/abi"
 +      "internal/goarch"
        "internal/itoa"
        "internal/unsafeheader"
        "math"
@@@ -14,6 -13,8 +14,6 @@@
        "unsafe"
  )
  
 -const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
 -
  // Value is the reflection interface to a Go value.
  //
  // Not all methods apply to all kinds of values. Restrictions,
@@@ -93,7 -94,7 +93,7 @@@ func (f flag) ro() flag 
  // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
  // if v.Kind() == Ptr, the base type must not be go:notinheap.
  func (v Value) pointer() unsafe.Pointer {
 -      if v.typ.size != ptrSize || !v.typ.pointers() {
 +      if v.typ.size != goarch.PtrSize || !v.typ.pointers() {
                panic("can't call pointer on a non-pointer Value")
        }
        if v.flag&flagIndir != 0 {
@@@ -532,7 -533,7 +532,7 @@@ func (v Value) call(op string, in []Val
        }
        // TODO(mknyszek): Remove this when we no longer have
        // caller reserved spill space.
 -      frameSize = align(frameSize, ptrSize)
 +      frameSize = align(frameSize, goarch.PtrSize)
        frameSize += abi.spill
  
        // Mark pointers in registers for the return path.
@@@ -957,6 -958,9 +957,6 @@@ func callMethod(ctxt *methodValue, fram
                // 2. Stack -> registers translation.
                // 3. Registers -> stack translation.
                // 4. Registers -> registers translation.
 -              // TODO(mknyszek): Cases 2 and 3 below only work on little endian
 -              // architectures. This is OK for now, but this needs to be fixed
 -              // before supporting the register ABI on big endian architectures.
  
                // If the value ABI passes the value on the stack,
                // then the method ABI does too, because it has strictly
                                        methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from)
                                        fallthrough // We need to make sure this ends up in Ints, too.
                                case abiStepIntReg:
 -                                      memmove(unsafe.Pointer(&methodRegs.Ints[mStep.ireg]), from, mStep.size)
 +                                      memmove(methodRegs.IntRegArgAddr(mStep.ireg, mStep.size), from, mStep.size)
                                case abiStepFloatReg:
 -                                      memmove(unsafe.Pointer(&methodRegs.Floats[mStep.freg]), from, mStep.size)
 +                                      memmove(methodRegs.FloatRegArgAddr(mStep.freg, mStep.size), from, mStep.size)
                                default:
                                        panic("unexpected method step")
                                }
                                        // Do the pointer copy directly so we get a write barrier.
                                        *(*unsafe.Pointer)(to) = valueRegs.Ptrs[vStep.ireg]
                                case abiStepIntReg:
 -                                      memmove(to, unsafe.Pointer(&valueRegs.Ints[vStep.ireg]), vStep.size)
 +                                      memmove(to, valueRegs.IntRegArgAddr(vStep.ireg, vStep.size), vStep.size)
                                case abiStepFloatReg:
 -                                      memmove(to, unsafe.Pointer(&valueRegs.Floats[vStep.freg]), vStep.size)
 +                                      memmove(to, valueRegs.FloatRegArgAddr(vStep.freg, vStep.size), vStep.size)
                                default:
                                        panic("unexpected value step")
                                }
        methodFrameSize := methodFrameType.size
        // TODO(mknyszek): Remove this when we no longer have
        // caller reserved spill space.
 -      methodFrameSize = align(methodFrameSize, ptrSize)
 +      methodFrameSize = align(methodFrameSize, goarch.PtrSize)
        methodFrameSize += methodABI.spill
  
        // Mark pointers in registers for the return path.
@@@ -2807,6 -2811,26 +2807,26 @@@ func (v Value) Convert(t Type) Value 
        return op(v, t)
  }
  
+ // CanConvert reports whether the value v can be converted to type t.
+ // If v.CanConvert(t) returns true then v.Convert(t) will not panic.
+ func (v Value) CanConvert(t Type) bool {
+       vt := v.Type()
+       if !vt.ConvertibleTo(t) {
+               return false
+       }
+       // Currently the only conversion that is OK in terms of type
+       // but that can panic depending on the value is converting
+       // from slice to pointer-to-array.
+       if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
+               n := t.Elem().Len()
+               h := (*unsafeheader.Slice)(v.ptr)
+               if n > h.Len {
+                       return false
+               }
+       }
+       return true
+ }
  // convertOp returns the function to convert a value of type src
  // to a value of type dst. If the conversion is illegal, convertOp returns nil.
  func convertOp(dst, src *rtype) func(Value, Type) Value {
diff --combined src/runtime/malloc.go
index 8483ec99d88cd946b78d2755dd9618612ab7c699,cc22b0f276597e94b5e6138a4fcddb8d5e20bb5b..f8d5d48a28d7c8f7c1e35ebc013f93a166bbb42b
  package runtime
  
  import (
 +      "internal/goarch"
 +      "internal/goos"
        "runtime/internal/atomic"
        "runtime/internal/math"
        "runtime/internal/sys"
@@@ -152,7 -150,7 +152,7 @@@ const 
        //   windows/32       | 4KB        | 3
        //   windows/64       | 8KB        | 2
        //   plan9            | 4KB        | 3
 -      _NumStackOrders = 4 - sys.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9
 +      _NumStackOrders = 4 - goarch.PtrSize/4*goos.IsWindows - 1*goos.IsPlan9
  
        // heapAddrBits is the number of bits in a heap address. On
        // amd64, addresses are sign-extended beyond heapAddrBits. On
        // arenaBaseOffset to offset into the top 4 GiB.
        //
        // WebAssembly currently has a limit of 4GB linear memory.
 -      heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*sys.GoosIos*sys.GoarchArm64
 +      heapAddrBits = (_64bit*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64))*48 + (1-_64bit+goarch.IsWasm)*(32-(goarch.IsMips+goarch.IsMipsle)) + 33*goos.IsIos*goarch.IsArm64
  
        // maxAlloc is the maximum size of an allocation. On 64-bit,
        // it's theoretically possible to allocate 1<<heapAddrBits bytes. On
        // logHeapArenaBytes is log_2 of heapArenaBytes. For clarity,
        // prefer using heapArenaBytes where possible (we need the
        // constant to compute some other constants).
 -      logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm + (2+20)*sys.GoosIos*sys.GoarchArm64
 +      logHeapArenaBytes = (6+20)*(_64bit*(1-goos.IsWindows)*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64)) + (2+20)*(_64bit*goos.IsWindows) + (2+20)*(1-_64bit) + (2+20)*goarch.IsWasm + (2+20)*goos.IsIos*goarch.IsArm64
  
        // heapArenaBitmapBytes is the size of each heap arena's bitmap.
 -      heapArenaBitmapBytes = heapArenaBytes / (sys.PtrSize * 8 / 2)
 +      heapArenaBitmapBytes = heapArenaBytes / (goarch.PtrSize * 8 / 2)
  
        pagesPerArena = heapArenaBytes / pageSize
  
        // We use the L1 map on 64-bit Windows because the arena size
        // is small, but the address space is still 48 bits, and
        // there's a high cost to having a large L2.
 -      arenaL1Bits = 6 * (_64bit * sys.GoosWindows)
 +      arenaL1Bits = 6 * (_64bit * goos.IsWindows)
  
        // arenaL2Bits is the number of bits of the arena number
        // covered by the second level arena index.
        //
        // On other platforms, the user address space is contiguous
        // and starts at 0, so no offset is necessary.
 -      arenaBaseOffset = 0xffff800000000000*sys.GoarchAmd64 + 0x0a00000000000000*sys.GoosAix
 +      arenaBaseOffset = 0xffff800000000000*goarch.IsAmd64 + 0x0a00000000000000*goos.IsAix
        // A typed version of this constant that will make it into DWARF (for viewcore).
        arenaBaseOffsetUintptr = uintptr(arenaBaseOffset)
  
@@@ -422,6 -420,8 +422,6 @@@ func mallocinit() 
                throw("bad TinySizeClass")
        }
  
 -      testdefersizes()
 -
        if heapArenaBitmapBytes&(heapArenaBitmapBytes-1) != 0 {
                // heapBits expects modular arithmetic on bitmap
                // addresses to work.
        lockInit(&globalAlloc.mutex, lockRankGlobalAlloc)
  
        // Create initial arena growth hints.
 -      if sys.PtrSize == 8 {
 +      if goarch.PtrSize == 8 {
                // On a 64-bit machine, we pick the following hints
                // because:
                //
@@@ -732,7 -732,7 +732,7 @@@ mapped
                l2 := h.arenas[ri.l1()]
                if l2 == nil {
                        // Allocate an L2 arena map.
 -                      l2 = (*[1 << arenaL2Bits]*heapArena)(persistentalloc(unsafe.Sizeof(*l2), sys.PtrSize, nil))
 +                      l2 = (*[1 << arenaL2Bits]*heapArena)(persistentalloc(unsafe.Sizeof(*l2), goarch.PtrSize, nil))
                        if l2 == nil {
                                throw("out of memory allocating heap arena map")
                        }
                        throw("arena already initialized")
                }
                var r *heapArena
 -              r = (*heapArena)(h.heapArenaAlloc.alloc(unsafe.Sizeof(*r), sys.PtrSize, &memstats.gcMiscSys))
 +              r = (*heapArena)(h.heapArenaAlloc.alloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys))
                if r == nil {
 -                      r = (*heapArena)(persistentalloc(unsafe.Sizeof(*r), sys.PtrSize, &memstats.gcMiscSys))
 +                      r = (*heapArena)(persistentalloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys))
                        if r == nil {
                                throw("out of memory allocating heap arena metadata")
                        }
  
                // Add the arena to the arenas list.
                if len(h.allArenas) == cap(h.allArenas) {
 -                      size := 2 * uintptr(cap(h.allArenas)) * sys.PtrSize
 +                      size := 2 * uintptr(cap(h.allArenas)) * goarch.PtrSize
                        if size == 0 {
                                size = physPageSize
                        }
 -                      newArray := (*notInHeap)(persistentalloc(size, sys.PtrSize, &memstats.gcMiscSys))
 +                      newArray := (*notInHeap)(persistentalloc(size, goarch.PtrSize, &memstats.gcMiscSys))
                        if newArray == nil {
                                throw("out of memory allocating allArenas")
                        }
                        oldSlice := h.allArenas
 -                      *(*notInHeapSlice)(unsafe.Pointer(&h.allArenas)) = notInHeapSlice{newArray, len(h.allArenas), int(size / sys.PtrSize)}
 +                      *(*notInHeapSlice)(unsafe.Pointer(&h.allArenas)) = notInHeapSlice{newArray, len(h.allArenas), int(size / goarch.PtrSize)}
                        copy(h.allArenas, oldSlice)
                        // Do not free the old backing array because
                        // there may be concurrent readers. Since we
@@@ -1017,7 -1017,7 +1017,7 @@@ func mallocgc(size uintptr, typ *_type
                        // Align tiny pointer for required (conservative) alignment.
                        if size&7 == 0 {
                                off = alignUp(off, 8)
 -                      } else if sys.PtrSize == 4 && size == 12 {
 +                      } else if goarch.PtrSize == 4 && size == 12 {
                                // Conservatively align 12-byte objects to 8 bytes on 32-bit
                                // systems so that objects whose first field is a 64-bit
                                // value is aligned to 8 bytes and does not cause a fault on
  
        var scanSize uintptr
        if !noscan {
 -              // If allocating a defer+arg block, now that we've picked a malloc size
 -              // large enough to hold everything, cut the "asked for" size down to
 -              // just the defer header, so that the GC bitmap will record the arg block
 -              // as containing nothing at all (as if it were unused space at the end of
 -              // a malloc block caused by size rounding).
 -              // The defer arg areas are scanned as part of scanstack.
 -              if typ == deferType {
 -                      dataSize = unsafe.Sizeof(_defer{})
 -              }
                heapBitsSetType(uintptr(x), size, dataSize, typ)
                if dataSize > typ.size {
                        // Array allocation. If there are any
                msanmalloc(x, size)
        }
  
+       if rate := MemProfileRate; rate > 0 {
+               // Note cache c only valid while m acquired; see #47302
+               if rate != 1 && size < c.nextSample {
+                       c.nextSample -= size
+               } else {
+                       profilealloc(mp, x, size)
+               }
+       }
        mp.mallocing = 0
        releasem(mp)
  
        // Pointerfree data can be zeroed late in a context where preemption can occur.
        // x will keep the memory alive.
        if !isZeroed && needzero {
-               memclrNoHeapPointersChunked(size, x)
+               memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302
        }
  
        if debug.malloc {
                }
        }
  
-       if rate := MemProfileRate; rate > 0 {
-               if rate != 1 && size < c.nextSample {
-                       c.nextSample -= size
-               } else {
-                       mp := acquirem()
-                       profilealloc(mp, x, size)
-                       releasem(mp)
-               }
-       }
        if assistG != nil {
                // Account for internal fragmentation in the assist
                // debt now that we know it.
@@@ -1412,7 -1419,7 +1410,7 @@@ func persistentalloc1(size, align uintp
                                break
                        }
                }
 -              persistent.off = alignUp(sys.PtrSize, align)
 +              persistent.off = alignUp(goarch.PtrSize, align)
        }
        p := persistent.base.add(persistent.off)
        persistent.off += size
diff --combined src/runtime/runtime2.go
index d557ee8a3e49379fce0b69223bb8416b22382277,8a15787382c61017a30f99fcf6c77e8678540cbc..83d7d50b192e555a0e33c455a765b42f293a528a
@@@ -5,8 -5,8 +5,8 @@@
  package runtime
  
  import (
 +      "internal/goarch"
        "runtime/internal/atomic"
 -      "runtime/internal/sys"
        "unsafe"
  )
  
@@@ -505,7 -505,7 +505,7 @@@ const 
        // tlsSlots is the number of pointer-sized slots reserved for TLS on some platforms,
        // like Windows.
        tlsSlots = 6
 -      tlsSize  = tlsSlots * sys.PtrSize
 +      tlsSize  = tlsSlots * goarch.PtrSize
  )
  
  type m struct {
@@@ -613,8 -613,8 +613,8 @@@ type p struct 
        pcache      pageCache
        raceprocctx uintptr
  
 -      deferpool    [5][]*_defer // pool of available defer structs of different sizes (see panic.go)
 -      deferpoolbuf [5][32]*_defer
 +      deferpool    []*_defer // pool of available defer structs (see panic.go)
 +      deferpoolbuf [32]*_defer
  
        // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen.
        goidcache    uint64
        // timerModifiedEarlier status. Because the timer may have been
        // modified again, there need not be any timer with this value.
        // This is updated using atomic functions.
-       // This is 0 if the value is unknown.
+       // This is 0 if there are no timerModifiedEarlier timers.
        timerModifiedEarliest uint64
  
        // Per-P GC state
@@@ -801,9 -801,9 +801,9 @@@ type schedt struct 
        sudoglock  mutex
        sudogcache *sudog
  
 -      // Central pool of available defer structs of different sizes.
 +      // Central pool of available defer structs.
        deferlock mutex
 -      deferpool [5]*_defer
 +      deferpool *_defer
  
        // freem is the list of m's waiting to be freed when their
        // m.exited is set. Linked through m.freelink.
@@@ -930,7 -930,7 +930,7 @@@ func extendRandom(r []byte, n int) 
                        w = 16
                }
                h := memhash(unsafe.Pointer(&r[n-w]), uintptr(nanotime()), uintptr(w))
 -              for i := 0; i < sys.PtrSize && n < len(r); i++ {
 +              for i := 0; i < goarch.PtrSize && n < len(r); i++ {
                        r[n] = byte(h)
                        n++
                        h >>= 8
  
  // A _defer holds an entry on the list of deferred calls.
  // If you add a field here, add code to clear it in freedefer and deferProcStack
 -// This struct must match the code in cmd/compile/internal/reflectdata/reflect.go:deferstruct
 -// and cmd/compile/internal/gc/ssa.go:(*state).call.
 +// This struct must match the code in cmd/compile/internal/ssagen/ssa.go:deferstruct
 +// and cmd/compile/internal/ssagen/ssa.go:(*state).call.
  // Some defers will be allocated on the stack and some on the heap.
  // All defers are logically part of the stack, so write barriers to
  // initialize them are not required. All defers must be manually scanned,
  // and for heap defers, marked.
  type _defer struct {
 -      siz     int32 // includes both arguments and results
        started bool
        heap    bool
        // openDefer indicates that this _defer is for a frame with open-coded
diff --combined src/runtime/time.go
index 90e9b1139f8c8b035cf64bd818891ebaf08614e0,7b84d2af571515e6e37d442ec57fbeba2a06321b..2f791c4ad876b1f899f3e0a3d1722914ee59573d
@@@ -7,7 -7,6 +7,7 @@@
  package runtime
  
  import (
 +      "internal/abi"
        "runtime/internal/atomic"
        "runtime/internal/sys"
        "unsafe"
@@@ -669,11 -668,6 +669,6 @@@ func adjusttimers(pp *p, now int64) 
                if verifyTimers {
                        verifyTimerHeap(pp)
                }
-               // There are no timers to adjust, so it is safe to clear
-               // timerModifiedEarliest. Do so in case it is stale.
-               // Everything will work if we don't do this,
-               // but clearing here may save future calls to adjusttimers.
-               atomic.Store64(&pp.timerModifiedEarliest, 0)
                return
        }
  
@@@ -857,7 -851,7 +852,7 @@@ func runOneTimer(pp *p, t *timer, now i
        if raceenabled {
                ppcur := getg().m.p.ptr()
                if ppcur.timerRaceCtx == 0 {
 -                      ppcur.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
 +                      ppcur.timerRaceCtx = racegostart(abi.FuncPCABIInternal(runtimer) + sys.PCQuantum)
                }
                raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t))
        }