aboutsummaryrefslogtreecommitdiffstats
path: root/sysgen
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 /sysgen
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 'sysgen')
-rw-r--r--sysgen/sysgen.go51
1 files changed, 22 insertions, 29 deletions
diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go
index 12bcf26f7..b9212cbba 100644
--- a/sysgen/sysgen.go
+++ b/sysgen/sysgen.go
@@ -147,7 +147,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
generateResources(desc, consts, out)
generateStructs(desc, consts, out)
- fmt.Fprintf(out, "func initCalls() {\n")
+ fmt.Fprintf(out, "var Calls = []*Call{\n")
for _, s := range desc.Syscalls {
logf(4, " generate population code for %v", s.Name)
skipCurrentSyscall = ""
@@ -160,7 +160,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
logf(0, "unsupported syscall: %v", s.CallName)
}
}
- fmt.Fprintf(out, "func() { Calls = append(Calls, &Call{Name: \"%v\", CallName: \"%v\"", s.Name, s.CallName)
+ fmt.Fprintf(out, "&Call{Name: \"%v\", CallName: \"%v\"", s.Name, s.CallName)
if len(s.Ret) != 0 {
fmt.Fprintf(out, ", Ret: ")
generateArg("", "ret", s.Ret[0], "out", s.Ret[1:], desc, consts, true, false, out)
@@ -177,7 +177,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
logf(0, "unsupported syscall: %v due to %v", s.Name, skipCurrentSyscall)
syscallNR = -1
}
- fmt.Fprintf(out, "}, NR: %v})}()\n", syscallNR)
+ fmt.Fprintf(out, "}, NR: %v},\n", syscallNR)
}
fmt.Fprintf(out, "}\n\n")
@@ -201,7 +201,7 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write
}
sort.Sort(resArray)
- fmt.Fprintf(out, "var Resources = map[string]*ResourceDesc{\n")
+ fmt.Fprintf(out, "var resourceArray = []*ResourceDesc{\n")
for _, res := range resArray {
underlying := ""
name := res.Name
@@ -230,7 +230,7 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write
res = desc.Resources[res.Base]
}
}
- fmt.Fprintf(out, "\"%v\": &ResourceDesc{Name: \"%v\", Type: ", name, name)
+ fmt.Fprintf(out, "&ResourceDesc{Name: \"%v\", Type: ", name)
generateArg("", "resource-type", underlying, "inout", nil, desc, consts, true, true, out)
fmt.Fprintf(out, ", Kind: []string{")
for i, k := range kind {
@@ -260,7 +260,7 @@ type structKey struct {
dir string
}
-func generateStructEntry(str Struct, key structKey, out io.Writer) {
+func generateStructEntry(str Struct, out io.Writer) {
typ := "StructType"
if str.IsUnion {
typ = "UnionType"
@@ -277,36 +277,29 @@ func generateStructEntry(str Struct, key structKey, out io.Writer) {
if str.Align != 0 {
align = fmt.Sprintf(", align: %v", str.Align)
}
- fmt.Fprintf(out, "\"%v\": &%v{TypeCommon: TypeCommon{TypeName: \"%v\", FldName: \"%v\", ArgDir: %v, IsOptional: %v} %v %v %v},\n",
- key, typ, key.name, key.field, fmtDir(key.dir), false, packed, align, varlen)
+ fmt.Fprintf(out, "&%v{TypeCommon: TypeCommon{TypeName: \"%v\", IsOptional: %v} %v %v %v},\n",
+ typ, str.Name, false, packed, align, varlen)
}
func generateStructFields(str Struct, key structKey, desc *Description, consts map[string]uint64, out io.Writer) {
- typ := "StructType"
- fields := "Fields"
- if str.IsUnion {
- typ = "UnionType"
- fields = "Options"
- }
- fmt.Fprintf(out, "func() { s := Structs[\"%v\"].(*%v)\n", key, typ)
+ fmt.Fprintf(out, "{structKey{\"%v\", \"%v\", %v}, []Type{\n", key.name, key.field, fmtDir(key.dir))
for _, a := range str.Flds {
- fmt.Fprintf(out, "s.%v = append(s.%v, ", fields, fields)
generateArg(str.Name, a[0], a[1], key.dir, a[2:], desc, consts, false, true, out)
- fmt.Fprintf(out, ")\n")
+ fmt.Fprintf(out, ",\n")
}
- fmt.Fprintf(out, "}()\n")
+ fmt.Fprintf(out, "}},\n")
+
}
func generateStructs(desc *Description, consts map[string]uint64, out io.Writer) {
// Struct fields can refer to other structs. Go compiler won't like if
- // we refer to Structs map during Structs map initialization. So we do
- // it in 2 passes: on the first pass create types and assign them to
- // the map, on the second pass fill in fields.
+ // we refer to Structs during Structs initialization. So we do
+ // it in 2 passes: on the first pass create struct types without fields,
+ // on the second pass we fill in fields.
// Since structs of the same type can be fields with different names
// of multiple other structs, we have an instance of those structs
- // for each field indexed by the name of the parent struct and the
- // field name.
+ // for each field indexed by the name of the parent struct, field name and dir.
structMap := make(map[structKey]Struct)
for _, str := range desc.Structs {
@@ -322,13 +315,13 @@ func generateStructs(desc *Description, consts map[string]uint64, out io.Writer)
}
}
- fmt.Fprintf(out, "var Structs = map[string]Type{\n")
- for key, str := range structMap {
- generateStructEntry(str, key, out)
+ fmt.Fprintf(out, "var structArray = []Type{\n")
+ for _, str := range desc.Structs {
+ generateStructEntry(str, out)
}
fmt.Fprintf(out, "}\n")
- fmt.Fprintf(out, "func initStructFields() {\n")
+ fmt.Fprintf(out, "var structFields = []struct{key structKey; fields []Type}{")
for key, str := range structMap {
generateStructFields(str, key, desc, consts, out)
}
@@ -692,12 +685,12 @@ func generateArg(
if len(a) != 0 {
failf("struct '%v' has args", typ)
}
- fmt.Fprintf(out, "Structs[\"%v\"]", structKey{typ, origName, dir})
+ fmt.Fprintf(out, "getStruct(structKey{\"%v\", \"%v\", %v})", typ, origName, fmtDir(dir))
} else if _, ok := desc.Resources[typ]; ok {
if len(a) != 0 {
failf("resource '%v' has args", typ)
}
- fmt.Fprintf(out, "&ResourceType{%v, Desc: Resources[\"%v\"]}", common(), typ)
+ fmt.Fprintf(out, "&ResourceType{%v, Desc: resource(\"%v\")}", common(), typ)
return
} else {
failf("unknown arg type \"%v\" for %v", typ, name)