aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-05-26 15:32:51 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-05-29 13:15:17 +0200
commit1f710b08fc40d6077b0065a25c5d7ab5d0750e7a (patch)
treecf6b26abe4d4724a5e07902c2ada4b846f5d2708 /sys
parent108115666bf24c0ed2844f7af9be9a672849bb9c (diff)
sys: generate arrays instead of maps
Compilation of large maps is super slow. Generate arrays instead and converet to maps at runtime. Reduces build time from ~40s to ~2s. Update #182
Diffstat (limited to 'sys')
-rw-r--r--sys/align.go2
-rw-r--r--sys/decl.go94
2 files changed, 86 insertions, 10 deletions
diff --git a/sys/align.go b/sys/align.go
index e1ce27d56..00d464bcb 100644
--- a/sys/align.go
+++ b/sys/align.go
@@ -32,7 +32,7 @@ func initAlign() {
}
}
- for _, s := range Structs {
+ for _, s := range keyedStructs {
rec(s)
}
}
diff --git a/sys/decl.go b/sys/decl.go
index 0956a94ee..28c18d488 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -430,7 +430,86 @@ func (t *UnionType) Align() uintptr {
return align
}
-var ctors = make(map[string][]*Call)
+var (
+ CallMap = make(map[string]*Call)
+ structs map[string]Type
+ keyedStructs map[structKey]Type
+ Resources map[string]*ResourceDesc
+ ctors = make(map[string][]*Call)
+)
+
+type structKey struct {
+ name string
+ field string
+ dir Dir
+}
+
+func getStruct(key structKey) Type {
+ if structs == nil {
+ structs = make(map[string]Type)
+ keyedStructs = make(map[structKey]Type)
+ for _, str := range structArray {
+ structs[str.Name()] = str
+ }
+ }
+ str := keyedStructs[key]
+ if str == nil {
+ proto := structs[key.name]
+ if proto == nil {
+ panic(fmt.Sprintf("missing struct prototype for %v", key.name))
+ }
+ switch typed := proto.(type) {
+ case *StructType:
+ newStr := new(StructType)
+ *newStr = *typed
+ newStr.FldName = key.field
+ newStr.ArgDir = key.dir
+ str = newStr
+ case *UnionType:
+ newStr := new(UnionType)
+ *newStr = *typed
+ newStr.FldName = key.field
+ newStr.ArgDir = key.dir
+ str = newStr
+ default:
+ panic(fmt.Sprintf("unexpected type of struct prototype for %v: %+v", key.name, proto))
+ }
+ keyedStructs[key] = str
+ }
+ return str
+}
+
+func initStructFields() {
+ missed := 0
+ for _, f := range structFields {
+ untyped := keyedStructs[f.key]
+ if untyped == nil {
+ missed++
+ continue
+ }
+ switch str := untyped.(type) {
+ case *StructType:
+ str.Fields = f.fields
+ case *UnionType:
+ str.Options = f.fields
+ default:
+ panic(fmt.Sprintf("unexpected type of struct prototype for %v: %+v", f.key.name, untyped))
+ }
+ }
+ fmt.Printf("missed %v/%v\n", missed, len(structFields))
+}
+
+func resource(name string) *ResourceDesc {
+ if Resources == nil {
+ // This is first called during init of sys package, so does not need to be thread-safe.
+ // resourceArray is in sys_GOARCH.go (generated by sysgen).
+ Resources = make(map[string]*ResourceDesc)
+ for _, res := range resourceArray {
+ Resources[res.Name] = res
+ }
+ }
+ return Resources[name]
+}
// ResourceConstructors returns a list of calls that can create a resource of the given kind.
func ResourceConstructors(name string) []*Call {
@@ -438,8 +517,9 @@ func ResourceConstructors(name string) []*Call {
}
func initResources() {
- for name, res := range Resources {
- ctors[name] = resourceCtors(res.Kind, false)
+ resource("") // init resources, if it's not done yet
+ for _, res := range resourceArray {
+ ctors[res.Name] = resourceCtors(res.Kind, false)
}
}
@@ -611,16 +691,12 @@ func ForeachType(meta *Call, f func(Type)) {
}
}
-var (
- Calls []*Call
- CallMap = make(map[string]*Call)
-)
-
func init() {
- initCalls()
initStructFields()
initResources()
initAlign()
+ keyedStructs = nil
+ structs = nil
for i, c := range Calls {
c.ID = i