Skip to content

Commit

Permalink
Trying to figure out how to encapsulate instance checking
Browse files Browse the repository at this point in the history
  • Loading branch information
grantnelson-wf committed Sep 6, 2024
1 parent 82e8d95 commit e6a483d
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 22 deletions.
4 changes: 3 additions & 1 deletion compiler/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,9 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
if typesutil.IsJsPackage(obj.Pkg()) && obj.Name() == "InternalObject" {
return fc.translateExpr(e.Args[0])
}
fc.pkgCtx.DeclareDCEDep(obj)
if inst, has := fc.pkgCtx.Instances[f]; has {
fc.pkgCtx.DeclareDCEDepWithInstance(obj, inst)
}
return fc.translateCall(e, sig, fc.translateExpr(f))

case *ast.SelectorExpr:
Expand Down
17 changes: 7 additions & 10 deletions compiler/internal/dce/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,24 @@ type Decl interface {
// Collector is a tool to collect dependencies for a declaration
// that'll be used in dead-code elimination (DCE).
type Collector struct {
TypeInfo *types.Info
dependencies map[string]struct{}
TypeInfo *types.Info
decl *Info
}

// CollectDCEDeps captures a list of Go objects (types, functions, etc.)
// the code translated inside f() depends on. Then sets those objects
// as dependencies of the given dead-code elimination info.
//
// Only one CollectDCEDeps call can be active at a time.
// This will overwrite any previous dependencies collected for the given DCE.
func (c *Collector) CollectDCEDeps(decl Decl, f func()) {
if c.dependencies != nil {
if c.decl != nil {
panic(errors.New(`called CollectDCEDeps inside another CollectDCEDeps call`))
}

c.dependencies = make(map[string]struct{})
defer func() { c.dependencies = nil }()
c.decl = decl.Dce()
defer func() { c.decl = nil }()

f()

decl.Dce().setDeps(c.dependencies)
}

// DeclareDCEDep records that the code that is currently being transpiled
Expand All @@ -47,7 +44,7 @@ func (c *Collector) DeclareDCEDep(o types.Object) {
}

func (c *Collector) DeclareDCEDepWithInstance(o types.Object, inst types.Instance) {
if c.dependencies == nil {
if c.decl == nil {
return // Dependencies are not being collected.
}

Expand All @@ -62,5 +59,5 @@ func (c *Collector) DeclareDCEDepWithInstance(o types.Object, inst types.Instanc
if typesutil.IsMethod(o) {
qualifiedName += "~"
}
c.dependencies[qualifiedName] = struct{}{}
c.decl.addDep(qualifiedName)
}
3 changes: 2 additions & 1 deletion compiler/internal/dce/dce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
c.DeclareDCEDep(obj)
})
equal(t, len(d.Dce().deps), 1)
equal(t, d.Dce().deps[0], tt.wantDep)
equal(t, d.Dce().getDeps()[0], tt.wantDep)
})
}
})
Expand Down Expand Up @@ -508,6 +508,7 @@ func Test_Selector_SpecificMethods(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
vetinari.Dce().deps = nil // reset deps
c.CollectDCEDeps(vetinari, func() {
for _, decl := range tt.deps {
c.DeclareDCEDep(decl.obj)
Expand Down
26 changes: 17 additions & 9 deletions compiler/internal/dce/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Info struct {

// List of fully qualified (including package path) DCE symbol identifiers the
// symbol depends on for dead code elimination purposes.
deps []string
deps map[string]struct{}
}

// String gets a human-readable representation of the DCE info.
Expand All @@ -47,7 +47,7 @@ func (d *Info) String() string {
if len(d.methodFilter) > 0 {
fullName += `.` + d.methodFilter
}
return tags + fullName + ` -> [` + strings.Join(d.deps, `, `) + `]`
return tags + fullName + ` -> [` + strings.Join(d.getDeps(), `, `) + `]`
}

// unnamed returns true if SetName has not been called for this declaration.
Expand Down Expand Up @@ -91,14 +91,22 @@ func (d *Info) SetName(o types.Object) {
}
}

// setDeps sets the declaration dependencies used by DCE
// addDep adds a declaration dependency used by DCE
// for the declaration this DCE info is attached to.
// This overwrites any prior set dependencies.
func (d *Info) setDeps(depSet map[string]struct{}) {
deps := make([]string, 0, len(depSet))
for dep := range depSet {
deps = append(deps, dep)
func (d *Info) addDep(dep string) {
if d.deps == nil {
d.deps = make(map[string]struct{})
}
d.deps[dep] = struct{}{}
}

func (id *Info) getDeps() []string {
deps := make([]string, len(id.deps))
i := 0
for dep := range id.deps {
deps[i] = dep
i++
}
sort.Strings(deps)
d.deps = deps
return deps
}
2 changes: 1 addition & 1 deletion compiler/internal/dce/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (s *Selector[D]) AliveDecls() map[D]struct{} {

// Consider all decls the current one is known to depend on and possible add
// them to the live queue.
for _, dep := range dce.deps {
for _, dep := range dce.getDeps() {
if infos, ok := s.byFilter[dep]; ok {
delete(s.byFilter, dep)
for _, info := range infos {
Expand Down

0 comments on commit e6a483d

Please sign in to comment.