aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/_mkmalloc
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/_mkmalloc')
-rw-r--r--src/runtime/_mkmalloc/mkmalloc.go57
1 files changed, 51 insertions, 6 deletions
diff --git a/src/runtime/_mkmalloc/mkmalloc.go b/src/runtime/_mkmalloc/mkmalloc.go
index 46c50d6661..8032983da8 100644
--- a/src/runtime/_mkmalloc/mkmalloc.go
+++ b/src/runtime/_mkmalloc/mkmalloc.go
@@ -107,6 +107,7 @@ type replacementKind int
const (
inlineFunc = replacementKind(iota)
subBasicLit
+ foldCondition
)
// op is a single inlining operation for the inliner. Any calls to the function
@@ -171,7 +172,7 @@ func specializedMallocConfig(classes []class, sizeToSizeClass []uint8) generator
{subBasicLit, "elemsize_", str(elemsize)},
{subBasicLit, "sizeclass_", str(sc)},
{subBasicLit, "noscanint_", str(noscan)},
- {subBasicLit, "isTiny_", str(0)},
+ {foldCondition, "isTiny_", str(false)},
},
})
}
@@ -199,7 +200,7 @@ func specializedMallocConfig(classes []class, sizeToSizeClass []uint8) generator
{subBasicLit, "sizeclass_", str(tinySizeClass)},
{subBasicLit, "size_", str(s)},
{subBasicLit, "noscanint_", str(noscan)},
- {subBasicLit, "isTiny_", str(1)},
+ {foldCondition, "isTiny_", str(true)},
},
})
}
@@ -217,7 +218,7 @@ func specializedMallocConfig(classes []class, sizeToSizeClass []uint8) generator
{subBasicLit, "elemsize_", str(elemsize)},
{subBasicLit, "sizeclass_", str(sc)},
{subBasicLit, "noscanint_", str(noscan)},
- {subBasicLit, "isTiny_", str(0)},
+ {foldCondition, "isTiny_", str(false)},
},
})
}
@@ -277,10 +278,17 @@ func inline(config generatorConfig) []byte {
// Apply each of the ops given by the specs
stamped := ast.Node(containingFuncCopy)
for _, repl := range spec.ops {
- if toDecl, ok := funcDecls[repl.to]; ok {
- stamped = inlineFunction(stamped, repl.from, toDecl)
- } else {
+ switch repl.kind {
+ case inlineFunc:
+ if toDecl, ok := funcDecls[repl.to]; ok {
+ stamped = inlineFunction(stamped, repl.from, toDecl)
+ }
+ case subBasicLit:
stamped = substituteWithBasicLit(stamped, repl.from, repl.to)
+ case foldCondition:
+ stamped = foldIfCondition(stamped, repl.from, repl.to)
+ default:
+ log.Fatal("unknown op kind %v", repl.kind)
}
}
@@ -310,6 +318,43 @@ func substituteWithBasicLit(node ast.Node, from, to string) ast.Node {
}, nil)
}
+// foldIfCondition looks for if statements with a single boolean variable from, or
+// the negation of from and either replaces it with its body or nothing,
+// depending on whether the to value is true or false.
+func foldIfCondition(node ast.Node, from, to string) ast.Node {
+ var isTrue bool
+ switch to {
+ case "true":
+ isTrue = true
+ case "false":
+ isTrue = false
+ default:
+ log.Fatalf("op 'to' expr %q is not true or false", to)
+ }
+ return astutil.Apply(node, func(cursor *astutil.Cursor) bool {
+ var foldIfTrue bool
+ ifexpr, ok := cursor.Node().(*ast.IfStmt)
+ if !ok {
+ return true
+ }
+ if isIdentWithName(ifexpr.Cond, from) {
+ foldIfTrue = true
+ } else if unaryexpr, ok := ifexpr.Cond.(*ast.UnaryExpr); ok && unaryexpr.Op == token.NOT && isIdentWithName(unaryexpr.X, from) {
+ foldIfTrue = false
+ } else {
+ // not an if with from or !from.
+ return true
+ }
+ if foldIfTrue == isTrue {
+ for _, stmt := range ifexpr.Body.List {
+ cursor.InsertBefore(stmt)
+ }
+ }
+ cursor.Delete()
+ return true
+ }, nil)
+}
+
// inlineFunction recursively replaces calls to the function 'from' with the body of the function
// 'toDecl'. All calls to 'from' must appear in assignment statements.
// The replacement is very simple: it doesn't substitute the arguments for the parameters, so the