mirror of
				https://github.com/golang/go.git
				synced 2025-11-04 02:30:57 +00:00 
			
		
		
		
	Add a bunch of extra tests and benchmarks for defer, in preparation for new low-cost (open-coded) implementation of defers (see #34481), - New file defer_test.go that tests a bunch more unusual defer scenarios, including things that might have problems for open-coded defers. - Additions to callers_test.go actually verifying what the stack trace looks like for various panic or panic-recover scenarios. - Additions to crash_test.go testing several more crash scenarios involving recursive panics. - New benchmark in runtime_test.go measuring speed of panic-recover - New CGo benchmark in cgo_test.go calling from Go to C back to Go that shows defer overhead Updates #34481 Change-Id: I423523f3e05fc0229d4277dd00073289a5526188 Reviewed-on: https://go-review.googlesource.com/c/go/+/197017 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Austin Clements <austin@google.com>
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// asmcheck
 | 
						|
 | 
						|
// Copyright 2018 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 codegen
 | 
						|
 | 
						|
import "runtime"
 | 
						|
 | 
						|
// This file contains code generation tests related to the use of the
 | 
						|
// stack.
 | 
						|
 | 
						|
// Check that stack stores are optimized away.
 | 
						|
 | 
						|
// 386:"TEXT\t.*, [$]0-"
 | 
						|
// amd64:"TEXT\t.*, [$]0-"
 | 
						|
// arm:"TEXT\t.*, [$]-4-"
 | 
						|
// arm64:"TEXT\t.*, [$]0-"
 | 
						|
// mips:"TEXT\t.*, [$]-4-"
 | 
						|
// ppc64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64le:"TEXT\t.*, [$]0-"
 | 
						|
// s390x:"TEXT\t.*, [$]0-"
 | 
						|
func StackStore() int {
 | 
						|
	var x int
 | 
						|
	return *(&x)
 | 
						|
}
 | 
						|
 | 
						|
type T struct {
 | 
						|
	A, B, C, D int // keep exported fields
 | 
						|
	x, y, z    int // reset unexported fields
 | 
						|
}
 | 
						|
 | 
						|
// Check that large structs are cleared directly (issue #24416).
 | 
						|
 | 
						|
// 386:"TEXT\t.*, [$]0-"
 | 
						|
// amd64:"TEXT\t.*, [$]0-"
 | 
						|
// arm:"TEXT\t.*, [$]0-" (spills return address)
 | 
						|
// arm64:"TEXT\t.*, [$]0-"
 | 
						|
// mips:"TEXT\t.*, [$]-4-"
 | 
						|
// ppc64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64le:"TEXT\t.*, [$]0-"
 | 
						|
// s390x:"TEXT\t.*, [$]0-"
 | 
						|
func ZeroLargeStruct(x *T) {
 | 
						|
	t := T{}
 | 
						|
	*x = t
 | 
						|
}
 | 
						|
 | 
						|
// Check that structs are partially initialised directly (issue #24386).
 | 
						|
 | 
						|
// Notes:
 | 
						|
// - 386 fails due to spilling a register
 | 
						|
// amd64:"TEXT\t.*, [$]0-"
 | 
						|
// arm:"TEXT\t.*, [$]0-" (spills return address)
 | 
						|
// arm64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64le:"TEXT\t.*, [$]0-"
 | 
						|
// s390x:"TEXT\t.*, [$]0-"
 | 
						|
// Note: that 386 currently has to spill a register.
 | 
						|
func KeepWanted(t *T) {
 | 
						|
	*t = T{A: t.A, B: t.B, C: t.C, D: t.D}
 | 
						|
}
 | 
						|
 | 
						|
// Check that small array operations avoid using the stack (issue #15925).
 | 
						|
 | 
						|
// Notes:
 | 
						|
// - 386 fails due to spilling a register
 | 
						|
// - arm & mips fail due to softfloat calls
 | 
						|
// amd64:"TEXT\t.*, [$]0-"
 | 
						|
// arm64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64le:"TEXT\t.*, [$]0-"
 | 
						|
// s390x:"TEXT\t.*, [$]0-"
 | 
						|
func ArrayAdd64(a, b [4]float64) [4]float64 {
 | 
						|
	return [4]float64{a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]}
 | 
						|
}
 | 
						|
 | 
						|
// Check that small array initialization avoids using the stack.
 | 
						|
 | 
						|
// 386:"TEXT\t.*, [$]0-"
 | 
						|
// amd64:"TEXT\t.*, [$]0-"
 | 
						|
// arm:"TEXT\t.*, [$]0-" (spills return address)
 | 
						|
// arm64:"TEXT\t.*, [$]0-"
 | 
						|
// mips:"TEXT\t.*, [$]-4-"
 | 
						|
// ppc64:"TEXT\t.*, [$]0-"
 | 
						|
// ppc64le:"TEXT\t.*, [$]0-"
 | 
						|
// s390x:"TEXT\t.*, [$]0-"
 | 
						|
func ArrayInit(i, j int) [4]int {
 | 
						|
	return [4]int{i, 0, j, 0}
 | 
						|
}
 | 
						|
 | 
						|
// Check that assembly output has matching offset and base register
 | 
						|
// (issue #21064).
 | 
						|
 | 
						|
func check_asmout(a, b int) int {
 | 
						|
	runtime.GC() // use some frame
 | 
						|
	// amd64:`.*b\+24\(SP\)`
 | 
						|
	// arm:`.*b\+4\(FP\)`
 | 
						|
	return b
 | 
						|
}
 | 
						|
 | 
						|
// Check that simple functions get promoted to nosplit, even when
 | 
						|
// they might panic in various ways. See issue 31219.
 | 
						|
// amd64:"TEXT\t.*NOSPLIT.*"
 | 
						|
func MightPanic(a []int, i, j, k, s int) {
 | 
						|
	_ = a[i]     // panicIndex
 | 
						|
	_ = a[i:j]   // panicSlice
 | 
						|
	_ = a[i:j:k] // also panicSlice
 | 
						|
	_ = i << s   // panicShift
 | 
						|
	_ = i / j    // panicDivide
 | 
						|
}
 | 
						|
 | 
						|
// Put a defer in a loop, so second defer is not open-coded
 | 
						|
func Defer() {
 | 
						|
	for i := 0; i < 2; i++ {
 | 
						|
		defer func() {}()
 | 
						|
	}
 | 
						|
	// amd64:`CALL\truntime\.deferprocStack`
 | 
						|
	defer func() {}()
 | 
						|
}
 |