aboutsummaryrefslogtreecommitdiffhomepage
path: root/stacksize/stacksize.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2020-07-18 13:36:28 +0200
committerRon Evans <[email protected]>2020-08-27 19:23:22 +0200
commita21a039ac774e80d279cf946729ef409575150f8 (patch)
treed78b14739c1d557c782e25fb82266db419a6d8f5 /stacksize/stacksize.go
parenta761f556ff81b52a7693dd3c62ac4c1d6398a724 (diff)
downloadtinygo-a21a039ac774e80d279cf946729ef409575150f8.tar.gz
tinygo-a21a039ac774e80d279cf946729ef409575150f8.zip
arm: automatically determine stack sizes
This is a big change that will determine the stack size for many goroutines automatically. Functions that aren't recursive and don't call function pointers can in many cases have an automatically determined worst case stack size. This is useful, as the stack size is usually much lower than the previous hardcoded default of 1024 bytes: somewhere around 200-500 bytes is common. A side effect of this change is that the default stack sizes (including the stack size for other architectures such as AVR) can now be changed in the config JSON file, making it tunable per application.
Diffstat (limited to 'stacksize/stacksize.go')
-rw-r--r--stacksize/stacksize.go29
1 files changed, 24 insertions, 5 deletions
diff --git a/stacksize/stacksize.go b/stacksize/stacksize.go
index 4161dc2f2..2b111ddcf 100644
--- a/stacksize/stacksize.go
+++ b/stacksize/stacksize.go
@@ -14,19 +14,38 @@ import (
// set to true to print information useful for debugging
const debugPrint = false
-type sizeType uint8
+// SizeType indicates whether a stack or frame size could be determined and if
+// not, why.
+type SizeType uint8
// Results after trying to determine the stack size of a function in the call
// graph. The goal is to find a maximum (bounded) stack size, but sometimes this
// is not possible for some reasons such as recursion or indirect calls.
const (
- Undefined sizeType = iota // not yet calculated
+ Undefined SizeType = iota // not yet calculated
Unknown // child has unknown stack size
Bounded // stack size is fixed at compile time (no recursion etc)
Recursive
IndirectCall
)
+func (s SizeType) String() string {
+ switch s {
+ case Undefined:
+ return "undefined"
+ case Unknown:
+ return "unknown"
+ case Bounded:
+ return "bounded"
+ case Recursive:
+ return "recursive"
+ case IndirectCall:
+ return "indirect call"
+ default:
+ return "<?>"
+ }
+}
+
// CallNode is a node in the call graph (that is, a function). Because this is
// determined after linking, there may be multiple names for a single function
// (due to aliases). It is also possible multiple functions have the same name
@@ -37,9 +56,9 @@ type CallNode struct {
Size uint64 // symbol size, in bytes
Children []*CallNode // functions this function calls
FrameSize uint64 // frame size, if FrameSizeType is Bounded
- FrameSizeType sizeType // can be Undefined or Bounded
+ FrameSizeType SizeType // can be Undefined or Bounded
stackSize uint64
- stackSizeType sizeType
+ stackSizeType SizeType
missingFrameInfo *CallNode // the child function that is the cause for not being able to determine the stack size
}
@@ -236,7 +255,7 @@ func findSymbol(symbolList []*CallNode, address uint64) *CallNode {
// returns the maximum stack size, whether this size can be known at compile
// time and the call node responsible for failing to determine the maximum stack
// usage. The stack size is only valid if sizeType is Bounded.
-func (node *CallNode) StackSize() (uint64, sizeType, *CallNode) {
+func (node *CallNode) StackSize() (uint64, SizeType, *CallNode) {
if node.stackSizeType == Undefined {
node.determineStackSize(make(map[*CallNode]struct{}))
}