loadPackageEx: dedup
This commit is contained in:
@@ -19,7 +19,6 @@ package cl_test
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
@@ -71,13 +70,11 @@ func TestPython(t *testing.T) {
|
|||||||
cltest.Pkg(t, ssa.PkgPython, "../py/llgo_autogen.ll")
|
cltest.Pkg(t, ssa.PkgPython, "../py/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoLibMath(t *testing.T) {
|
func TestGoPkgMath(t *testing.T) {
|
||||||
if runtime.GOOS == "darwin" { // TODO(xsw): support linux/windows
|
root, _ := filepath.Abs("..")
|
||||||
root, _ := filepath.Abs("..")
|
os.Setenv("LLGOROOT", root)
|
||||||
os.Setenv("LLGOROOT", root)
|
conf := build.NewDefaultConf(build.ModeInstall)
|
||||||
conf := build.NewDefaultConf(build.ModeInstall)
|
build.Do([]string{"math"}, conf)
|
||||||
build.Do([]string{"math"}, conf)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
|
|||||||
@@ -99,13 +99,33 @@ type loader struct {
|
|||||||
requestedMode LoadMode
|
requestedMode LoadMode
|
||||||
}
|
}
|
||||||
|
|
||||||
type Deduper struct {
|
type cachedPackage struct {
|
||||||
|
Types *types.Package
|
||||||
|
TypesInfo *types.Info
|
||||||
|
Syntax []*ast.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeduper() *Deduper {
|
type aDeduper struct {
|
||||||
|
cache sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
type Deduper = *aDeduper
|
||||||
|
|
||||||
|
func NewDeduper() Deduper {
|
||||||
|
return &aDeduper{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Deduper) check(pkgPath string) *cachedPackage {
|
||||||
|
if v, ok := p.cache.Load(pkgPath); ok {
|
||||||
|
return v.(*cachedPackage)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Deduper) set(pkgPath string, cp *cachedPackage) {
|
||||||
|
p.cache.Store(pkgPath, cp)
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname defaultDriver golang.org/x/tools/go/packages.defaultDriver
|
//go:linkname defaultDriver golang.org/x/tools/go/packages.defaultDriver
|
||||||
func defaultDriver(cfg *Config, patterns ...string) (*packages.DriverResponse, bool, error)
|
func defaultDriver(cfg *Config, patterns ...string) (*packages.DriverResponse, bool, error)
|
||||||
|
|
||||||
@@ -130,7 +150,7 @@ type importerFunc func(path string) (*types.Package, error)
|
|||||||
|
|
||||||
func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
|
func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
|
||||||
|
|
||||||
func loadPackageEx(dedup *Deduper, ld *loader, lpkg *loaderPackage) {
|
func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) {
|
||||||
if lpkg.PkgPath == "unsafe" {
|
if lpkg.PkgPath == "unsafe" {
|
||||||
// Fill in the blanks to avoid surprises.
|
// Fill in the blanks to avoid surprises.
|
||||||
lpkg.Types = types.Unsafe
|
lpkg.Types = types.Unsafe
|
||||||
@@ -141,6 +161,26 @@ func loadPackageEx(dedup *Deduper, ld *loader, lpkg *loaderPackage) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dedup != nil {
|
||||||
|
if cp := dedup.check(lpkg.PkgPath); cp != nil {
|
||||||
|
lpkg.Types = cp.Types
|
||||||
|
lpkg.Fset = ld.Fset
|
||||||
|
lpkg.TypesInfo = cp.TypesInfo
|
||||||
|
lpkg.Syntax = cp.Syntax
|
||||||
|
lpkg.TypesSizes = ld.sizes
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if !lpkg.IllTyped && lpkg.needtypes && lpkg.needsrc {
|
||||||
|
dedup.set(lpkg.PkgPath, &cachedPackage{
|
||||||
|
Types: lpkg.Types,
|
||||||
|
TypesInfo: lpkg.TypesInfo,
|
||||||
|
Syntax: lpkg.Syntax,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Call NewPackage directly with explicit name.
|
// Call NewPackage directly with explicit name.
|
||||||
// This avoids skew between golist and go/types when the files'
|
// This avoids skew between golist and go/types when the files'
|
||||||
// package declarations are inconsistent.
|
// package declarations are inconsistent.
|
||||||
@@ -404,7 +444,7 @@ func loadPackageEx(dedup *Deduper, ld *loader, lpkg *loaderPackage) {
|
|||||||
lpkg.IllTyped = illTyped
|
lpkg.IllTyped = illTyped
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadRecursiveEx(dedup *Deduper, ld *loader, lpkg *loaderPackage) {
|
func loadRecursiveEx(dedup Deduper, ld *loader, lpkg *loaderPackage) {
|
||||||
lpkg.loadOnce.Do(func() {
|
lpkg.loadOnce.Do(func() {
|
||||||
// Load the direct dependencies, in parallel.
|
// Load the direct dependencies, in parallel.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -421,7 +461,7 @@ func loadRecursiveEx(dedup *Deduper, ld *loader, lpkg *loaderPackage) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func refineEx(dedup *Deduper, ld *loader, response *packages.DriverResponse) ([]*Package, error) {
|
func refineEx(dedup Deduper, ld *loader, response *packages.DriverResponse) ([]*Package, error) {
|
||||||
roots := response.Roots
|
roots := response.Roots
|
||||||
rootMap := make(map[string]int, len(roots))
|
rootMap := make(map[string]int, len(roots))
|
||||||
for i, root := range roots {
|
for i, root := range roots {
|
||||||
@@ -641,7 +681,7 @@ func refineEx(dedup *Deduper, ld *loader, response *packages.DriverResponse) ([]
|
|||||||
// return an error. Clients may need to handle such errors before
|
// return an error. Clients may need to handle such errors before
|
||||||
// proceeding with further analysis. The PrintErrors function is
|
// proceeding with further analysis. The PrintErrors function is
|
||||||
// provided for convenient display of all errors.
|
// provided for convenient display of all errors.
|
||||||
func LoadEx(dedup *Deduper, sizes func(types.Sizes) types.Sizes, cfg *Config, patterns ...string) ([]*Package, error) {
|
func LoadEx(dedup Deduper, sizes func(types.Sizes) types.Sizes, cfg *Config, patterns ...string) ([]*Package, error) {
|
||||||
ld := newLoader(cfg)
|
ld := newLoader(cfg)
|
||||||
response, external, err := defaultDriver(&ld.Config, patterns...)
|
response, external, err := defaultDriver(&ld.Config, patterns...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user