Skip to content

Commit

Permalink
Merge pull request #111 from golang/master
Browse files Browse the repository at this point in the history
PR
  • Loading branch information
ferrmin authored Jul 23, 2021
2 parents f7096b1 + 052da57 commit 2a54999
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 39 deletions.
21 changes: 3 additions & 18 deletions src/cmd/compile/internal/abi/abiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 7 additions & 4 deletions src/cmd/compile/internal/ssagen/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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:]
}

Expand All @@ -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
Expand Down
20 changes: 9 additions & 11 deletions src/runtime/malloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/runtime2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions src/runtime/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
34 changes: 34 additions & 0 deletions src/time/sleep_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions test/fixedbugs/issue47317.dir/a.s
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions test/fixedbugs/issue47317.dir/x.go
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions test/fixedbugs/issue47317.go
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 2a54999

Please sign in to comment.