Skip to content

Commit 7004afe

Browse files
committed
reduce embed and type conversion allocation overhead
1 parent 66693e8 commit 7004afe

2 files changed

Lines changed: 92 additions & 25 deletions

File tree

internal/goembed/goembed.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type VarData struct {
2727
type VarMap map[string]VarData
2828

2929
func LoadDirectives(fset *token.FileSet, files []*ast.File) (VarMap, error) {
30-
if len(files) == 0 {
30+
if len(files) == 0 || !hasEmbedDirective(files) {
3131
return nil, nil
3232
}
3333
byVar := make(VarMap)
@@ -89,6 +89,25 @@ func LoadDirectives(fset *token.FileSet, files []*ast.File) (VarMap, error) {
8989
return byVar, nil
9090
}
9191

92+
func hasEmbedDirective(files []*ast.File) bool {
93+
for _, file := range files {
94+
if file == nil {
95+
continue
96+
}
97+
for _, group := range file.Comments {
98+
if group == nil {
99+
continue
100+
}
101+
for _, comment := range group.List {
102+
if comment != nil && strings.Contains(comment.Text, "go:embed") {
103+
return true
104+
}
105+
}
106+
}
107+
}
108+
return false
109+
}
110+
92111
func FileImportsEmbed(file *ast.File) bool {
93112
for _, imp := range file.Imports {
94113
if imp == nil || imp.Path == nil {

ssa/type_cvt.go

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -234,51 +234,87 @@ func (p goTypes) cvtFunc(sig *types.Signature, recv *types.Var) (raw *types.Sign
234234

235235
func (p goTypes) cvtTuple(t *types.Tuple) (*types.Tuple, bool) {
236236
n := t.Len()
237-
vars := make([]*types.Var, n)
238-
needcvt := false
237+
var vars []*types.Var
239238
for i := 0; i < n; i++ {
240239
v := t.At(i)
241-
if t, cvt := p.cvtType(v.Type()); cvt {
242-
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
243-
needcvt = true
240+
if raw, cvt := p.cvtType(v.Type()); cvt {
241+
if vars == nil {
242+
vars = make([]*types.Var, n)
243+
for j := 0; j < i; j++ {
244+
vars[j] = t.At(j)
245+
}
246+
}
247+
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), raw)
248+
}
249+
if vars != nil {
250+
vars[i] = v
244251
}
245-
vars[i] = v
246252
}
247-
if needcvt {
253+
if vars != nil {
248254
return types.NewTuple(vars...), true
249255
}
250256
return t, false
251257
}
252258

253-
func (p goTypes) cvtExplicitMethods(typ *types.Interface) ([]*types.Func, bool) {
259+
func explicitMethods(typ *types.Interface) []*types.Func {
254260
n := typ.NumExplicitMethods()
255261
methods := make([]*types.Func, n)
256-
needcvt := false
262+
for i := 0; i < n; i++ {
263+
methods[i] = typ.ExplicitMethod(i)
264+
}
265+
return methods
266+
}
267+
268+
func embeddedTypes(typ *types.Interface) []types.Type {
269+
n := typ.NumEmbeddeds()
270+
embeddeds := make([]types.Type, n)
271+
for i := 0; i < n; i++ {
272+
embeddeds[i] = typ.EmbeddedType(i)
273+
}
274+
return embeddeds
275+
}
276+
277+
func (p goTypes) cvtExplicitMethods(typ *types.Interface) ([]*types.Func, bool) {
278+
n := typ.NumExplicitMethods()
279+
var methods []*types.Func
257280
for i := 0; i < n; i++ {
258281
m := typ.ExplicitMethod(i)
259282
sig := m.Type().(*types.Signature)
260283
if raw := p.cvtFunc(sig, nil); sig != raw {
284+
if methods == nil {
285+
methods = make([]*types.Func, n)
286+
for j := 0; j < i; j++ {
287+
methods[j] = typ.ExplicitMethod(j)
288+
}
289+
}
261290
m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), raw)
262-
needcvt = true
263291
}
264-
methods[i] = m
292+
if methods != nil {
293+
methods[i] = m
294+
}
265295
}
266-
return methods, needcvt
296+
return methods, methods != nil
267297
}
268298

269299
func (p goTypes) cvtEmbeddedTypes(typ *types.Interface) ([]types.Type, bool) {
270300
n := typ.NumEmbeddeds()
271-
embeddeds := make([]types.Type, n)
272-
needcvt := false
301+
var embeddeds []types.Type
273302
for i := 0; i < n; i++ {
274303
t := typ.EmbeddedType(i)
275304
if raw, cvt := p.cvtType(t); cvt {
305+
if embeddeds == nil {
306+
embeddeds = make([]types.Type, n)
307+
for j := 0; j < i; j++ {
308+
embeddeds[j] = typ.EmbeddedType(j)
309+
}
310+
}
276311
t = raw
277-
needcvt = true
278312
}
279-
embeddeds[i] = t
313+
if embeddeds != nil {
314+
embeddeds[i] = t
315+
}
280316
}
281-
return embeddeds, needcvt
317+
return embeddeds, embeddeds != nil
282318
}
283319

284320
func (p goTypes) cvtInterface(typ *types.Interface) (raw *types.Interface, cvt bool) {
@@ -293,6 +329,12 @@ func (p goTypes) cvtInterface(typ *types.Interface) (raw *types.Interface, cvt b
293329
methods, cvt1 := p.cvtExplicitMethods(typ)
294330
embeddeds, cvt2 := p.cvtEmbeddedTypes(typ)
295331
if cvt1 || cvt2 {
332+
if !cvt1 {
333+
methods = explicitMethods(typ)
334+
}
335+
if !cvt2 {
336+
embeddeds = embeddedTypes(typ)
337+
}
296338
return types.NewInterfaceType(methods, embeddeds), true
297339
}
298340
return typ, false
@@ -308,17 +350,23 @@ func (p goTypes) cvtStruct(typ *types.Struct) (raw *types.Struct, cvt bool) {
308350
p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw)
309351
}()
310352
n := typ.NumFields()
311-
flds := make([]*types.Var, n)
312-
needcvt := false
353+
var flds []*types.Var
313354
for i := 0; i < n; i++ {
314355
f := typ.Field(i)
315-
if t, cvt := p.cvtType(f.Type()); cvt {
316-
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
317-
needcvt = true
356+
if raw, cvt := p.cvtType(f.Type()); cvt {
357+
if flds == nil {
358+
flds = make([]*types.Var, n)
359+
for j := 0; j < i; j++ {
360+
flds[j] = typ.Field(j)
361+
}
362+
}
363+
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), raw, f.Anonymous())
364+
}
365+
if flds != nil {
366+
flds[i] = f
318367
}
319-
flds[i] = f
320368
}
321-
if needcvt {
369+
if flds != nil {
322370
return types.NewStruct(flds, nil), true
323371
}
324372
return typ, false

0 commit comments

Comments
 (0)