aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@golang.org>2016-02-23 11:31:13 -0500
committerDavid Crawshaw <crawshaw@golang.org>2016-03-09 01:25:18 +0000
commit8df733bd2210e086c179ffb898d4e960f8d62df7 (patch)
treee9d7ec93cd4bf8fdb277e1128c1c687ae4543707 /src/runtime
parentb050adeebddb269cfb57f2c84acef7430326b6d5 (diff)
downloadgo-8df733bd2210e086c179ffb898d4e960f8d62df7.tar.xz
cmd/compile: remove slices from rtype.funcType
Alternative to golang.org/cl/19852. This memory layout doesn't have an easy type representation, but it is noticeably smaller than the current funcType, and saves significant extra space. Some notes on the layout are in reflect/type.go: // A *rtype for each in and out parameter is stored in an array that // directly follows the funcType (and possibly its uncommonType). So // a function type with one method, one input, and one output is: // // struct { // funcType // uncommonType // [2]*rtype // [0] is in, [1] is out // uncommonTypeSliceContents // } There are three arbitrary limits introduced by this CL: 1. No more than 65535 function input parameters. 2. No more than 32767 function output parameters. 3. reflect.FuncOf is limited to 128 parameters. I don't think these are limits in practice, but are worth noting. Reduces godoc binary size by 2.4%, 330KB. For #6853. Change-Id: I225c0a0516ebdbe92d41dfdf43f716da42dfe347 Reviewed-on: https://go-review.googlesource.com/19916 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/mfinal.go11
-rw-r--r--src/runtime/syscall_windows.go6
-rw-r--r--src/runtime/type.go30
3 files changed, 36 insertions, 11 deletions
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 6d5378200e..1238d4a053 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -331,10 +331,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
throw("runtime.SetFinalizer: second argument is " + ftyp._string + ", not a function")
}
ft := (*functype)(unsafe.Pointer(ftyp))
- if ft.dotdotdot || len(ft.in) != 1 {
+ if ft.dotdotdot() {
+ throw("runtime.SetFinalizer: cannot pass " + etyp._string + " to finalizer " + ftyp._string + " because dotdotdot")
+ }
+ if ft.dotdotdot() || ft.inCount != 1 {
throw("runtime.SetFinalizer: cannot pass " + etyp._string + " to finalizer " + ftyp._string)
}
- fint := ft.in[0]
+ fint := ft.in()[0]
switch {
case fint == etyp:
// ok - same type
@@ -359,8 +362,8 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
okarg:
// compute size needed for return parameters
nret := uintptr(0)
- for _, t := range ft.out {
- nret = round(nret, uintptr(t.align)) + t.size
+ for _, t := range ft.out() {
+ nret = round(nret, uintptr(t.align)) + uintptr(t.size)
}
nret = round(nret, sys.PtrSize)
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 081516c70a..ebfa32ff8c 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -45,15 +45,15 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
panic("compileCallback: not a function")
}
ft := (*functype)(unsafe.Pointer(fn._type))
- if len(ft.out) != 1 {
+ if len(ft.out()) != 1 {
panic("compileCallback: function must have one output parameter")
}
uintptrSize := unsafe.Sizeof(uintptr(0))
- if ft.out[0].size != uintptrSize {
+ if ft.out()[0].size != uintptrSize {
panic("compileCallback: output parameter size is wrong")
}
argsize := uintptr(0)
- for _, t := range ft.in {
+ for _, t := range ft.in() {
if t.size > uintptrSize {
panic("compileCallback: input parameter size is wrong")
}
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 9c9b5fb8cc..c504e2d294 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -128,6 +128,29 @@ func (t *_type) name() string {
return t._string[i+1:]
}
+func (t *functype) in() []*_type {
+ // See funcType in reflect/type.go for details on data layout.
+ uadd := uintptr(unsafe.Sizeof(functype{}))
+ if t.typ.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommontype{})
+ }
+ return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[:t.inCount]
+}
+
+func (t *functype) out() []*_type {
+ // See funcType in reflect/type.go for details on data layout.
+ uadd := uintptr(unsafe.Sizeof(functype{}))
+ if t.typ.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommontype{})
+ }
+ outCount := t.outCount & (1<<15 - 1)
+ return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount]
+}
+
+func (t *functype) dotdotdot() bool {
+ return t.outCount&(1<<15) != 0
+}
+
type method struct {
name *string
pkgpath *string
@@ -187,10 +210,9 @@ type slicetype struct {
}
type functype struct {
- typ _type
- dotdotdot bool
- in []*_type
- out []*_type
+ typ _type
+ inCount uint16
+ outCount uint16
}
type ptrtype struct {