Compiler and Runtime Support for Continuation Marks Matthew Flatt R

Compiler and Runtime Support for Continuation Marks Matthew Flatt R

Compiler and Runtime Support for Continuation Marks Matthew Flatt R. Kent Dybvig University of Utah Cisco Systems, Inc. USA USA [email protected] [email protected] Abstract 1 Binding and Control Continuation marks enable dynamic binding and context Suppose that a program needs to call a function with out- inspection in a language with proper handling of tail calls put redirected to a file instead of the current default output and first-class, multi-prompt, delimited continuations. The stream. One way a language can support such redirection simplest and most direct use of continuation marks is to is by having a global variable like stdout hold the default implement dynamically scoped variables, such as the current output destination for functions like printf, and then a output stream or the current exception handler. Other uses program can temporarily change the value of stdout and include stack inspection for debugging or security checks, restore it when the function call returns: serialization of an in-progress computation, and run-time elision of redundant checks. By exposing continuation marks FILE *orig_stdout = stdout; to users of a programming language, more kinds of language stdout = f_output; extensions can be implemented as libraries without further func(); changes to the compiler. At the same time, the compiler and stdout = orig_stdout; runtime system must provide an efficient implementation of continuation marks to ensure that library-implemented This approach has several potential problems. If the host language extensions are as effective as changing the compiler. language supports threads, then stdout must be a thread- Our implementation of continuation marks for Chez Scheme local variable so that redirecting output in one thread does (in support of Racket) makes dynamic binding and lookup not interfere with other threads. If the host language sup- constant-time and fast, preserves the performance of Chez ports exceptions, then a form analogous to try–finally is Scheme’s first-class continuations, and imposes negligible needed to ensure that stdout is reset on an exception escape. overhead on program fragments that do not use first-class If the host language supports proper handling of tail calls, continuations or marks. then func no longer can be called in tail position (in contrast CCS Concepts: • Software and its engineering ! Com- to passing the output stream explicitly to func and having pilers; Runtime environments; Control structures. it threaded throughout func’s computation), which might limit the use of this kind of redirection. If the host language Keywords: Dynamic binding, context inspection supports first-class continuations, then in case a continua- tion is captured during the call to func, stdout should be ACM Reference Format: set and restored using a mechanism like Scheme’s dynamic- Matthew Flatt and R. Kent Dybvig. 2020. Compiler and Runtime wind (which is a kind of generalization of try–finally), Support for Continuation Marks. In Proceedings of the 41st ACM but that adds a winding cost for jumping into or out of a SIGPLAN International Conference on Programming Language De- sign and Implementation (PLDI ’20), June 15–20, 2020, London, UK. continuation. ACM, New York, NY, USA, 14 pages. https://doi.org/10.1145/3385412. All of these issues are related to using global state to track 3385981 an intent about a program’s dynamic extent. A language implementation must already include some explicit repre- sentation of dynamic extent as a continuation, whether or not that continuation is exposed as a first-class value. The con- PLDI ’20, June 15–20, 2020, London, UK tinuation may be implemented as a call stack, for example. © 2020 Copyright held by the owner/author(s). Publication rights licensed The language implementer must have taken care to select to ACM. a representation of the continuation that is efficient and ex- This is the author’s version of the work. It is posted here for your personal pressive enough for the language’s control constructs. So, use. Not for redistribution. The definitive Version of Record was published instead of having users of a language track dynamic extent in Proceedings of the 41st ACM SIGPLAN International Conference on Pro- gramming Language Design and Implementation (PLDI ’20), June 15–20, 2020, through external state, the language should include built-in London, UK, https://doi.org/10.1145/3385412.3385981. constructs to reflect on continuations, provided that support- ing these additional constructs does not unduly burden the PLDI ’20, June 15–20, 2020, London, UK Matthew Flatt and R. Kent Dybvig implementation. Built-in operations enable a more expres- same as for delimited continuations with tagged prompts. sive and efficient implementation that takes advantage of Although all control and binding constructs (including con- internal representations of continuations. tinuation marks) can be encoded with effect handlers or In Racket, the output-redirection example is written delimited continuations, recent work on effect handlers in- cludes direct semantic support for specialized constructs, (parameterize([current-output-port f-output]) partly on the grounds that they can be more efficient [9, (func)) 10] including for dynamic binding [5]. We are following a where current-output-port is defined to hold a dynami- similar path, but with a baseline implementation of contin- cally scoped binding, and that binding is used by functions uations that tends to be much faster already compared to like printf. In this example, the output stream is set to f- other existing implementations. output during the call to func, which is called in tail position Contributions in this paper: with respect to the parameterize form and might capture • We offer the first report on implementing direct com- its continuation. If it does capture the continuation, the dy- piler and runtime support for continuation marks. namic binding of current-output-port to f-output sticks • We demonstrate that the implementation of continu- with the continuation without increasing the cost of captur- ation marks is compatible with a high-performance ing or restoring the continuation. The parameterize form implementation of first-class, delimited continuations. is a library-implemented language extension (i.e., a macro), • We demonstrate that compiler and runtime support but it relies on a lower-level form that is built into the core for continuation marks can improve the performance language and compiler: continuation marks [7]. of applications. Like closures, tail calls, and first-class continuations, con- tinuation marks enable useful language extensions without 2 Using Continuations Marks further changes to the compiler’s core language. Continua- The core Racket constructs for continuation marks include tion marks in Racket have been used to implement dynamic operations to set a mark on the current continuation and to binding [17], debugging [8, 22], profiling [1], generators [16 get marks of any continuation. §4.14.3, 26], serializable continuations in a web server [23], security contracts [24], and space-efficient contracts [14]. 2.1 Setting Marks To support a Racket implementation on Chez Scheme [15], we add continuation attachments to the Chez Scheme com- The expression form piler and runtime system. This even-simpler core construct (with-continuation-mark key val body) supports a layer that implements Racket’s rich language of maps key to val in the current continuation and evaluates continuation marks and delimited continuations [17], which body in tail position. Since body is in tail position, its value in turn supports Racket’s ecosystem of library-implemented is the result of the with-continuation-mark expression. languages and language extensions. The performance of con- For example, tinuation marks in Racket on Chez Scheme compares favor- ably with the traditional implementation of Racket, which (with-continuation-mark 'team-color "red" (player-desc)) sacrifices some performance on every non-tail call to provide better performance for continuation marks. produces the result of calling player-desc while the key Our implementation of continuation attachments for Chez 'team-color is mapped to the value "red" during the call. Scheme is nearly pay-as-you go, imposing a small cost on pro- If key is already mapped to a value in the current contin- grams that use first-class continuations and dynamic-wind uation frame, then with-continuation-mark replaces the and no cost on programs that do not use them (or continua- old mapping in that frame. If key is instead set in a more tion marks). The implementation is modest, touching about nested continuation frame, then the nested mapping for key 35 (of 18k) lines in Chez Scheme’s C-implemented kernel and is left in place while a new mapping is added to the current 500 (of 94k) lines in the Scheme-implemented compiler and frame. run-time system. Compiler-supported continuation attach- For example, in ments perform 3 to 20 times as fast as an implementation (with-continuation-mark 'team-color "red" without compiler support; for Racket on Chez Scheme, that (place-in-game improvement makes continuation marks perform generally (player-desc) better than in the original Racket implementation. (with-continuation-mark 'team-color "blue" (all-teams-desc)))) Relatively few languages currently offer first-class contin- uations, much less the richness of Racket’s control constructs. then the call to player-desc sees 'team-color mapped However, interest is growing around delimited continuations, to "red", while the call to (all-teams-desc) sees 'team- particularly in the form of algebraic effect handlers [25], and color immediately mapped to "blue" and also mapped the implementation strategies for effect handlers are the to "red" in a deeper continuation frame; overall, it sees Compiler and Runtime Support for Continuation Marks PLDI ’20, June 15–20, 2020, London, UK (list "blue" "red") as a list of mappings for 'team- (define(all-team-colors) color. Whether a list of mappings or only the newest map- (continuation-mark-set->list(current-continuation-marks) ping is relevant depends on how a key is used in a program.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    14 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us