Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gopherjs/gopherjs into dceIntegra…
Browse files Browse the repository at this point in the history
…tionTests
  • Loading branch information
grantnelson-wf committed Oct 2, 2024
2 parents f565ca5 + 56cec36 commit df51690
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 85 deletions.
22 changes: 11 additions & 11 deletions compiler/internal/dce/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,33 @@ 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 {
dependencies map[types.Object]struct{}
dce *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.dce != nil {
panic(errors.New(`called CollectDCEDeps inside another CollectDCEDeps call`))
}

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

f()

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

// DeclareDCEDep records that the code that is currently being transpiled
// depends on a given Go object.
// depends on a given Go object with optional type arguments.
//
// The given optional type arguments are used to when the object is a
// function with type parameters or anytime the object doesn't carry them.
// If not given, this attempts to get the type arguments from the object.
func (c *Collector) DeclareDCEDep(o types.Object) {
if c.dependencies == nil {
return // Dependencies are not being collected.
if c.dce != nil {
c.dce.addDep(o)
}
c.dependencies[o] = struct{}{}
}
77 changes: 42 additions & 35 deletions compiler/internal/dce/dce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@ func Test_Collector_Collecting(t *testing.T) {
depCount(t, decl1, 2)
depCount(t, decl2, 3)

// The second collection overwrites the first collection.
// The second collection adds to existing dependencies.
c.CollectDCEDeps(decl2, func() {
c.DeclareDCEDep(obj4)
c.DeclareDCEDep(obj5)
})
depCount(t, decl1, 2)
depCount(t, decl2, 1)
depCount(t, decl2, 4)
}

func Test_Info_SetNameAndDep(t *testing.T) {
Expand All @@ -86,8 +87,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
import Sarah "fmt"`),
want: Info{
importPath: `jim`,
objectFilter: `Sarah`,
objectFilter: `jim.Sarah`,
},
wantDep: `jim.Sarah`,
},
Expand All @@ -97,8 +97,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
var Toby float64`),
want: Info{
importPath: `jim`,
objectFilter: `Toby`,
objectFilter: `jim.Toby`,
},
wantDep: `jim.Toby`,
},
Expand All @@ -108,8 +107,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
const Ludo int = 42`),
want: Info{
importPath: `jim`,
objectFilter: `Ludo`,
objectFilter: `jim.Ludo`,
},
wantDep: `jim.Ludo`,
},
Expand All @@ -126,8 +124,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
}
}`),
want: Info{
importPath: `jim`,
objectFilter: `Gobo`,
objectFilter: `jim.Gobo`,
},
wantDep: `jim.Gobo`,
},
Expand All @@ -137,8 +134,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
type Jen struct{}`),
want: Info{
importPath: `jim`,
objectFilter: `Jen`,
objectFilter: `jim.Jen`,
},
wantDep: `jim.Jen`,
},
Expand All @@ -148,8 +144,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
type Henson[T comparable] struct{}`),
want: Info{
importPath: `jim`,
objectFilter: `Henson`,
objectFilter: `jim.Henson`,
},
wantDep: `jim.Henson`,
},
Expand All @@ -159,8 +154,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
func Jareth() {}`),
want: Info{
importPath: `jim`,
objectFilter: `Jareth`,
objectFilter: `jim.Jareth`,
},
wantDep: `jim.Jareth`,
},
Expand All @@ -170,8 +164,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
`package jim
func Didymus[T comparable]() {}`),
want: Info{
importPath: `jim`,
objectFilter: `Didymus`,
objectFilter: `jim.Didymus`,
},
wantDep: `jim.Didymus`,
},
Expand All @@ -182,8 +175,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
type Fizzgig string
func (f Fizzgig) Kira() {}`),
want: Info{
importPath: `jim`,
objectFilter: `Fizzgig`,
objectFilter: `jim.Fizzgig`,
},
wantDep: `jim.Kira~`,
},
Expand All @@ -194,9 +186,8 @@ func Test_Info_SetNameAndDep(t *testing.T) {
type Aughra int
func (a Aughra) frank() {}`),
want: Info{
importPath: `jim`,
objectFilter: `Aughra`,
methodFilter: `frank~`,
objectFilter: `jim.Aughra`,
methodFilter: `jim.frank~`,
},
wantDep: `jim.frank~`,
},
Expand All @@ -207,8 +198,7 @@ func Test_Info_SetNameAndDep(t *testing.T) {
type wembley struct{}
func (w wembley) Red() {}`),
want: Info{
importPath: `jim`,
objectFilter: `wembley`,
objectFilter: `jim.wembley`,
},
wantDep: `jim.Red~`,
},
Expand All @@ -219,12 +209,11 @@ func Test_Info_SetNameAndDep(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
d := &testDecl{}
equal(t, d.Dce().unnamed(), true)
equal(t, d.Dce().String(), `[unnamed] . -> []`)
equal(t, d.Dce().String(), `[unnamed] -> []`)
t.Log(`object:`, types.ObjectString(tt.obj, nil))

d.Dce().SetName(tt.obj)
equal(t, d.Dce().unnamed(), tt.want.unnamed())
equal(t, d.Dce().importPath, tt.want.importPath)
equal(t, d.Dce().objectFilter, tt.want.objectFilter)
equal(t, d.Dce().methodFilter, tt.want.methodFilter)
equal(t, d.Dce().String(), tt.want.String())
Expand All @@ -238,11 +227,17 @@ func Test_Info_SetNameAndDep(t *testing.T) {
d := &testDecl{}
t.Log(`object:`, types.ObjectString(tt.obj, nil))

d.Dce().setDeps(map[types.Object]struct{}{
tt.obj: {},
wantDeps := []string{}
if len(tt.wantDep) > 0 {
wantDeps = append(wantDeps, tt.wantDep)
}
sort.Strings(wantDeps)

c := Collector{}
c.CollectDCEDeps(d, func() {
c.DeclareDCEDep(tt.obj)
})
equal(t, len(d.Dce().deps), 1)
equal(t, d.Dce().deps[0], tt.wantDep)
equalSlices(t, d.Dce().getDeps(), wantDeps)
})
}
})
Expand All @@ -269,11 +264,11 @@ func Test_Info_SetAsAlive(t *testing.T) {
obj := quickVar(pkg, `Falkor`)
decl := &testDecl{}
equal(t, decl.Dce().isAlive(), true) // unnamed is automatically alive
equal(t, decl.Dce().String(), `[unnamed] . -> []`)
equal(t, decl.Dce().String(), `[unnamed] -> []`)

decl.Dce().SetAsAlive()
equal(t, decl.Dce().isAlive(), true) // still alive but now explicitly alive
equal(t, decl.Dce().String(), `[alive] [unnamed] . -> []`)
equal(t, decl.Dce().String(), `[alive] [unnamed] -> []`)

decl.Dce().SetName(obj)
equal(t, decl.Dce().isAlive(), true) // alive because SetAsAlive was called
Expand All @@ -284,7 +279,7 @@ func Test_Info_SetAsAlive(t *testing.T) {
obj := quickVar(pkg, `Artax`)
decl := &testDecl{}
equal(t, decl.Dce().isAlive(), true) // unnamed is automatically alive
equal(t, decl.Dce().String(), `[unnamed] . -> []`)
equal(t, decl.Dce().String(), `[unnamed] -> []`)

decl.Dce().SetName(obj)
equal(t, decl.Dce().isAlive(), false) // named so no longer automatically alive
Expand Down Expand Up @@ -493,6 +488,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 Expand Up @@ -626,6 +622,17 @@ func depCount(t *testing.T, decl *testDecl, want int) {
func equal[T comparable](t *testing.T, got, want T) {
t.Helper()
if got != want {
t.Errorf(`expected %#v but got %#v`, want, got)
t.Errorf("Unexpected value was gotten:\n\texp: %#v\n\tgot: %#v", want, got)
}
}

func equalSlices[T comparable](t *testing.T, got, want []T) {
t.Helper()
if len(got) != len(want) {
t.Errorf("expected %d but got %d\n\texp: %#v\n\tgot: %#v", len(want), len(got), want, got)
return
}
for i, wantElem := range want {
equal(t, got[i], wantElem)
}
}
32 changes: 32 additions & 0 deletions compiler/internal/dce/filters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dce

import (
"go/types"

"github.com/gopherjs/gopherjs/compiler/typesutil"
)

// getFilters determines the DCE filters for the given object.
// This will return an object filter and optionally return a method filter.
func getFilters(o types.Object) (objectFilter, methodFilter string) {
importPath := o.Pkg().Path()
if typesutil.IsMethod(o) {
recv := typesutil.RecvType(o.Type().(*types.Signature)).Obj()
objectFilter = importPath + `.` + recv.Name()
if !o.Exported() {
methodFilter = importPath + `.` + o.Name() + `~`
}
} else {
objectFilter = importPath + `.` + o.Name()
}
return
}

// getDepFilter returns the filter for the given object to be used as a dependency.
func getDepFilter(o types.Object) string {
qualifiedName := o.Pkg().Path() + "." + o.Name()
if typesutil.IsMethod(o) {
qualifiedName += "~"
}
return qualifiedName
}
Loading

0 comments on commit df51690

Please sign in to comment.