Merge branch 'golang:master' into add-copyright-header

This commit is contained in:
180909 2021-07-23 17:32:31 +08:00 committed by GitHub
commit 4122be1b4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 178 additions and 41 deletions

View file

@ -80,6 +80,7 @@ pkg net/url, method (Values) Has(string) bool
pkg reflect, func VisibleFields(Type) []StructField
pkg reflect, method (Method) IsExported() bool
pkg reflect, method (StructField) IsExported() bool
pkg reflect, method (Value) CanConvert(Type) bool
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}

View file

@ -989,6 +989,18 @@ func Foo() bool {
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
<p><!-- CL 334669 -->
The new
<a href="/pkg/reflect/#Value.CanConvert"><code>Value.CanConvert</code></a>
method reports whether a value can be converted to a type.
This may be used to avoid a panic when converting a slice to an
array pointer type if the slice is too short.
Previously it was sufficient to use
<a href="/pkg/reflect/#Type.ConvertibleTo"><code>Type.ConvertibleTo</code></a>
for this, but the newly permitted conversion from slice to array
pointer type can panic even if the types are convertible.
</p>
<p><!-- CL 266197 -->
The new
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>

View file

@ -446,35 +446,20 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul
return result
}
// parameterUpdateMu protects the Offset field of function/method parameters (a subset of structure Fields)
var parameterUpdateMu sync.Mutex
// FieldOffsetOf returns a concurrency-safe version of f.Offset
func FieldOffsetOf(f *types.Field) int64 {
parameterUpdateMu.Lock()
defer parameterUpdateMu.Unlock()
return f.Offset
}
func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isReturn, setNname bool) {
// Everything except return values in registers has either a frame home (if not in a register) or a frame spill location.
if !isReturn || len(a.Registers) == 0 {
// The type frame offset DOES NOT show effects of minimum frame size.
// Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set
parameterUpdateMu.Lock()
defer parameterUpdateMu.Unlock()
off := a.FrameOffset(result)
fOffset := f.Offset
if fOffset == types.BOGUS_FUNARG_OFFSET {
// Set the Offset the first time. After that, we may recompute it, but it should never change.
f.Offset = off
if f.Nname != nil {
// always set it in this case.
if setNname && f.Nname != nil {
f.Nname.(*ir.Name).SetFrameOffset(off)
f.Nname.(*ir.Name).SetIsOutputParamInRegisters(false)
}
} else if fOffset != off {
base.Fatalf("offset for %s at %s changed from %d to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset, off)
} else {
base.Fatalf("field offset for %s at %s has been set to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset)
}
} else {
if setNname && f.Nname != nil {

View file

@ -1296,7 +1296,7 @@ func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrument
if f.Sym.IsBlank() {
continue
}
offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), abi.FieldOffsetOf(f), addr)
offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), f.Offset, addr)
s.instrumentFields(f.Type, offptr, kind)
}
}
@ -5053,19 +5053,23 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
ft := fn.Type()
off := t.FieldOff(12) // TODO register args: be sure this isn't a hardcoded param stack offset.
args := n.Args
i0 := 0
// Set receiver (for interface calls). Always a pointer.
if rcvr != nil {
p := s.newValue1I(ssa.OpOffPtr, ft.Recv().Type.PtrTo(), off, addr)
s.store(types.Types[types.TUINTPTR], p, rcvr)
i0 = 1
}
// Set receiver (for method calls).
if n.Op() == ir.OCALLMETH {
base.Fatalf("OCALLMETH missed by walkCall")
}
// Set other args.
for _, f := range ft.Params().Fields().Slice() {
s.storeArgWithBase(args[0], f.Type, addr, off+abi.FieldOffsetOf(f))
// This code is only used when RegabiDefer is not enabled, and arguments are always
// passed on stack.
for i, f := range ft.Params().Fields().Slice() {
s.storeArgWithBase(args[0], f.Type, addr, off+params.InParam(i+i0).FrameOffset(params))
args = args[1:]
}
@ -5078,7 +5082,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
if stksize < int64(types.PtrSize) {
// We need room for both the call to deferprocStack and the call to
// the deferred function.
// TODO(register args) Revisit this if/when we pass args in registers.
stksize = int64(types.PtrSize)
}
call.AuxInt = stksize

View file

@ -2848,3 +2848,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`)
}
}

View file

@ -252,8 +252,15 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
ccExe := b.ccExe()
fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
fmt.Fprintf(h, "CC ID=%q\n", ccID)
// Include the C compiler tool ID so that if the C
// compiler changes we rebuild the package.
// But don't do that for standard library packages like net,
// so that the prebuilt .a files from a Go binary install
// don't need to be rebuilt with the local compiler.
if !p.Standard {
if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
fmt.Fprintf(h, "CC ID=%q\n", ccID)
}
}
if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
cxxExe := b.cxxExe()

View file

@ -4304,6 +4304,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()) {
@ -4311,6 +4314,9 @@ func TestConvert(t *testing.T) {
}
// 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()) {
@ -4371,6 +4377,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)
})

View file

@ -2811,6 +2811,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 {

View file

@ -1,3 +1,7 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package reflect
// VisibleFields returns all the visible fields in t, which must be a

View file

@ -1,3 +1,7 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package reflect_test
import (

View file

@ -24,6 +24,9 @@ func TestPanicOnFault(t *testing.T) {
if runtime.GOOS == "ios" {
t.Skip("iOS doesn't provide fault addresses")
}
if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
t.Skip("netbsd-arm doesn't provide fault address (golang.org/issue/45026)")
}
m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON)
if err != nil {
t.Fatalf("can't map anonymous memory: %s", err)

View file

@ -1135,13 +1135,21 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
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 {
@ -1155,16 +1163,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
}
}
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.

View file

@ -681,7 +681,7 @@ type p struct {
// 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

View file

@ -668,11 +668,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
}

View file

@ -527,6 +527,40 @@ func TestZeroTimer(t *testing.T) {
}
}
// Test that rapidly moving a timer earlier doesn't cause it to get dropped.
// Issue 47329.
func TestTimerModifiedEarlier(t *testing.T) {
past := Until(Unix(0, 0))
count := 1000
fail := 0
for i := 0; i < count; i++ {
timer := NewTimer(Hour)
for j := 0; j < 10; j++ {
if !timer.Stop() {
<-timer.C
}
timer.Reset(past)
}
deadline := NewTimer(10 * Second)
defer deadline.Stop()
now := Now()
select {
case <-timer.C:
if since := Since(now); since > 8*Second {
t.Errorf("timer took too long (%v)", since)
fail++
}
case <-deadline.C:
t.Error("deadline expired")
}
}
if fail > 0 {
t.Errorf("%d failures", fail)
}
}
// Benchmark timer latency when the thread that creates the timer is busy with
// other work and the timers must be serviced by other threads.
// https://golang.org/issue/38860

View file

@ -0,0 +1,6 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
TEXT ·G(SB),4,$0
RET

View file

@ -0,0 +1,17 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 47317: ICE when calling ABI0 function via func value.
package main
func main() { F() }
func F() interface{} {
g := G
g(1)
return G
}
func G(x int) [2]int

View file

@ -0,0 +1,7 @@
// builddir
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored