// and setting those fields to nil. Doing so
// would reduce the binary size of typical
// programs like cmd/go by ~2%.
- d.markMethodType(m)
+ d.mark(m.mtyp(), m.src)
rem = append(rem, m)
} else {
rem = append(rem, m)
}
// methodref holds the relocations from a receiver type symbol to its
-// method. There are four relocations, one for each of the fields in
-// the reflect.method struct: mtyp, typ, ifn, and tfn.
+// method. There are three relocations, one for each of the fields in
+// the reflect.method struct: mtyp, ifn, and tfn.
type methodref struct {
m methodsig
src *LSym // receiver type symbol
- r [4]*Reloc // R_METHOD relocations to fields of runtime.method
+ r [3]*Reloc // R_METHOD relocations to fields of runtime.method
}
func (m methodref) mtyp() *LSym { return m.r[0].Sym }
-func (m methodref) typ() *LSym { return m.r[1].Sym }
-func (m methodref) ifn() *LSym { return m.r[2].Sym }
-func (m methodref) tfn() *LSym { return m.r[3].Sym }
+func (m methodref) ifn() *LSym { return m.r[1].Sym }
+func (m methodref) tfn() *LSym { return m.r[2].Sym }
func (m methodref) isExported() bool {
for _, r := range m.m {
}
}
-// markMethodType marks just a method's types as reachable.
-func (d *deadcodepass) markMethodType(m methodref) {
- d.mark(m.mtyp(), m.src)
- d.mark(m.typ(), m.src)
-}
-
// init marks all initial symbols as reachable.
// In a typical binary, this is INITENTRY.
func (d *deadcodepass) init() {
name *string // name of method
pkgPath *string // nil for exported Names; otherwise import path
mtyp *rtype // method type (without receiver)
- typ *rtype // .(*FuncType) underneath (with receiver)
ifn unsafe.Pointer // fn used in interface call (one-word receiver)
tfn unsafe.Pointer // fn used for normal method call
}
func (t *rtype) common() *rtype { return t }
-func (t *uncommonType) Method(i int) (m Method) {
- if t == nil || i < 0 || i >= len(t.methods) {
+func (t *rtype) NumMethod() int {
+ if t.Kind() == Interface {
+ tt := (*interfaceType)(unsafe.Pointer(t))
+ return tt.NumMethod()
+ }
+ ut := t.uncommon()
+ if ut == nil {
+ return 0
+ }
+ return len(ut.methods)
+}
+
+func (t *rtype) Method(i int) (m Method) {
+ if t.Kind() == Interface {
+ tt := (*interfaceType)(unsafe.Pointer(t))
+ return tt.Method(i)
+ }
+ ut := t.uncommon()
+
+ if ut == nil || i < 0 || i >= len(ut.methods) {
panic("reflect: Method index out of range")
}
- p := &t.methods[i]
+ p := &ut.methods[i]
if p.name != nil {
m.Name = *p.name
}
m.PkgPath = *p.pkgPath
fl |= flagStickyRO
}
- mt := p.typ
+ ft := (*funcType)(unsafe.Pointer(p.mtyp))
+ in := make([]Type, 0, 1+len(ft.in()))
+ in = append(in, t)
+ for _, arg := range ft.in() {
+ in = append(in, arg)
+ }
+ out := make([]Type, 0, len(ft.out()))
+ for _, ret := range ft.out() {
+ out = append(out, ret)
+ }
+ mt := FuncOf(in, out, p.mtyp.IsVariadic())
m.Type = mt
fn := unsafe.Pointer(&p.tfn)
- m.Func = Value{mt, fn, fl}
+ m.Func = Value{mt.(*rtype), fn, fl}
m.Index = i
- return
+ return m
}
-func (t *uncommonType) NumMethod() int {
- if t == nil {
- return 0
+func (t *rtype) MethodByName(name string) (m Method, ok bool) {
+ if t.Kind() == Interface {
+ tt := (*interfaceType)(unsafe.Pointer(t))
+ return tt.MethodByName(name)
}
- return len(t.methods)
-}
-
-func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
- if t == nil {
- return
+ ut := t.uncommon()
+ if ut == nil {
+ return Method{}, false
}
var p *method
- for i := range t.methods {
- p = &t.methods[i]
+ for i := range ut.methods {
+ p = &ut.methods[i]
if p.name != nil && *p.name == name {
return t.Method(i), true
}
}
- return
-}
-
-// TODO(rsc): gc supplies these, but they are not
-// as efficient as they could be: they have commonType
-// as the receiver instead of *rtype.
-func (t *rtype) NumMethod() int {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.NumMethod()
- }
- return t.uncommon().NumMethod()
-}
-
-func (t *rtype) Method(i int) (m Method) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.Method(i)
- }
- return t.uncommon().Method(i)
-}
-
-func (t *rtype) MethodByName(name string) (m Method, ok bool) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.MethodByName(name)
- }
- return t.uncommon().MethodByName(name)
+ return Method{}, false
}
func (t *rtype) PkgPath() string {