Commit af0fc839 authored by David Crawshaw's avatar David Crawshaw

cmd/compile, etc: handle many struct fields

This adds 8 bytes of binary size to every type that has methods. It is
the smallest change I could come up with for 1.7.

Fixes #16037

Change-Id: Ibe15c3165854a21768596967757864b880dbfeed
Reviewed-on: https://go-review.googlesource.com/24070Reviewed-by: default avatarKeith Randall <khr@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 53242e49
...@@ -75,7 +75,7 @@ func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{}) ...@@ -75,7 +75,7 @@ func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{})
if t.Sym == nil && len(methods(t)) == 0 { if t.Sym == nil && len(methods(t)) == 0 {
return 0 return 0
} }
return 4 + 2 + 2 return 4 + 2 + 2 + 4 + 4
} }
func makefield(name string, t *Type) *Field { func makefield(name string, t *Type) *Field {
...@@ -604,17 +604,19 @@ func dextratype(s *Sym, ot int, t *Type, dataAdd int) int { ...@@ -604,17 +604,19 @@ func dextratype(s *Sym, ot int, t *Type, dataAdd int) int {
ot = dgopkgpathOffLSym(Linksym(s), ot, typePkg(t)) ot = dgopkgpathOffLSym(Linksym(s), ot, typePkg(t))
dataAdd += 4 + 2 + 2 dataAdd += uncommonSize(t)
mcount := len(m) mcount := len(m)
if mcount != int(uint16(mcount)) { if mcount != int(uint16(mcount)) {
Fatalf("too many methods on %s: %d", t, mcount) Fatalf("too many methods on %s: %d", t, mcount)
} }
if dataAdd != int(uint16(dataAdd)) { if dataAdd != int(uint32(dataAdd)) {
Fatalf("methods are too far away on %s: %d", t, dataAdd) Fatalf("methods are too far away on %s: %d", t, dataAdd)
} }
ot = duint16(s, ot, uint16(mcount)) ot = duint16(s, ot, uint16(mcount))
ot = duint16(s, ot, uint16(dataAdd)) ot = duint16(s, ot, 0)
ot = duint32(s, ot, uint32(dataAdd))
ot = duint32(s, ot, 0)
return ot return ot
} }
......
...@@ -61,7 +61,7 @@ func decode_inuxi(p []byte, sz int) uint64 { ...@@ -61,7 +61,7 @@ func decode_inuxi(p []byte, sz int) uint64 {
func commonsize() int { return 4*SysArch.PtrSize + 8 + 8 } // runtime._type func commonsize() int { return 4*SysArch.PtrSize + 8 + 8 } // runtime._type
func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield
func uncommonSize() int { return 4 + 2 + 2 } // runtime.uncommontype func uncommonSize() int { return 4 + 2 + 2 + 4 + 4 } // runtime.uncommontype
// Type.commonType.kind // Type.commonType.kind
func decodetype_kind(s *LSym) uint8 { func decodetype_kind(s *LSym) uint8 {
...@@ -362,7 +362,7 @@ func decodetype_methods(s *LSym) []methodsig { ...@@ -362,7 +362,7 @@ func decodetype_methods(s *LSym) []methodsig {
} }
mcount := int(decode_inuxi(s.P[off+4:], 2)) mcount := int(decode_inuxi(s.P[off+4:], 2))
moff := int(decode_inuxi(s.P[off+4+2:], 2)) moff := int(decode_inuxi(s.P[off+4+2+2:], 4))
off += moff // offset to array of reflect.method values off += moff // offset to array of reflect.method values
const sizeofMethod = 4 * 4 // sizeof reflect.method in program const sizeofMethod = 4 * 4 // sizeof reflect.method in program
return decode_methodsig(s, off, sizeofMethod, mcount) return decode_methodsig(s, off, sizeofMethod, mcount)
......
...@@ -313,7 +313,9 @@ type method struct { ...@@ -313,7 +313,9 @@ type method struct {
type uncommonType struct { type uncommonType struct {
pkgPath nameOff // import path; empty for built-in types like int, string pkgPath nameOff // import path; empty for built-in types like int, string
mcount uint16 // number of methods mcount uint16 // number of methods
moff uint16 // offset from this uncommontype to [mcount]method _ uint16 // unused
moff uint32 // offset from this uncommontype to [mcount]method
_ uint32 // unused
} }
// ChanDir represents a channel type's direction. // ChanDir represents a channel type's direction.
...@@ -2584,7 +2586,7 @@ func StructOf(fields []StructField) Type { ...@@ -2584,7 +2586,7 @@ func StructOf(fields []StructField) Type {
panic("reflect.StructOf: too many methods") panic("reflect.StructOf: too many methods")
} }
ut.mcount = uint16(len(methods)) ut.mcount = uint16(len(methods))
ut.moff = uint16(unsafe.Sizeof(uncommonType{})) ut.moff = uint32(unsafe.Sizeof(uncommonType{}))
if len(fs) > 0 { if len(fs) > 0 {
repr = append(repr, ' ') repr = append(repr, ' ')
......
...@@ -323,7 +323,9 @@ type method struct { ...@@ -323,7 +323,9 @@ type method struct {
type uncommontype struct { type uncommontype struct {
pkgpath nameOff pkgpath nameOff
mcount uint16 // number of methods mcount uint16 // number of methods
moff uint16 // offset from this uncommontype to [mcount]method _ uint16 // unused
moff uint32 // offset from this uncommontype to [mcount]method
_ uint32 // unused
} }
type imethod struct { type imethod struct {
......
// +build !nacl,!android
// run
// Copyright 2016 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 main
import (
"bytes"
"fmt"
"html/template"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
)
var tmpl = template.Must(template.New("main").Parse(`
package main
type T struct {
{{range .Names}}
{{.Name}} *string
{{end}}
}
{{range .Names}}
func (t *T) Get{{.Name}}() string {
if t.{{.Name}} == nil {
return ""
}
return *t.{{.Name}}
}
{{end}}
func main() {}
`))
func main() {
const n = 5000
type Name struct{ Name string }
var t struct{ Names []Name }
for i := 0; i < n; i++ {
t.Names = append(t.Names, Name{Name: fmt.Sprintf("H%06X", i)})
}
buf := new(bytes.Buffer)
if err := tmpl.Execute(buf, t); err != nil {
log.Fatal(err)
}
dir, err := ioutil.TempDir("", "issue16037-")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
path := filepath.Join(dir, "ridiculous_number_of_fields.go")
if err := ioutil.WriteFile(path, buf.Bytes(), 0664); err != nil {
log.Fatal(err)
}
out, err := exec.Command("go", "build", "-o="+filepath.Join(dir, "out"), path).CombinedOutput()
if err != nil {
log.Fatalf("build failed: %v\n%s", err, out)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment