aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorKeith Randall <khr@google.com>2019-02-05 16:22:38 -0800
committerKeith Randall <khr@golang.org>2019-03-18 20:10:55 +0000
commitd949d0b9252be1fffeadd65183a6bab3acf3de7a (patch)
tree842d96e7575d306fafd07322dbd7771ba56929ea /src/runtime
parent991c85a750574a608daf70330e26070f8cd97bb4 (diff)
downloadgo-d949d0b9252be1fffeadd65183a6bab3acf3de7a.tar.xz
cmd/compile: reorganize init functions
Instead of writing an init function per package that does the same thing for every package, just write that implementation once in the runtime. Change the compiler to generate a data structure that encodes the required initialization operations. Reduces cmd/go binary size by 0.3%+. Most of the init code is gone, including all the corresponding stack map info. The .inittask structures that replace them are quite a bit smaller. Most usefully to me, there is no longer an init function in every -S output. (There is an .inittask global there, but it's much less distracting.) After this CL we could change the name of the "init.ializers" function back to just "init". Update #6853 R=go1.13 Change-Id: Iec82b205cc52fe3ade4d36406933c97dbc9c01b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/161337 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/panic.go4
-rw-r--r--src/runtime/proc.go48
2 files changed, 40 insertions, 12 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 918ab7682a..543fd23c01 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -183,10 +183,6 @@ func panicmem() {
panic(memoryError)
}
-func throwinit() {
- throw("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
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 6e56b4b1d1..a077a5da03 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -82,11 +82,11 @@ var (
raceprocctx0 uintptr
)
-//go:linkname runtime_init runtime.init
-func runtime_init()
+//go:linkname runtime_inittask runtime..inittask
+var runtime_inittask initTask
-//go:linkname main_init main.init
-func main_init()
+//go:linkname main_inittask main..inittask
+var main_inittask initTask
// main_init_done is a signal used by cgocallbackg that initialization
// has been completed. It is made before _cgo_notify_runtime_init_done,
@@ -144,7 +144,7 @@ func main() {
throw("runtime.main not on m0")
}
- runtime_init() // must be before defer
+ doInit(&runtime_inittask) // must be before defer
if nanotime() == 0 {
throw("nanotime returning zero")
}
@@ -184,8 +184,8 @@ func main() {
cgocall(_cgo_notify_runtime_init_done, nil)
}
- fn := main_init // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
- fn()
+ doInit(&main_inittask)
+
close(main_init_done)
needUnlock = false
@@ -196,7 +196,7 @@ func main() {
// has a main, but it is not executed.
return
}
- fn = main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
+ fn := main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
fn()
if raceenabled {
racefini()
@@ -5185,3 +5185,35 @@ func gcd(a, b uint32) uint32 {
}
return a
}
+
+// An initTask represents the set of initializations that need to be done for a package.
+type initTask struct {
+ // TODO: pack the first 3 fields more tightly?
+ state uintptr // 0 = uninitialized, 1 = in progress, 2 = done
+ ndeps uintptr
+ nfns uintptr
+ // followed by ndeps instances of an *initTask, one per package depended on
+ // followed by nfns pcs, one per init function to run
+}
+
+func doInit(t *initTask) {
+ switch t.state {
+ case 2: // fully initialized
+ return
+ case 1: // initialization in progress
+ throw("recursive call during initialization - linker skew")
+ default: // not initialized yet
+ t.state = 1 // initialization in progress
+ for i := uintptr(0); i < t.ndeps; i++ {
+ p := add(unsafe.Pointer(t), (3+i)*sys.PtrSize)
+ t2 := *(**initTask)(p)
+ doInit(t2)
+ }
+ for i := uintptr(0); i < t.nfns; i++ {
+ p := add(unsafe.Pointer(t), (3+t.ndeps+i)*sys.PtrSize)
+ f := *(*func())(unsafe.Pointer(&p))
+ f()
+ }
+ t.state = 2 // initialization done
+ }
+}