2013-08-27 16:49:13 -06:00
|
|
|
// Copyright 2013 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2013-07-30 12:28:14 -06:00
|
|
|
package ssa_test
|
|
|
|
|
|
|
|
// This file runs the SSA builder in sanity-checking mode on all
|
|
|
|
// packages beneath $GOROOT and prints some summary information.
|
|
|
|
//
|
2013-09-04 13:20:38 -06:00
|
|
|
// Run test with GOMAXPROCS=8.
|
2013-07-30 12:28:14 -06:00
|
|
|
|
|
|
|
import (
|
|
|
|
"go/build"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"code.google.com/p/go.tools/importer"
|
|
|
|
"code.google.com/p/go.tools/ssa"
|
|
|
|
)
|
|
|
|
|
2013-07-31 11:13:05 -06:00
|
|
|
const debugMode = false
|
|
|
|
|
2013-07-30 12:28:14 -06:00
|
|
|
func allPackages() []string {
|
|
|
|
var pkgs []string
|
2013-08-02 00:25:49 -06:00
|
|
|
root := filepath.Join(runtime.GOROOT(), "src/pkg") + string(os.PathSeparator)
|
2013-07-30 12:28:14 -06:00
|
|
|
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
|
|
// Prune the search if we encounter any of these names:
|
|
|
|
switch filepath.Base(path) {
|
|
|
|
case "testdata", ".hg":
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
if info.IsDir() {
|
|
|
|
pkg := strings.TrimPrefix(path, root)
|
|
|
|
switch pkg {
|
|
|
|
case "builtin", "pkg", "code.google.com":
|
|
|
|
return filepath.SkipDir // skip these subtrees
|
|
|
|
case "":
|
|
|
|
return nil // ignore root of tree
|
|
|
|
}
|
|
|
|
pkgs = append(pkgs, pkg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return pkgs
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStdlib(t *testing.T) {
|
2013-09-04 13:20:38 -06:00
|
|
|
impctx := importer.Config{Build: &build.Default}
|
2013-07-30 12:28:14 -06:00
|
|
|
|
|
|
|
// Load, parse and type-check the program.
|
|
|
|
t0 := time.Now()
|
|
|
|
|
|
|
|
imp := importer.New(&impctx)
|
2013-09-06 16:13:57 -06:00
|
|
|
|
|
|
|
if _, _, err := imp.LoadInitialPackages(allPackages()); err != nil {
|
|
|
|
t.Errorf("LoadInitialPackages failed: %s", err)
|
|
|
|
return
|
2013-07-30 12:28:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
t1 := time.Now()
|
|
|
|
|
|
|
|
runtime.GC()
|
|
|
|
var memstats runtime.MemStats
|
|
|
|
runtime.ReadMemStats(&memstats)
|
|
|
|
alloc := memstats.Alloc
|
|
|
|
|
|
|
|
// Create SSA packages.
|
2013-07-31 11:13:05 -06:00
|
|
|
prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
|
2013-09-06 16:13:57 -06:00
|
|
|
if err := prog.CreatePackages(imp); err != nil {
|
|
|
|
t.Errorf("CreatePackages failed: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Enable debug mode globally.
|
|
|
|
for _, info := range imp.AllPackages() {
|
|
|
|
prog.Package(info.Pkg).SetDebugMode(debugMode)
|
2013-07-30 12:28:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
t2 := time.Now()
|
|
|
|
|
|
|
|
// Build SSA IR... if it's safe.
|
2013-09-06 16:13:57 -06:00
|
|
|
prog.BuildAll()
|
2013-07-30 12:28:14 -06:00
|
|
|
|
|
|
|
t3 := time.Now()
|
|
|
|
|
|
|
|
runtime.GC()
|
|
|
|
runtime.ReadMemStats(&memstats)
|
|
|
|
|
2013-09-06 16:13:57 -06:00
|
|
|
numPkgs := len(prog.AllPackages())
|
2013-07-30 12:28:14 -06:00
|
|
|
if want := 140; numPkgs < want {
|
|
|
|
t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dump some statistics.
|
|
|
|
allFuncs := ssa.AllFunctions(prog)
|
|
|
|
var numInstrs int
|
|
|
|
for fn := range allFuncs {
|
|
|
|
for _, b := range fn.Blocks {
|
|
|
|
numInstrs += len(b.Instrs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
|
|
|
|
t.Log("Load/parse/typecheck: ", t1.Sub(t0))
|
|
|
|
t.Log("SSA create: ", t2.Sub(t1))
|
2013-09-06 16:13:57 -06:00
|
|
|
t.Log("SSA build: ", t3.Sub(t2))
|
2013-07-30 12:28:14 -06:00
|
|
|
|
|
|
|
// SSA stats:
|
|
|
|
t.Log("#Packages: ", numPkgs)
|
|
|
|
t.Log("#Functions: ", len(allFuncs))
|
|
|
|
t.Log("#Instructions: ", numInstrs)
|
|
|
|
t.Log("#MB: ", (memstats.Alloc-alloc)/1000000)
|
|
|
|
}
|