runtime environments
play

Runtime Environments Where We Are Source Lexical Analysis Code - PowerPoint PPT Presentation

Runtime Environments Where We Are Source Lexical Analysis Code Syntax Analysis Semantic Analysis IR Generation IR Optimization Code Generation Machine Optimization Code Where We Are Source Lexical Analysis Code Syntax Analysis


  1. Activation Trees ● An activation tree is a tree structure representing all of the function calls made by a program on a particular execution. ● Depends on the runtime behavior of a program; can't always be determined at compile-time. ● (The static equivalent is the call graph ). ● Each node in the tree is an activation record. ● Each activation record stores a control link to the activation record of the function that invoked it.

  2. Activation Trees

  3. Activation Trees int main() { Fib(3); } int Fib(int n) { if (n <= 1) return n; return Fib(n – 1) + Fib(n – 2); }

  4. Activation Trees int main() { main Fib(3); } int Fib(int n) { if (n <= 1) return n; return Fib(n – 1) + Fib(n – 2); }

  5. Activation Trees int main() { main Fib(3); } int Fib(int n) { Fib if (n <= 1) return n; n = 3 return Fib(n – 1) + Fib(n – 2); }

  6. Activation Trees int main() { main Fib(3); } int Fib(int n) { Fib if (n <= 1) return n; n = 3 return Fib(n – 1) + Fib(n – 2); } Fib n = 2

  7. Activation Trees int main() { main Fib(3); } int Fib(int n) { Fib if (n <= 1) return n; n = 3 return Fib(n – 1) + Fib(n – 2); } Fib n = 2 Fib n = 1

  8. Activation Trees int main() { main Fib(3); } int Fib(int n) { Fib if (n <= 1) return n; n = 3 return Fib(n – 1) + Fib(n – 2); } Fib n = 2 Fib Fib n = 1 n = 0

  9. Activation Trees int main() { main Fib(3); } int Fib(int n) { Fib if (n <= 1) return n; n = 3 return Fib(n – 1) + Fib(n – 2); } Fib Fib n = 2 n = 1 Fib Fib n = 1 n = 0

  10. An activation tree is a spaghetti stack .

  11. The runtime stack is an optimization of this spaghetti stack.

  12. Why Can We Optimize the Stack? ● Once a function returns, its activation record cannot be referenced again. ● We don't need to store old nodes in the activation tree. ● Every activation record has either finished executing or is an ancestor of the current activation record. ● We don't need to keep multiple branches alive at any one time. ● These are not always true!

  13. Breaking Assumption 1 ● “Once a function returns, its activation record cannot be referenced again.” ● Any ideas on how to break this?

  14. Breaking Assumption 1 ● “Once a function returns, its activation record cannot be referenced again.” ● Any ideas on how to break this? ● One option: Closures function CreateCounter() { var counter = 0; return function() { counter ++; return counter; } }

  15. Breaking Assumption 1 ● “Once a function returns, its activation record cannot be referenced again.” ● Any ideas on how to break this? ● One option: Closures function CreateCounter() { var counter = 0; return function() { counter ++; return counter; } }

  16. Closures

  17. Closures function CreateCounter() { var counter = 0; return function() { counter ++; return counter; } } function MyFunction() { f = CreateCounter(); print(f()); print(f()); }

  18. Closures function CreateCounter() { var counter = 0; return function() { counter ++; return counter; } } function MyFunction() { f = CreateCounter(); print(f()); print(f()); } >

  19. Closures function CreateCounter() { var counter = 0; MyFunction return function() { counter ++; return counter; } } function MyFunction() { f = CreateCounter(); print(f()); print(f()); } >

  20. Closures function CreateCounter() { var counter = 0; MyFunction return function() { counter ++; return counter; CreateCounter } } counter = 0 function MyFunction() { f = CreateCounter(); print(f()); print(f()); } >

  21. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 0 function MyFunction() { f = CreateCounter(); print(f()); print(f()); } >

  22. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 0 function MyFunction() { f = CreateCounter(); <fn> print(f()); print(f()); } >

  23. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 0 function MyFunction() { f = CreateCounter(); <fn> print(f()); print(f()); } >

  24. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 1 function MyFunction() { f = CreateCounter(); <fn> print(f()); print(f()); } >

  25. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 1 function MyFunction() { f = CreateCounter(); <fn> print(f()); print(f()); } >

  26. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 1 function MyFunction() { f = CreateCounter(); <fn> print(f()); print(f()); } > 1

  27. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 1 function MyFunction() { f = CreateCounter(); <fn> <fn> print(f()); print(f()); } > 1

  28. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 1 function MyFunction() { f = CreateCounter(); <fn> <fn> print(f()); print(f()); } > 1

  29. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 2 function MyFunction() { f = CreateCounter(); <fn> <fn> print(f()); print(f()); } > 1

  30. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 2 function MyFunction() { f = CreateCounter(); <fn> <fn> print(f()); print(f()); } > 1

  31. Closures function CreateCounter() { var counter = 0; MyFunction return function() { f = <fn> counter ++; return counter; CreateCounter } } counter = 2 function MyFunction() { f = CreateCounter(); <fn> <fn> print(f()); print(f()); } > 1 2

  32. Control and Access Links ● The control link of a function is a pointer to the function that called it. ● Used to determine where to resume execution after the function returns. ● The access link of a function is a pointer to the activation record in which the function was created. ● Used by nested functions to determine the location of variables from the outer scope.

  33. Closures and the Runtime Stack ● Languages supporting closures do not typically have a runtime stack. ● Activation records typically dynamically allocated and garbage collected. ● Interesting exception: gcc C allows for nested functions, but uses a runtime stack. ● Behavior is undefined if nested function accesses data from its enclosing function once that function returns. ● (Why?)

  34. Breaking Assumption 2 ● “Every activation record has either finished executing or is an ancestor of the current activation record.” ● Any ideas on how to break this?

  35. Breaking Assumption 2 ● “Every activation record has either finished executing or is an ancestor of the current activation record.” ● Any ideas on how to break this? ● One idea: Coroutines def downFrom(n): while n > 0: yield n n = n - 1

  36. Breaking Assumption 2 ● “Every activation record has either finished executing or is an ancestor of the current activation record.” ● Any ideas on how to break this? ● One idea: Coroutines def downFrom(n): while n > 0: yield n n = n - 1

  37. Coroutines

  38. Coroutines def downFrom(n): while n > 0: yield n n = n – 1 def myFunc(): for i in downFrom(3): print i

  39. Coroutines def downFrom(n): while n > 0: yield n n = n – 1 def myFunc(): for i in downFrom(3): print i >

  40. Coroutines def downFrom(n): myFunc while n > 0: yield n n = n – 1 def myFunc(): for i in downFrom(3): print i >

  41. Coroutines def downFrom(n): myFunc while n > 0: yield n n = n – 1 def myFunc(): for i in downFrom(3): print i >

  42. Coroutines def downFrom(n): myFunc while n > 0: yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i >

  43. Coroutines def downFrom(n): myFunc while n > 0: yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i >

  44. Coroutines def downFrom(n): myFunc while n > 0: yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3) : print i >

  45. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3) : print i >

  46. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i >

  47. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i > 3

  48. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i > 3

  49. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 3 for i in downFrom(3): print i > 3

  50. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3

  51. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3

  52. Coroutines def downFrom(n): myFunc while n > 0: i = 3 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3

  53. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3

  54. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3

  55. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3 2

  56. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3 2

  57. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 2 for i in downFrom(3): print i > 3 2

  58. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2

  59. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2

  60. Coroutines def downFrom(n): myFunc while n > 0: i = 2 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2

  61. Coroutines def downFrom(n): myFunc while n > 0: i = 1 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2

  62. Coroutines def downFrom(n): myFunc while n > 0: i = 1 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2

  63. Coroutines def downFrom(n): myFunc while n > 0: i = 1 yield n n = n – 1 downFrom def myFunc(): n = 1 for i in downFrom(3): print i > 3 2 1

Recommend


More recommend