diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-05-26 15:32:51 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-05-29 13:15:17 +0200 |
| commit | 1f710b08fc40d6077b0065a25c5d7ab5d0750e7a (patch) | |
| tree | cf6b26abe4d4724a5e07902c2ada4b846f5d2708 /sys | |
| parent | 108115666bf24c0ed2844f7af9be9a672849bb9c (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.go | 2 | ||||
| -rw-r--r-- | sys/decl.go | 94 |
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 |
