Compiler Construction
Mayer Goldberg \ Ben-Gurion University Tuesday 10th December, 2019
Mayer Goldberg \ Ben-Gurion University Compiler Construction 1 / 54
Compiler Construction Compiler Construction 1 / 54 Mayer Goldberg \ - - PowerPoint PPT Presentation
Compiler Construction Compiler Construction 1 / 54 Mayer Goldberg \ Ben-Gurion University Tuesday 10 th December, 2019 Mayer Goldberg \ Ben-Gurion University Chapter 5 Agenda tail-call-optimization Compiler Construction 2 / 54 Intuition
Mayer Goldberg \ Ben-Gurion University Compiler Construction 1 / 54
▶ Intuition about the tail-calls, tail-position, & the
▶ The tail-position, tail-call ▶ The TCO ▶ Loops & tail-recursion ▶ Annotating the tail-call ▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 2 / 54
▶ Two people are walking through a forest, and encounter a witch
▶ The witch grants them three wishes… ▶ Here is what each person wished for:
▶ What is the difgerence?
Mayer Goldberg \ Ben-Gurion University Compiler Construction 3 / 54
▶ Here is what each person wished for:
▶ The fjrst person’s wishes are simple to grant ▶ The second person’s wishes are annoying:
▶ The witch must remember what to do once she returned from
▶ Since this nonsense is going to go on for a while, the witch
Mayer Goldberg \ Ben-Gurion University Compiler Construction 4 / 54
▶ Non-tail-calls require additional stack frames to manage
▶ The stack depth (in frames) is proportional to the number of
▶ Tail-calls do not require additional stack frames
▶ The stack depth (in frames) is independent of the number of
Mayer Goldberg \ Ben-Gurion University Compiler Construction 5 / 54
▶ You are surfjng a web browser ▶ The browser is broken: It has no ⟨Back⟩ key
▶ Once you click on a link, you are unable to return
▶ To read a web page, you therefore right-click on a link & select
▶ You read the page in the new frame, possibly opening links in
▶ When you are done reading a page, you click on the ⊠ button
Mayer Goldberg \ Ben-Gurion University Compiler Construction 6 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 7 / 54
▶ Some web pages have special links:
▶ These links are not just the last links on the page ▶ These links are the last thing on the page ▶ There’s nothing to read past these links!
Mayer Goldberg \ Ben-Gurion University Compiler Construction 8 / 54
▶ Enjoy the logo; It is not a link! 😊 Mayer Goldberg \ Ben-Gurion University Compiler Construction 9 / 54
▶ Because there’s nothing to read past these links, we need
▶ Rather than right-click & open the page in the new frame, we
▶ The new contents shall overwrite the old contents ▶ The new contents can be larger or smaller than the contents it
▶ The size of the frame can change ▶ The number of frames shall not change ▶ When we’re done reading the page, we close it with ⊠ Mayer Goldberg \ Ben-Gurion University Compiler Construction 10 / 54
a new frame a new frame a new frame
Mayer Goldberg \ Ben-Gurion University Compiler Construction 11 / 54
▶ The tail-position, tail-call ▶ The TCO ▶ Loops & tail-recursion ▶ Annotating the tail-call ▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 12 / 54
▶ The tail-position is a point in the body of a function, procedure,
▶ Exception handling: Similarly to return-statements,
▶ Because computation may proceed non-linearly, there many be
▶ To fjnd the tail positions, fjnd all points in the code where a
Mayer Goldberg \ Ben-Gurion University Compiler Construction 13 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 14 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 15 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 16 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 17 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 18 / 54
▶ tail-call
▶ While it is possible to return after computing previous
Mayer Goldberg \ Ben-Gurion University Compiler Construction 19 / 54
▶ The above example contains no application in tail-position
Mayer Goldberg \ Ben-Gurion University Compiler Construction 20 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 21 / 54
▶ tail-call
▶ The marked application is in tail-position relative to its
Mayer Goldberg \ Ben-Gurion University Compiler Construction 22 / 54
▶ tail-calls
Mayer Goldberg \ Ben-Gurion University Compiler Construction 23 / 54
▶
▶ Therefore, the last expression in the implicit sequence of the
Mayer Goldberg \ Ben-Gurion University Compiler Construction 24 / 54
▶ On the one hand, there is only one tail-call that appears
▶ On the other hand, there is another tail-call that shall take place
Mayer Goldberg \ Ben-Gurion University Compiler Construction 25 / 54
▶ This applicatoin is not in tail-position
▶ This applicatoin is in tail-position
Mayer Goldberg \ Ben-Gurion University Compiler Construction 26 / 54
▶ The TCO ▶ Loops & tail-recursion ▶ Annotating the tail-call ▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 27 / 54
▶ Function/method calls ordinarily open new activation frames on
▶ Function/method calls in tail-position need not open new
▶ Only two items in the current activation frame need to be
▶ The old frame-pointer ▶ The return-address
▶ Everything else on the stack —
▶ The lexical environment ▶ The values of arguments ▶ Any local values
Mayer Goldberg \ Ben-Gurion University Compiler Construction 28 / 54
▶ The tail-call optimization optimizes stack frames
▶ In some situations this may also optimize time ▶ We shall not encounter many other optimizations of space ▶ The tail-call optimization is very important! Mayer Goldberg \ Ben-Gurion University Compiler Construction 29 / 54
▶ Loops & tail-recursion ▶ Annotating the tail-call ▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 30 / 54
▶ All loops are special cases of recursive functions where the
▶ The TCO is our license to use recursive procedures to
▶ Absent the TCO, iteration using recursion would be
Mayer Goldberg \ Ben-Gurion University Compiler Construction 31 / 54
▶ By now, we know how to identify the tail-position ▶ We made the claim that the TCO is important because it gives
Mayer Goldberg \ Ben-Gurion University Compiler Construction 32 / 54
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 33 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 34 / 54
▶ Notice that the body is parameterized by the index-variable of
▶
Mayer Goldberg \ Ben-Gurion University Compiler Construction 35 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 36 / 54
▶ The tail-call optimization is not just important for loops ▶ Consider Ackermann’s Function:
▶ tail-calls ▶ non-tail-call ▶ The TCO cuts reduces the number of frames needed by 50%,
Mayer Goldberg \ Ben-Gurion University Compiler Construction 37 / 54
▶ When a frame is overwritten, debug information is lost ▶ Smalltalk & Java have great debuggers
▶ Scheme does not!
▶ Language implementations that do not implement the TCO
▶ No Scheme compiler does this ▶ It’s easy (if tedious) to by hand:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 38 / 54
▶ Annotating the tail-call ▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 39 / 54
▶ Annotating tail-calls is done in a single pass over the AST of
▶ You are given the type expr' which includes the type
▶ The simplest way to annotate tail-calls is to carry along an
▶ The initial value of in_tp is false ▶ When an Appic is encountered and the value of in_tp is true,
▶ Upon entering lambda-expressions (of any kind), the value of
Mayer Goldberg \ Ben-Gurion University Compiler Construction 40 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 41 / 54
▶ What TCO code looks like ▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 42 / 54
▶ The new frame is identical to the old frame, both in size and
Mayer Goldberg \ Ben-Gurion University Compiler Construction 43 / 54
▶ Notice that the current frame is changed in place ▶ Notice that goto replaces the function call ▶ Notice that one non-tail-call remains
Mayer Goldberg \ Ben-Gurion University Compiler Construction 44 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 45 / 54
▶ When the tail-call is not immediately-recursive
▶ non-recursive, or ▶ mutually-recursive
▶ This would require that we goto from within the body of one
▶ The new frame can be very difgerent in size, argument count,
Mayer Goldberg \ Ben-Gurion University Compiler Construction 46 / 54
▶ Tail-recursion, whether immediate or mutual, is a special case of
▶ The general tail-recursion optimization is all that is required to
▶ This is required by the standard for Scheme
▶ The tail-call optimization is more general than the tail-recursion
▶ The tail-call optimization crosses the boundaries of
Mayer Goldberg \ Ben-Gurion University Compiler Construction 47 / 54
▶ Implementing the TCO
Mayer Goldberg \ Ben-Gurion University Compiler Construction 48 / 54
▶ Verify that we have a closure!
▶ Loop, memcpy, whatever…
Mayer Goldberg \ Ben-Gurion University Compiler Construction 49 / 54
▶ This can be difgerent from the number of arguments you
▶ If you call a procedure with n arguments and it tail-calls a
▶ Variadic lambda-expressions and lambda-expressions with
Mayer Goldberg \ Ben-Gurion University Compiler Construction 50 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 51 / 54
A-n-1 A-n-2 ⋯ A-0 n lex-env-g ret-to-f B-m-1 B-m-2 B-m-3 ⋯ B-0 m lex-env-h rbp-in-f A [non-tail] call to (g A-0 ⋯ A-n-1) from within the body
Frame of the call (g A-0 ⋯ A-n-1) ret-to-g Frame of the call (h B-0 ... B-m-1) Setting up the stack for a [non-tail] call (h B-0 ⋯ B-m-1) from within the body
Once called, h shall push the rbp... Setting up the stack for a non-tail call A-n-1 A-n-2 ⋯ A-0 n lex-env-g ret-to-f B-m-1 B-m-2 B-m-3 ⋯ B-0 m lex-env-h rbp-in-f A [non-tail] call to (g A-0 ⋯ A-n-1) from within the body
Frame of the call (g A-0 ⋯ A-n-1) ret-to-f Setting up the stack for a tail-call (h B-0 ⋯ B-m-1) from within the body
Once called, h shall push the rbp... Frame of the call (h B-0 ... B-m-1) B-m-1 B-m-2 B-m-3 B-0 m lex-env-h ret-to-f The stack set up for the tail-call (h B-0 ⋯ B-m-1) after overwriting the frame from the call to g, and before jumping to f Setting up the stack for a tail-call
Mayer Goldberg \ Ben-Gurion University Compiler Construction 52 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 53 / 54
Mayer Goldberg \ Ben-Gurion University Compiler Construction 54 / 54