Skip to content

Commit

Permalink
Merge branch 'encapDCE' of github.com:Workiva/gopherjs into workingOn…
Browse files Browse the repository at this point in the history
…Go20
  • Loading branch information
grantnelson-wf committed Aug 9, 2024
2 parents 790baaa + cacbfcf commit 75705a6
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 42 deletions.
14 changes: 7 additions & 7 deletions compiler/decls.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (fc *funcContext) newVarDecl(init *types.Initializer) *Decl {
}
}

fc.pkgCtx.CollectDCEDeps(d.Dce(), func() {
fc.pkgCtx.CollectDCEDeps(&d, func() {
fc.localVars = nil
d.InitCode = fc.CatchOutput(1, func() {
fc.translateStmt(&ast.AssignStmt{
Expand Down Expand Up @@ -338,8 +338,8 @@ func (fc *funcContext) newFuncDecl(fun *ast.FuncDecl, inst typeparams.Instance)
}
}

fc.pkgCtx.CollectDCEDeps(d.Dce(), func() {
d.DeclCode = fc.namedFuncContext(inst).translateTopLevelFunction(fun)
fc.pkgCtx.CollectDCEDeps(d, func() {
d.DeclCode = fc.translateTopLevelFunction(fun, inst)
})
return d
}
Expand Down Expand Up @@ -451,7 +451,7 @@ func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, er
underlying := instanceType.Underlying()
d := &Decl{}
d.Dce().SetName(inst.Object)
fc.pkgCtx.CollectDCEDeps(d.Dce(), func() {
fc.pkgCtx.CollectDCEDeps(d, func() {
// Code that declares a JS type (i.e. prototype) for each Go type.
d.DeclCode = fc.CatchOutput(0, func() {
size := int64(0)
Expand Down Expand Up @@ -570,14 +570,14 @@ func (fc *funcContext) anonTypeDecls(anonTypes []*types.TypeName) []*Decl {
}
decls := []*Decl{}
for _, t := range anonTypes {
d := Decl{
d := &Decl{
Vars: []string{t.Name()},
}
d.Dce().SetName(t)
fc.pkgCtx.CollectDCEDeps(d.Dce(), func() {
fc.pkgCtx.CollectDCEDeps(d, func() {
d.DeclCode = []byte(fmt.Sprintf("\t%s = $%sType(%s);\n", t.Name(), strings.ToLower(typeKind(t.Type())[5:]), fc.initArgs(t.Type())))
})
decls = append(decls, &d)
decls = append(decls, d)
}
return decls
}
28 changes: 18 additions & 10 deletions compiler/internal/dce/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ package dce

import (
"errors"
"go/types"
)

// Decl is any code declaration that has dead-code elimination (DCE)
// information attached to it.
type Decl interface {
Dce() *Info
}

// Collector is a tool to collect dependencies for a declaration
// that'll be used in dead-code elimination (DCE).
type Collector struct {
dce *Info
dependencies map[types.Object]struct{}
}

// CollectDCEDeps captures a list of Go objects (types, functions, etc.)
Expand All @@ -17,22 +24,23 @@ type Collector struct {
// 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.dce != nil {
if c.dependencies != nil {
panic(errors.New(`called CollectDCEDeps inside another CollectDCEDeps call`))
}

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

f()

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

// DeclareDCEDep records a declaration that is currently being transpiled.
// If a collection in in progress, this will add the dependency of the
// declaration doing the collection.
func (c *Collector) DeclareDCEDep(decl Decl) {
if c.dce == nil {
// DeclareDCEDep records that the code that is currently being transpiled
// depends on a given Go object.
func (c *Collector) DeclareDCEDep(o types.Object) {
if c.dependencies == nil {
return // Dependencies are not being collected.
}
c.dce.addDep(decl.Dce())
c.dependencies[o] = struct{}{}
}
32 changes: 16 additions & 16 deletions compiler/internal/dce/dce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func Test_Collector_CalledOnce(t *testing.T) {
decl2 := &testDecl{}

err := capturePanic(t, func() {
c.CollectDCEDeps(decl1.Dce(), func() {
c.CollectDCEDeps(decl2.Dce(), func() {
c.CollectDCEDeps(decl1, func() {
c.CollectDCEDeps(decl2, func() {
t.Fatal(`the nested collect function was called`)
})
})
Expand All @@ -45,7 +45,7 @@ func Test_Collector_Collecting(t *testing.T) {
depCount(t, decl1, 0)
depCount(t, decl2, 0)

c.CollectDCEDeps(decl1.Dce(), func() {
c.CollectDCEDeps(decl1, func() {
c.DeclareDCEDep(obj2)
c.DeclareDCEDep(obj3)
c.DeclareDCEDep(obj3) // already added so has no effect.
Expand All @@ -57,7 +57,7 @@ func Test_Collector_Collecting(t *testing.T) {
depCount(t, decl1, 2)
depCount(t, decl2, 0)

c.CollectDCEDeps(decl2.Dce(), func() {
c.CollectDCEDeps(decl2, func() {
c.DeclareDCEDep(obj5)
c.DeclareDCEDep(obj6)
c.DeclareDCEDep(obj7)
Expand All @@ -66,7 +66,7 @@ func Test_Collector_Collecting(t *testing.T) {
depCount(t, decl2, 3)

// The second collection overwrites the first collection.
c.CollectDCEDeps(decl2.Dce(), func() {
c.CollectDCEDeps(decl2, func() {
c.DeclareDCEDep(obj5)
})
depCount(t, decl1, 2)
Expand Down Expand Up @@ -313,24 +313,24 @@ func Test_Selector_JustVars(t *testing.T) {
}

c := Collector{}
c.CollectDCEDeps(frodo.Dce(), func() {
c.CollectDCEDeps(frodo, func() {
c.DeclareDCEDep(samwise.obj)
c.DeclareDCEDep(meri.obj)
c.DeclareDCEDep(pippin.obj)
})
c.CollectDCEDeps(pippin.Dce(), func() {
c.CollectDCEDeps(pippin, func() {
c.DeclareDCEDep(meri.obj)
})
c.CollectDCEDeps(aragorn.Dce(), func() {
c.CollectDCEDeps(aragorn, func() {
c.DeclareDCEDep(boromir.obj)
})
c.CollectDCEDeps(gimli.Dce(), func() {
c.CollectDCEDeps(gimli, func() {
c.DeclareDCEDep(legolas.obj)
})
c.CollectDCEDeps(legolas.Dce(), func() {
c.CollectDCEDeps(legolas, func() {
c.DeclareDCEDep(gimli.obj)
})
c.CollectDCEDeps(gandalf.Dce(), func() {
c.CollectDCEDeps(gandalf, func() {
c.DeclareDCEDep(frodo.obj)
c.DeclareDCEDep(aragorn.obj)
c.DeclareDCEDep(gimli.obj)
Expand Down Expand Up @@ -449,16 +449,16 @@ func Test_Selector_SpecificMethods(t *testing.T) {
allDecls := []*testDecl{rincewind, rincewindRun, rincewindHide, vimes, vimesRun, vimesRead, vetinari}

c := Collector{}
c.CollectDCEDeps(rincewindRun.Dce(), func() {
c.CollectDCEDeps(rincewindRun, func() {
c.DeclareDCEDep(rincewind.obj)
})
c.CollectDCEDeps(rincewindHide.Dce(), func() {
c.CollectDCEDeps(rincewindHide, func() {
c.DeclareDCEDep(rincewind.obj)
})
c.CollectDCEDeps(vimesRun.Dce(), func() {
c.CollectDCEDeps(vimesRun, func() {
c.DeclareDCEDep(vimes.obj)
})
c.CollectDCEDeps(vimesRead.Dce(), func() {
c.CollectDCEDeps(vimesRead, func() {
c.DeclareDCEDep(vimes.obj)
})
vetinari.Dce().SetAsAlive()
Expand Down Expand Up @@ -493,7 +493,7 @@ func Test_Selector_SpecificMethods(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c.CollectDCEDeps(vetinari.Dce(), func() {
c.CollectDCEDeps(vetinari, func() {
for _, decl := range tt.deps {
c.DeclareDCEDep(decl.obj)
}
Expand Down
12 changes: 3 additions & 9 deletions compiler/internal/dce/selector.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package dce

// Decl is type for any code declaration that has
// dead-code elimination (DCE) information attached to it.
type Decl interface {
Dce() *Info
}

// DeclConstraint is type constraint for any code declaration that has
// dead-code elimination (DCE) information attached to it.
// Since this will be used in a set, it must also be comparable.
// dead-code elimination (DCE) information attached to it and will be
// used in a set.
type DeclConstraint interface {
Dce() *Info
Decl
comparable
}

Expand Down

0 comments on commit 75705a6

Please sign in to comment.