Skip to content

Commit 142181f

Browse files
rethinking for anons, about to try cache 5
1 parent 3fa9247 commit 142181f

File tree

4 files changed

+150
-30
lines changed

4 files changed

+150
-30
lines changed

compiler/declCache.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ func (dc *DeclCache) GetDecl(fullname string) *Decl {
4343
if decl, ok := dc.decls[fullname]; ok {
4444
dc.stats.usedCount++
4545
declCacheGlobalStats.usedCount++
46+
47+
fmt.Printf(">>> GetDecl(%q): Found\n", fullname) // TODO(grantnelson-wf): REMOVE
4648
return decl
4749
}
50+
51+
fmt.Printf(">>> GetDecl(%q): Miss\n", fullname) // TODO(grantnelson-wf): REMOVE
4852
return nil
4953
}
5054

@@ -73,20 +77,23 @@ func (dc *DeclCache) PutDecl(decl *Decl) {
7377
// since those don't invalidate dependent packages' caches.
7478
dc.stats.skippedCount++
7579
declCacheGlobalStats.skippedCount++
80+
fmt.Printf(">>> PutDecl(%q): Generic\n", decl.FullName) // TODO(grantnelson-wf): REMOVE
7681
return
7782
}
7883

7984
if !isUniqueDeclFullName(decl.FullName) {
8085
// Only cache declarations with unique names.
8186
dc.stats.skippedCount++
8287
declCacheGlobalStats.skippedCount++
88+
fmt.Printf(">>> PutDecl(%q): Not Unique\n", decl.FullName) // TODO(grantnelson-wf): REMOVE
8389
return
8490
}
8591

8692
if existing, ok := dc.decls[decl.FullName]; ok {
8793
if existing != decl {
8894
panic(fmt.Errorf(`decl cache conflict: different decls with same name: %q`, decl.FullName))
8995
}
96+
fmt.Printf(">>> PutDecl(%q): Dup\n", decl.FullName) // TODO(grantnelson-wf): REMOVE
9097
return
9198
}
9299

@@ -97,6 +104,8 @@ func (dc *DeclCache) PutDecl(decl *Decl) {
97104
dc.changed = true
98105
dc.stats.addedCount++
99106
declCacheGlobalStats.addedCount++
107+
108+
fmt.Printf(">>> PutDecl(%q): Added\n", decl.FullName) // TODO(grantnelson-wf): REMOVE
100109
}
101110

102111
func (dc *DeclCache) Read(decode func(any) error) error {

compiler/decls.go

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,15 @@ func (fc *funcContext) newVarDecl(init *types.Initializer) *Decl {
313313
return d
314314
}
315315

316-
// funcDecls translates all package-level function and methods.
317-
//
318-
// `functions` must contain all package-level function and method declarations
319-
// found in the AST. The function returns Decls that define corresponding JS
320-
// functions at runtime. For special functions like init() and main() decls will
321-
// also contain code necessary to invoke them.
322-
func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
323-
var funcDecls []*Decl
324-
var mainFunc *types.Func
316+
type funcGroup struct {
317+
fun *ast.FuncDecl
318+
o *types.Func
319+
instances []typeparams.Instance
320+
}
321+
322+
// groupFuncDecls groups all the package-level function and methods
323+
// into generic or non-generic groups.
324+
func (fc *funcContext) groupFuncDecls(functions []*ast.FuncDecl) (mainFunc *funcGroup, fns, expGenFns []*funcGroup) {
325325
for _, fun := range functions {
326326
o := fc.pkgCtx.Defs[fun.Name].(*types.Func)
327327
instances := fc.knownInstances(o)
@@ -330,29 +330,50 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
330330
continue
331331
}
332332

333-
if fun.Recv == nil {
334-
// Auxiliary decl shared by all instances of the function that defines
335-
// package-level variable by which they all are referenced,
336-
// e.g. init functions and instances of generic functions.
337-
funcDecls = append(funcDecls, fc.newFuncVarDecl(fun, o, instances))
333+
fg := &funcGroup{
334+
fun: fun,
335+
o: o,
336+
instances: instances,
338337
}
339338

340-
for _, inst := range instances {
341-
funcDecls = append(funcDecls, fc.newFuncDecl(fun, inst))
339+
generic := len(instances) > 1 || !instances[0].IsTrivial()
340+
if generic && fun.Name.IsExported() {
341+
// function is an exported generic function so it must be processed later
342+
// since it may have instances with type arguments from packages depending
343+
// on the current package.
344+
expGenFns = append(expGenFns, fg)
345+
continue
342346
}
343347

344-
if o.Name() == "main" {
345-
mainFunc = o // main() function candidate.
348+
fns = append(fns, fg)
349+
350+
if fg.o.Name() == "main" {
351+
mainFunc = fg // main() function candidate.
346352
}
347353
}
348-
if fc.pkgCtx.isMain() {
349-
if mainFunc == nil {
350-
return nil, fmt.Errorf("missing main function")
354+
355+
return mainFunc, fns, expGenFns
356+
}
357+
358+
// funcDecls translates all package-level function and methods.
359+
//
360+
// `functions` must contain all package-level function and method declarations
361+
// found in the AST. The function returns Decls that define corresponding JS
362+
// functions at runtime. For special functions like init() and main() decls will
363+
// also contain code necessary to invoke them.
364+
func (fc *funcContext) funcDecls(functions []*funcGroup) ([]*Decl, error) {
365+
var funcDecls []*Decl
366+
for _, fg := range functions {
367+
if fg.fun.Recv == nil {
368+
// Auxiliary decl shared by all instances of the function that defines
369+
// package-level variable by which they all are referenced,
370+
// e.g. init functions and instances of generic functions.
371+
funcDecls = append(funcDecls, fc.newFuncVarDecl(fg.fun, fg.o, fg.instances))
372+
}
373+
374+
for _, inst := range fg.instances {
375+
funcDecls = append(funcDecls, fc.newFuncDecl(fg.fun, inst))
351376
}
352-
// Add a special Decl for invoking main() function after the program has
353-
// been initialized. It must come after all other functions, especially all
354-
// init() functions, otherwise main() will be invoked too early.
355-
funcDecls = append(funcDecls, fc.newCallMainFuncDecl(mainFunc))
356377
}
357378
return funcDecls, nil
358379
}
@@ -479,6 +500,36 @@ func (fc *funcContext) callMainFunc(main *types.Func) ast.Stmt {
479500
return ifStmt
480501
}
481502

503+
func (fc *funcContext) groupNamedTypeDecls(typeNames typesutil.TypeNames) (typs, expGenTyps typesutil.TypeNames) {
504+
if !fc.isRoot() {
505+
panic(bailout(fmt.Errorf("functionContext.groupNamedTypeDecls() must be only called on the package-level context")))
506+
}
507+
508+
for _, o := range typeNames.Slice() {
509+
if o.IsAlias() {
510+
continue
511+
}
512+
513+
instances := fc.knownInstances(o)
514+
if len(instances) == 0 {
515+
// No instances of the type, skip it.
516+
continue
517+
}
518+
519+
generic := len(instances) > 1 || !instances[0].IsTrivial()
520+
if generic && o.Exported() {
521+
// type is an exported generic type so it must be processed later
522+
// since it may have instances with type arguments from packages depending
523+
// on the current package.
524+
expGenTyps.Add(o)
525+
continue
526+
}
527+
528+
typs.Add(o)
529+
}
530+
return typs, expGenTyps
531+
}
532+
482533
// namedTypeDecls returns Decls that define all names Go types.
483534
//
484535
// `typeNames` must contain all named types defined in the package, including

compiler/package.go

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,38 @@ func Compile(srcs *sources.Sources, declCache *DeclCache, tContext *types.Contex
177177

178178
importedPaths, importDecls := rootCtx.importDecls()
179179

180+
// Collect top-level objects and group them by if they are exported generics or not.
180181
vars, functions, typeNames := rootCtx.topLevelObjects(srcs)
182+
mainFunc, fns, expGenFns := rootCtx.groupFuncDecls(functions)
183+
typs, expGenTyps := rootCtx.groupNamedTypeDecls(typeNames)
184+
185+
// TODO(grantnelson-wf): Check cache
186+
//return fc.pkgCtx.declCache.GetDecl(fullname)
187+
181188
// More named types may be added to the list when function bodies are processed.
182-
rootCtx.pkgCtx.typeNames = typeNames
189+
rootCtx.pkgCtx.typeNames.AddAll(typs)
183190

184-
// Translate functions and variables.
191+
// Translate variables.
185192
varDecls := rootCtx.varDecls(vars)
186-
funcDecls, err := rootCtx.funcDecls(functions)
193+
194+
// Translate concrete functions.
195+
funcDecls, err := rootCtx.funcDecls(fns)
187196
if err != nil {
188197
return nil, err
189198
}
190199

191-
// It is important that we translate types *after* we've processed all
192-
// functions to make sure we've discovered all types declared inside function
200+
if rootCtx.pkgCtx.isMain() {
201+
if mainFunc == nil {
202+
return nil, fmt.Errorf("missing main function")
203+
}
204+
// Add a special Decl for invoking main() function after the program has
205+
// been initialized. It must come after all other functions, especially all
206+
// init() functions, otherwise main() will be invoked too early.
207+
funcDecls = append(funcDecls, rootCtx.newCallMainFuncDecl(mainFunc.o))
208+
}
209+
210+
// It is important that we translate current types *after* we've processed all
211+
// current functions to make sure we've discovered all types declared inside function
193212
// bodies.
194213
typeDecls, err := rootCtx.namedTypeDecls(rootCtx.pkgCtx.typeNames)
195214
if err != nil {
@@ -201,6 +220,35 @@ func Compile(srcs *sources.Sources, declCache *DeclCache, tContext *types.Contex
201220
// declarations.
202221
typeDecls = append(typeDecls, rootCtx.anonTypeDecls(rootCtx.pkgCtx.anonTypes)...)
203222

223+
// TODO(grantnelson-wf): Save cache
224+
//return fc.pkgCtx.declCache.PutDecl(d)
225+
226+
// Reset before processing exported generic types.
227+
rootCtx.pkgCtx.typeNames.Clear()
228+
rootCtx.pkgCtx.typeNames.AddAll(expGenTyps)
229+
rootCtx.pkgCtx.anonTypes = nil
230+
231+
// Translate exported generic functions.
232+
expGenfuncDecls, err := rootCtx.funcDecls(expGenFns)
233+
if err != nil {
234+
return nil, err
235+
}
236+
funcDecls = append(funcDecls, expGenfuncDecls...)
237+
238+
// It is important that we translate remaining types *after* we've processed all
239+
// remaining functions to make sure we've discovered all types declared inside function
240+
// bodies.
241+
expGenTypeDecls, err := rootCtx.namedTypeDecls(rootCtx.pkgCtx.typeNames)
242+
if err != nil {
243+
return nil, err
244+
}
245+
typeDecls = append(typeDecls, expGenTypeDecls...)
246+
247+
// Finally, anonymous types are translated the last, to make sure we've
248+
// discovered all of them referenced in functions, variable and type
249+
// declarations.
250+
typeDecls = append(typeDecls, rootCtx.anonTypeDecls(rootCtx.pkgCtx.anonTypes)...)
251+
204252
// Combine all decls in a single list in the order they must appear in the
205253
// final program.
206254
allDecls := append(append(append(importDecls, typeDecls...), varDecls...), funcDecls...)

compiler/typesutil/typenames.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,19 @@ func (tn *TypeNames) Add(name *types.TypeName) {
2424
tn.known[name] = struct{}{}
2525
}
2626

27+
func (tn *TypeNames) AddAll(other TypeNames) {
28+
for _, name := range other.Slice() {
29+
tn.Add(name)
30+
}
31+
}
32+
2733
// Slice returns set elements in the order they were first added to the set.
2834
func (tn *TypeNames) Slice() []*types.TypeName {
2935
return tn.order
3036
}
37+
38+
// Clear will remove the types without clearing if the types have been seen
39+
// before so that types seem before will not be added but new types will be.
40+
func (tn *TypeNames) Clear() {
41+
tn.order = nil
42+
}

0 commit comments

Comments
 (0)