mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
build: merge the great pkg/ rename into dev.power64
This also removes pkg/runtime/traceback_lr.c, which was ported to Go in an earlier commit and then moved to runtime/traceback.go. Reviewer: rsc@golang.org rsc: LGTM
This commit is contained in:
commit
2bd616b1a7
2208 changed files with 400 additions and 852 deletions
216
src/runtime/panic.go
Normal file
216
src/runtime/panic.go
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
// Copyright 2014 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 runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var indexError = error(errorString("index out of range"))
|
||||
|
||||
func panicindex() {
|
||||
panic(indexError)
|
||||
}
|
||||
|
||||
var sliceError = error(errorString("slice bounds out of range"))
|
||||
|
||||
func panicslice() {
|
||||
panic(sliceError)
|
||||
}
|
||||
|
||||
var divideError = error(errorString("integer divide by zero"))
|
||||
|
||||
func panicdivide() {
|
||||
panic(divideError)
|
||||
}
|
||||
|
||||
func throwreturn() {
|
||||
gothrow("no return at end of a typed function - compiler is broken")
|
||||
}
|
||||
|
||||
func throwinit() {
|
||||
gothrow("recursive call during initialization - linker skew")
|
||||
}
|
||||
|
||||
// Create a new deferred function fn with siz bytes of arguments.
|
||||
// The compiler turns a defer statement into a call to this.
|
||||
//go:nosplit
|
||||
func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
|
||||
// the arguments of fn are in a perilous state. The stack map
|
||||
// for deferproc does not describe them. So we can't let garbage
|
||||
// collection or stack copying trigger until we've copied them out
|
||||
// to somewhere safe. deferproc_m does that. Until deferproc_m,
|
||||
// we can only call nosplit routines.
|
||||
argp := uintptr(unsafe.Pointer(&fn))
|
||||
argp += unsafe.Sizeof(fn)
|
||||
if GOARCH == "arm" || GOARCH == "power64" || GOARCH == "power64le" {
|
||||
argp += ptrSize // skip caller's saved link register
|
||||
}
|
||||
mp := acquirem()
|
||||
mp.scalararg[0] = uintptr(siz)
|
||||
mp.ptrarg[0] = unsafe.Pointer(fn)
|
||||
mp.scalararg[1] = argp
|
||||
mp.scalararg[2] = getcallerpc(unsafe.Pointer(&siz))
|
||||
|
||||
if mp.curg != getg() {
|
||||
// go code on the m stack can't defer
|
||||
gothrow("defer on m")
|
||||
}
|
||||
|
||||
onM(deferproc_m)
|
||||
|
||||
releasem(mp)
|
||||
|
||||
// deferproc returns 0 normally.
|
||||
// a deferred func that stops a panic
|
||||
// makes the deferproc return 1.
|
||||
// the code the compiler generates always
|
||||
// checks the return value and jumps to the
|
||||
// end of the function if deferproc returns != 0.
|
||||
return0()
|
||||
// No code can go here - the C return register has
|
||||
// been set and must not be clobbered.
|
||||
}
|
||||
|
||||
// Each P holds pool for defers with arg sizes 8, 24, 40, 56 and 72 bytes.
|
||||
// Memory block is 40 (24 for 32 bits) bytes larger due to Defer header.
|
||||
// This maps exactly to malloc size classes.
|
||||
|
||||
// defer size class for arg size sz
|
||||
func deferclass(siz uintptr) uintptr {
|
||||
return (siz + 7) >> 4
|
||||
}
|
||||
|
||||
// total size of memory block for defer with arg size sz
|
||||
func totaldefersize(siz uintptr) uintptr {
|
||||
return (unsafe.Sizeof(_defer{}) - unsafe.Sizeof(_defer{}.args)) + round(siz, ptrSize)
|
||||
}
|
||||
|
||||
// Ensure that defer arg sizes that map to the same defer size class
|
||||
// also map to the same malloc size class.
|
||||
func testdefersizes() {
|
||||
var m [len(p{}.deferpool)]int32
|
||||
|
||||
for i := range m {
|
||||
m[i] = -1
|
||||
}
|
||||
for i := uintptr(0); ; i++ {
|
||||
defersc := deferclass(i)
|
||||
if defersc >= uintptr(len(m)) {
|
||||
break
|
||||
}
|
||||
siz := goroundupsize(totaldefersize(i))
|
||||
if m[defersc] < 0 {
|
||||
m[defersc] = int32(siz)
|
||||
continue
|
||||
}
|
||||
if m[defersc] != int32(siz) {
|
||||
print("bad defer size class: i=", i, " siz=", siz, " defersc=", defersc, "\n")
|
||||
gothrow("bad defer size class")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a Defer, usually using per-P pool.
|
||||
// Each defer must be released with freedefer.
|
||||
// Note: runs on M stack
|
||||
func newdefer(siz int32) *_defer {
|
||||
var d *_defer
|
||||
sc := deferclass(uintptr(siz))
|
||||
mp := acquirem()
|
||||
if sc < uintptr(len(p{}.deferpool)) {
|
||||
pp := mp.p
|
||||
d = pp.deferpool[sc]
|
||||
if d != nil {
|
||||
pp.deferpool[sc] = d.link
|
||||
}
|
||||
}
|
||||
if d == nil {
|
||||
// deferpool is empty or just a big defer
|
||||
total := goroundupsize(totaldefersize(uintptr(siz)))
|
||||
d = (*_defer)(gomallocgc(total, conservative, 0))
|
||||
}
|
||||
d.siz = siz
|
||||
d.special = false
|
||||
gp := mp.curg
|
||||
d.link = gp._defer
|
||||
gp._defer = d
|
||||
releasem(mp)
|
||||
return d
|
||||
}
|
||||
|
||||
// Free the given defer.
|
||||
// The defer cannot be used after this call.
|
||||
func freedefer(d *_defer) {
|
||||
if d.special {
|
||||
return
|
||||
}
|
||||
sc := deferclass(uintptr(d.siz))
|
||||
if sc < uintptr(len(p{}.deferpool)) {
|
||||
mp := acquirem()
|
||||
pp := mp.p
|
||||
d.link = pp.deferpool[sc]
|
||||
pp.deferpool[sc] = d
|
||||
releasem(mp)
|
||||
// No need to wipe out pointers in argp/pc/fn/args,
|
||||
// because we empty the pool before GC.
|
||||
}
|
||||
}
|
||||
|
||||
// Run a deferred function if there is one.
|
||||
// The compiler inserts a call to this at the end of any
|
||||
// function which calls defer.
|
||||
// If there is a deferred function, this will call runtime·jmpdefer,
|
||||
// which will jump to the deferred function such that it appears
|
||||
// to have been called by the caller of deferreturn at the point
|
||||
// just before deferreturn was called. The effect is that deferreturn
|
||||
// is called again and again until there are no more deferred functions.
|
||||
// Cannot split the stack because we reuse the caller's frame to
|
||||
// call the deferred function.
|
||||
|
||||
// The single argument isn't actually used - it just has its address
|
||||
// taken so it can be matched against pending defers.
|
||||
//go:nosplit
|
||||
func deferreturn(arg0 uintptr) {
|
||||
gp := getg()
|
||||
d := gp._defer
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
argp := uintptr(unsafe.Pointer(&arg0))
|
||||
if d.argp != argp {
|
||||
return
|
||||
}
|
||||
|
||||
// Moving arguments around.
|
||||
// Do not allow preemption here, because the garbage collector
|
||||
// won't know the form of the arguments until the jmpdefer can
|
||||
// flip the PC over to fn.
|
||||
mp := acquirem()
|
||||
memmove(unsafe.Pointer(argp), unsafe.Pointer(&d.args), uintptr(d.siz))
|
||||
fn := d.fn
|
||||
gp._defer = d.link
|
||||
freedefer(d)
|
||||
releasem(mp)
|
||||
jmpdefer(fn, argp)
|
||||
}
|
||||
|
||||
// Goexit terminates the goroutine that calls it. No other goroutine is affected.
|
||||
// Goexit runs all deferred calls before terminating the goroutine.
|
||||
//
|
||||
// Calling Goexit from the main goroutine terminates that goroutine
|
||||
// without func main returning. Since func main has not returned,
|
||||
// the program continues execution of other goroutines.
|
||||
// If all other goroutines exit, the program crashes.
|
||||
func Goexit() {
|
||||
// Run all deferred functions for the current goroutine.
|
||||
gp := getg()
|
||||
for gp._defer != nil {
|
||||
d := gp._defer
|
||||
gp._defer = d.link
|
||||
reflectcall(unsafe.Pointer(d.fn), unsafe.Pointer(&d.args), uint32(d.siz), uint32(d.siz))
|
||||
freedefer(d)
|
||||
// Note: we ignore recovers here because Goexit isn't a panic
|
||||
}
|
||||
goexit()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue