Switch to typeless generated deepcopy functions for less reflection

This commit is contained in:
Dr. Stefan Schimanski 2016-07-08 12:56:43 +02:00
parent 6049623a13
commit 61cde63622
3 changed files with 29 additions and 16 deletions

View File

@ -204,6 +204,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
const (
apiPackagePath = "k8s.io/kubernetes/pkg/api"
conversionPackagePath = "k8s.io/kubernetes/pkg/conversion"
runtimePackagePath = "k8s.io/kubernetes/pkg/runtime"
)
// genDeepCopy produces a file with autogenerated deep-copy functions.
@ -384,8 +385,10 @@ func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
sw.Do("if err := $.scheme|raw$.AddGeneratedDeepCopyFuncs(\n", map[string]interface{}{
"scheme": scheme,
})
reflect := c.Universe.Type(types.Name{Package: "reflect", Name: "TypeOf"})
for _, t := range g.typesForInit {
sw.Do(fmt.Sprintf("%s,\n", g.funcNameTmpl(t)), argsFromType(t))
g.imports.AddType(reflect)
sw.Do(fmt.Sprintf("conversion.GeneratedDeepCopyFunc{Fn: %s, InType: reflect.TypeOf(func() *$.type|raw$ {var x *$.type|raw$; return x}())},\n", g.funcNameTmpl(t)), argsFromType(t))
}
sw.Do("); err != nil {\n", nil)
sw.Do("// if one of the deep copy functions is malformed, detect it immediately.\n", nil)
@ -425,10 +428,11 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri
sw := generator.NewSnippetWriter(w, c, "$", "$")
funcName := g.funcNameTmpl(t)
sw.Do(fmt.Sprintf("func %s(in *$.type|raw$, out *$.type|raw$, c *$.Cloner|raw$) error {\n", funcName), g.withGlobals(argsFromType(t)))
sw.Do(fmt.Sprintf("func %s(in interface{}, out interface{}, c *$.Cloner|raw$) error {{\n", funcName), g.withGlobals(argsFromType(t)))
sw.Do("in := in.(*$.type|raw$)\nout := out.(*$.type|raw$)\n", g.withGlobals(argsFromType(t)))
g.generateFor(t, sw)
sw.Do("return nil\n", nil)
sw.Do("}\n\n", nil)
sw.Do("}}\n\n", nil)
return sw.Error()
}
@ -531,6 +535,10 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
}
func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
if len(t.Members) == 0 {
// at least do something with in/out to avoid "declared and not used" errors
sw.Do("_ = in\n_ = out\n", nil)
}
for _, m := range t.Members {
t := m.Type
if t.Kind == types.Alias {

View File

@ -25,14 +25,14 @@ import (
type Cloner struct {
// Map from the type to a function which can do the deep copy.
deepCopyFuncs map[reflect.Type]reflect.Value
generatedDeepCopyFuncs map[reflect.Type]reflect.Value
generatedDeepCopyFuncs map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error
}
// NewCloner creates a new Cloner object.
func NewCloner() *Cloner {
c := &Cloner{
deepCopyFuncs: map[reflect.Type]reflect.Value{},
generatedDeepCopyFuncs: map[reflect.Type]reflect.Value{},
generatedDeepCopyFuncs: map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error{},
}
if err := c.RegisterDeepCopyFunc(byteSliceDeepCopy); err != nil {
// If one of the deep-copy functions is malformed, detect it immediately.
@ -103,15 +103,17 @@ func (c *Cloner) RegisterDeepCopyFunc(deepCopyFunc interface{}) error {
return nil
}
// GeneratedDeepCopyFunc bundles an untyped generated deep-copy function of a type
// with a reflection type object used as a key to lookup the deep-copy function.
type GeneratedDeepCopyFunc struct {
Fn func(in interface{}, out interface{}, c *Cloner) error
InType reflect.Type
}
// Similar to RegisterDeepCopyFunc, but registers deep copy function that were
// automatically generated.
func (c *Cloner) RegisterGeneratedDeepCopyFunc(deepCopyFunc interface{}) error {
fv := reflect.ValueOf(deepCopyFunc)
ft := fv.Type()
if err := verifyDeepCopyFunctionSignature(ft); err != nil {
return err
}
c.generatedDeepCopyFuncs[ft.In(0)] = fv
func (c *Cloner) RegisterGeneratedDeepCopyFunc(fn GeneratedDeepCopyFunc) error {
c.generatedDeepCopyFuncs[fn.InType] = fn.Fn
return nil
}
@ -146,7 +148,10 @@ func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) {
return c.customDeepCopy(src, fv)
}
if fv, ok := c.generatedDeepCopyFuncs[inType]; ok {
return c.customDeepCopy(src, fv)
var outValue reflect.Value
outValue = reflect.New(inType.Elem())
err := fv(src.Interface(), outValue.Interface(), c)
return outValue, err
}
return c.defaultDeepCopy(src)
}

View File

@ -357,9 +357,9 @@ func (s *Scheme) AddDeepCopyFuncs(deepCopyFuncs ...interface{}) error {
// Similar to AddDeepCopyFuncs, but registers deep-copy functions that were
// automatically generated.
func (s *Scheme) AddGeneratedDeepCopyFuncs(deepCopyFuncs ...interface{}) error {
for _, f := range deepCopyFuncs {
if err := s.cloner.RegisterGeneratedDeepCopyFunc(f); err != nil {
func (s *Scheme) AddGeneratedDeepCopyFuncs(deepCopyFuncs ...conversion.GeneratedDeepCopyFunc) error {
for _, fn := range deepCopyFuncs {
if err := s.cloner.RegisterGeneratedDeepCopyFunc(fn); err != nil {
return err
}
}