Changeset 9cdfa5fb for doc/theses
- Timestamp:
- Sep 10, 2021, 10:43:15 AM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 63b3279
- Parents:
- d0b9247
- Location:
- doc/theses/andrew_beach_MMath
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/andrew_beach_MMath/conclusion.tex
rd0b9247 r9cdfa5fb 3 3 % Just a little knot to tie the paper together. 4 4 5 In the previous chapters this thesis presents the design and implementation5 In the previous chapters, this thesis presents the design and implementation 6 6 of \CFA's exception handling mechanism (EHM). 7 7 Both the design and implementation are based off of tools and 8 8 techniques developed for other programming languages but they were adapted to 9 9 better fit \CFA's feature set and add a few features that do not exist in 10 other EHMs ;10 other EHMs, 11 11 including conditional matching, default handlers for unhandled exceptions 12 12 and cancellation though coroutines and threads back to the program main stack. -
doc/theses/andrew_beach_MMath/existing.tex
rd0b9247 r9cdfa5fb 6 6 compatibility with C and its programmers. \CFA is designed to have an 7 7 orthogonal feature-set based closely on the C programming paradigm 8 (non-object-oriented) and these features can be added incrementally to an 9 existing C code-base allowing programmers to learn \CFA on an as-needed basis. 8 (non-object-oriented), and these features can be added incrementally to an 9 existing C code-base, 10 allowing programmers to learn \CFA on an as-needed basis. 10 11 11 12 Only those \CFA features pertaining to this thesis are discussed. … … 45 46 \CFA adds a reference type to C as an auto-dereferencing pointer. 46 47 They work very similarly to pointers. 47 Reference-types are written the same way as a pointer-typebut each48 Reference-types are written the same way as pointer-types, but each 48 49 asterisk (@*@) is replaced with a ampersand (@&@); 49 this includes cv-qualifiers and multiple levels of reference. 50 51 Generally, references act like pointers with an implicate dereferencing 50 this includes cv-qualifiers (\snake{const} and \snake{volatile}) 51 %\todo{Should I go into even more detail on cv-qualifiers.} 52 and multiple levels of reference. 53 54 Generally, references act like pointers with an implicit dereferencing 52 55 operation added to each use of the variable. 53 56 These automatic dereferences may be disabled with the address-of operator … … 83 86 Mutable references may be assigned to by converting them to a pointer 84 87 with a @&@ and then assigning a pointer to them, as in @&ri = &j;@ above. 85 % ???86 88 87 89 \section{Operators} … … 93 95 For example, 94 96 infixed multiplication is @?*?@, while prefix dereference is @*?@. 95 This syntax make it easy to tell the difference between prefix operations96 (such as @++?@) and post -fix operations (@?++@).97 This syntax makes it easy to tell the difference between prefix operations 98 (such as @++?@) and postfix operations (@?++@). 97 99 98 100 As an example, here are the addition and equality operators for a point type. … … 104 106 } 105 107 \end{cfa} 106 Note that this syntax works effectively but a textual transformation,108 Note that this syntax works effectively as a textual transformation; 107 109 the compiler converts all operators into functions and then resolves them 108 110 normally. This means any combination of types may be used, … … 113 115 %\subsection{Constructors and Destructors} 114 116 In \CFA, constructors and destructors are operators, which means they are 115 functions with special operator names rather than type names in \Cpp.117 functions with special operator names, rather than type names as in \Cpp. 116 118 Both constructors and destructors can be implicity called by the compiler, 117 119 however the operator names allow explicit calls. … … 137 139 @b@ because of the explicit call and @a@ implicitly. 138 140 @c@ will be initalized with the second constructor. 139 Currently, there is no general way to skip initial ation.141 Currently, there is no general way to skip initialization. 140 142 % I don't use @= anywhere in the thesis. 141 143 … … 202 204 do_twice(i); 203 205 \end{cfa} 204 Any objectwith a type fulfilling the assertion may be passed as an argument to206 Any value with a type fulfilling the assertion may be passed as an argument to 205 207 a @do_twice@ call. 206 208 … … 222 224 function. The matched assertion function is then passed as a function pointer 223 225 to @do_twice@ and called within it. 224 The global definition of @do_once@ is ignored, however if quadrupletook a226 The global definition of @do_once@ is ignored, however if @quadruple@ took a 225 227 @double@ argument, then the global definition would be used instead as it 226 228 would then be a better match.\cite{Moss19} 227 229 228 230 To avoid typing long lists of assertions, constraints can be collected into 229 convenient apackage called a @trait@, which can then be used in an assertion231 a convenient package called a @trait@, which can then be used in an assertion 230 232 instead of the individual constraints. 231 233 \begin{cfa} … … 241 243 functions and variables, and are usually used to create a shorthand for, and 242 244 give descriptive names to, common groupings of assertions describing a certain 243 functionality, like @sum able@, @listable@, \etc.245 functionality, like @summable@, @listable@, \etc. 244 246 245 247 Polymorphic structures and unions are defined by qualifying an aggregate type 246 248 with @forall@. The type variables work the same except they are used in field 247 declarations instead of parameters, returns ,and local variable declarations.249 declarations instead of parameters, returns and local variable declarations. 248 250 \begin{cfa} 249 251 forall(dtype T) … … 261 263 262 264 \section{Control Flow} 263 \CFA has a number of advanced control-flow features: @generator@, @coroutine@, @monitor@, @mutex@ parameters, and @thread@. 265 \CFA has a number of advanced control-flow features: @generator@, @coroutine@, 266 @monitor@, @mutex@ parameters, and @thread@. 264 267 The two features that interact with 265 268 the exception system are @coroutine@ and @thread@; they and their supporting … … 268 271 \subsection{Coroutine} 269 272 A coroutine is a type with associated functions, where the functions are not 270 required to finish execution when control is handed back to the caller. Instead 273 required to finish execution when control is handed back to the caller. 274 Instead, 271 275 they may suspend execution at any time and be resumed later at the point of 272 last suspension. (Generators are stackless and coroutines are stackful.) These 276 last suspension. 277 Coroutine 273 278 types are not concurrent but share some similarities along with common 274 underpinnings, so they are combined with the \CFA threading library. Further 275 discussion in this section only refers to the coroutine because generators are 276 similar. 279 underpinnings, so they are combined with the \CFA threading library. 280 % I had mention of generators, but they don't actually matter here. 277 281 278 282 In \CFA, a coroutine is created using the @coroutine@ keyword, which is an … … 322 326 \end{cfa} 323 327 324 When the main function returns the coroutine halts and can no longer be328 When the main function returns, the coroutine halts and can no longer be 325 329 resumed. 326 330 327 331 \subsection{Monitor and Mutex Parameter} 328 Concurrency does not guarantee ordering; without ordering results are332 Concurrency does not guarantee ordering; without ordering, results are 329 333 non-deterministic. To claw back ordering, \CFA uses monitors and @mutex@ 330 334 (mutual exclusion) parameters. A monitor is another kind of aggregate, where … … 332 336 @mutex@ parameters. 333 337 334 A function that requires deterministic (ordered) execution ,acquires mutual338 A function that requires deterministic (ordered) execution acquires mutual 335 339 exclusion on a monitor object by qualifying an object reference parameter with 336 @mutex@.340 the @mutex@ qualifier. 337 341 \begin{cfa} 338 342 void example(MonitorA & mutex argA, MonitorB & mutex argB); … … 344 348 345 349 \subsection{Thread} 346 Functions, generators , and coroutines are sequentialso there is only a single350 Functions, generators and coroutines are sequential, so there is only a single 347 351 (but potentially sophisticated) execution path in a program. Threads introduce 348 352 multiple execution paths that continue independently. 349 353 350 354 For threads to work safely with objects requires mutual exclusion using 351 monitors and mutex parameters. For threads to work safely with other threads ,355 monitors and mutex parameters. For threads to work safely with other threads 352 356 also requires mutual exclusion in the form of a communication rendezvous, which 353 357 also supports internal synchronization as for mutex objects. For exceptions, -
doc/theses/andrew_beach_MMath/features.tex
rd0b9247 r9cdfa5fb 5 5 and begins with a general overview of EHMs. It is not a strict 6 6 definition of all EHMs nor an exhaustive list of all possible features. 7 However it does cover the most common structure and features found in them.7 However, it does cover the most common structure and features found in them. 8 8 9 9 \section{Overview of EHMs} … … 42 42 43 43 The @try@ statements of \Cpp, Java and Python are common examples. All three 44 also show another common feature of handlers ,they are grouped by the guarded44 also show another common feature of handlers: they are grouped by the guarded 45 45 region. 46 46 … … 101 101 between different sub-hierarchies. 102 102 This design is used in \CFA even though it is not a object-orientated 103 language ;so different tools are used to create the hierarchy.103 language, so different tools are used to create the hierarchy. 104 104 105 105 % Could I cite the rational for the Python IO exception rework? … … 118 118 For effective exception handling, additional information is often passed 119 119 from the raise to the handler and back again. 120 So far, only communication of the exception s'identity is covered.120 So far, only communication of the exception's identity is covered. 121 121 A common communication method for adding information to an exception 122 122 is putting fields into the exception instance … … 129 129 \section{Virtuals} 130 130 \label{s:virtuals} 131 %\todo{Maybe explain what "virtual" actually means.} 131 132 Virtual types and casts are not part of \CFA's EHM nor are they required for 132 133 an EHM. … … 152 153 % A type's descendants are its children and its children's descendants. 153 154 154 For the purposes of illustration, a proposed -- but unimplemented syntax --155 For the purposes of illustration, a proposed, but unimplemented, syntax 155 156 will be used. Each virtual type is represented by a trait with an annotation 156 157 that makes it a virtual type. This annotation is empty for a root type, which … … 177 178 \end{minipage} 178 179 179 Every virtual type also has a list of virtual members and a unique id ,180 both are stored in a virtual table.180 Every virtual type also has a list of virtual members and a unique id. 181 Both are stored in a virtual table. 181 182 Every instance of a virtual type also has a pointer to a virtual table stored 182 183 in it, although there is no per-type virtual table as in many other languages. 183 184 184 The list of virtual members is built up down the tree. Every virtual type 185 The list of virtual members is accumulated from the root type down the tree. 186 Every virtual type 185 187 inherits the list of virtual members from its parent and may add more 186 188 virtual members to the end of the list which are passed on to its children. … … 198 200 % Consider adding a diagram, but we might be good with the explanation. 199 201 200 As @child_type@ is a child of @root_type@ it has the virtual members of202 As @child_type@ is a child of @root_type@, it has the virtual members of 201 203 @root_type@ (@to_string@ and @size@) as well as the one it declared 202 204 (@irrelevant_function@). … … 206 208 The names ``size" and ``align" are reserved for the size and alignment of the 207 209 virtual type, and are always automatically initialized as such. 208 The other special case areuses of the trait's polymorphic argument210 The other special case is uses of the trait's polymorphic argument 209 211 (@T@ in the example), which are always updated to refer to the current 210 virtual type. This allows functions that refer to t opolymorphic argument212 virtual type. This allows functions that refer to the polymorphic argument 211 213 to act as traditional virtual methods (@to_string@ in the example), as the 212 214 object can always be passed to a virtual method in its virtual table. 213 215 214 Up until this point the virtual system is similar to ones found in215 object-oriented languages but this is where \CFA diverges.216 Up until this point, the virtual system is similar to ones found in 217 object-oriented languages, but this is where \CFA diverges. 216 218 Objects encapsulate a single set of methods in each type, 217 219 universally across the entire program, … … 223 225 224 226 In \CFA, types do not encapsulate any code. 225 Whether or not satisfies any given assertion, and hence any trait, is227 Whether or not a type satisfies any given assertion, and hence any trait, is 226 228 context sensitive. Types can begin to satisfy a trait, stop satisfying it or 227 229 satisfy the same trait at any lexical location in the program. 228 In this sense, a ntype's implementation in the set of functions and variables230 In this sense, a type's implementation in the set of functions and variables 229 231 that allow it to satisfy a trait is ``open" and can change 230 232 throughout the program. … … 248 250 \end{cfa} 249 251 250 Like any variable they may be forward declared with the @extern@ keyword.252 Like any variable, they may be forward declared with the @extern@ keyword. 251 253 Forward declaring virtual tables is relatively common. 252 254 Many virtual types have an ``obvious" implementation that works in most … … 259 261 Initialization is automatic. 260 262 The type id and special virtual members ``size" and ``align" only depend on 261 the virtual type, which is fixed given the type of the virtual table and263 the virtual type, which is fixed given the type of the virtual table, and 262 264 so the compiler fills in a fixed value. 263 The other virtual members are resolved ,using the best match to the member's265 The other virtual members are resolved using the best match to the member's 264 266 name and type, in the same context as the virtual table is declared using 265 267 \CFA's normal resolution rules. 266 268 267 While much of the virtual infrastructure is created, it is currently only used 269 While much of the virtual infrastructure has been created, 270 it is currently only used 268 271 internally for exception handling. The only user-level feature is the virtual 269 272 cast, which is the same as the \Cpp \code{C++}{dynamic_cast}. … … 274 277 Note, the syntax and semantics matches a C-cast, rather than the function-like 275 278 \Cpp syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be 276 a pointer to a virtual type.279 pointers to virtual types. 277 280 The cast dynamically checks if the @EXPRESSION@ type is the same or a sub-type 278 281 of @TYPE@, and if true, returns a pointer to the 279 282 @EXPRESSION@ object, otherwise it returns @0p@ (null pointer). 283 This allows the expression to be used as both a cast and a type check. 280 284 281 285 \section{Exceptions} 282 286 283 287 The syntax for declaring an exception is the same as declaring a structure 284 except the keyword that is swapped out:288 except the keyword: 285 289 \begin{cfa} 286 290 exception TYPE_NAME { … … 289 293 \end{cfa} 290 294 291 Fields are filled in the same way as a structure as well. However an extra295 Fields are filled in the same way as a structure as well. However, an extra 292 296 field is added that contains the pointer to the virtual table. 293 297 It must be explicitly initialized by the user when the exception is … … 299 303 300 304 \begin{minipage}[t]{0.4\textwidth} 301 Header :305 Header (.hfa): 302 306 \begin{cfa} 303 307 exception Example { … … 310 314 \end{minipage} 311 315 \begin{minipage}[t]{0.6\textwidth} 312 Source:316 Implementation (.cfa): 313 317 \begin{cfa} 314 318 vtable(Example) example_base_vtable … … 319 323 %\subsection{Exception Details} 320 324 This is the only interface needed when raising and handling exceptions. 321 However it is actually a shorthand for a more complex322 trait 325 However, it is actually a shorthand for a more complex 326 trait-based interface. 323 327 324 328 The language views exceptions through a series of traits. … … 336 340 completing the virtual system). The imaginary assertions would probably come 337 341 from a trait defined by the virtual system, and state that the exception type 338 is a virtual type, is a descendant of @exception_t@ (the base exception type) 342 is a virtual type, 343 that that the type is a descendant of @exception_t@ (the base exception type) 339 344 and allow the user to find the virtual table type. 340 345 … … 355 360 }; 356 361 \end{cfa} 357 Both traits ensure a pair of types is an exception type , its virtual table358 type 362 Both traits ensure a pair of types is an exception type and 363 its virtual table type, 359 364 and defines one of the two default handlers. The default handlers are used 360 as fallbacks and are discussed in detail in \ vref{s:ExceptionHandling}.365 as fallbacks and are discussed in detail in \autoref{s:ExceptionHandling}. 361 366 362 367 However, all three of these traits can be tricky to use directly. 363 368 While there is a bit of repetition required, 364 369 the largest issue is that the virtual table type is mangled and not in a user 365 facing way. So these three macros are provided to wrap these traits to370 facing way. So, these three macros are provided to wrap these traits to 366 371 simplify referring to the names: 367 372 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. … … 371 376 The second (optional) argument is a parenthesized list of polymorphic 372 377 arguments. This argument is only used with polymorphic exceptions and the 373 list is bepassed to both types.378 list is passed to both types. 374 379 In the current set-up, the two types always have the same polymorphic 375 arguments so these macros can be used without losing flexibility.376 377 For example consider a function that is polymorphic over types that have a380 arguments, so these macros can be used without losing flexibility. 381 382 For example, consider a function that is polymorphic over types that have a 378 383 defined arithmetic exception: 379 384 \begin{cfa} … … 388 393 These twin operations are the core of \CFA's exception handling mechanism. 389 394 This section covers the general patterns shared by the two operations and 390 then goes on to cover the details each individual operation.395 then goes on to cover the details of each individual operation. 391 396 392 397 Both operations follow the same set of steps. … … 407 412 \label{s:Termination} 408 413 Termination handling is the familiar kind of handling 409 andused in most programming414 used in most programming 410 415 languages with exception handling. 411 416 It is a dynamic, non-local goto. If the raised exception is matched and … … 483 488 Since it is so general, a more specific handler can be defined, 484 489 overriding the default behaviour for the specific exception types. 490 %\todo{Examples?} 485 491 486 492 \subsection{Resumption} … … 542 548 @EXCEPTION_TYPE@$_i$ is matched and @NAME@$_i$ is bound to the exception, 543 549 @HANDLER_BLOCK@$_i$ is executed right away without first unwinding the stack. 544 After the block has finished running control jumps to the raise site, where550 After the block has finished running, control jumps to the raise site, where 545 551 the just handled exception came from, and continues executing after it, 546 552 not after the try statement. 553 %\todo{Examples?} 547 554 548 555 \subsubsection{Resumption Marking} … … 551 558 not unwind the stack. A side effect is that, when a handler is matched 552 559 and run, its try block (the guarded statements) and every try statement 553 searched before it are still on the stack. The represence can lead to560 searched before it are still on the stack. Their presence can lead to 554 561 the recursive resumption problem.\cite{Buhr00a} 555 562 % Other possible citation is MacLaren77, but the form is different. … … 585 592 \end{center} 586 593 587 There are other sets of marking rules that could be used ,588 for instance, marking just the handlers that caught the exception, 594 There are other sets of marking rules that could be used. 595 For instance, marking just the handlers that caught the exception 589 596 would also prevent recursive resumption. 590 However, the rules selected mirror swhat happens with termination,597 However, the rules selected mirror what happens with termination, 591 598 so this reduces the amount of rules and patterns a programmer has to know. 592 599 … … 628 635 // Handle a failure relating to f2 further down the stack. 629 636 \end{cfa} 630 In this example the file that experienced the IO error is used to decide637 In this example, the file that experienced the IO error is used to decide 631 638 which handler should be run, if any at all. 632 639 … … 657 664 658 665 \subsection{Comparison with Reraising} 659 In languages without conditional catch , that isno ability to match an660 exception based on something other than its type ,it can be mimicked666 In languages without conditional catch -- that is, no ability to match an 667 exception based on something other than its type -- it can be mimicked 661 668 by matching all exceptions of the right type, checking any additional 662 669 conditions inside the handler and re-raising the exception if it does not … … 664 671 665 672 Here is a minimal example comparing both patterns, using @throw;@ 666 (no argument) to start a re-raise.673 (no operand) to start a re-raise. 667 674 \begin{center} 668 675 \begin{tabular}{l r} … … 692 699 \end{tabular} 693 700 \end{center} 694 At first glance catch-and-reraise may appear to just be a quality oflife701 At first glance, catch-and-reraise may appear to just be a quality-of-life 695 702 feature, but there are some significant differences between the two 696 strat agies.703 strategies. 697 704 698 705 A simple difference that is more important for \CFA than many other languages 699 is that the raise site changes , with a re-raisebut does not with a706 is that the raise site changes with a re-raise, but does not with a 700 707 conditional catch. 701 708 This is important in \CFA because control returns to the raise site to run 702 the per-site default handler. Because of this only a conditional catch can709 the per-site default handler. Because of this, only a conditional catch can 703 710 allow the original raise to continue. 704 711 … … 753 760 % } else throw; 754 761 % } 755 In similar simple examples translating from re-raise to conditional catch756 takes less code but it does not have a general trivial solution either.762 In similar simple examples, translating from re-raise to conditional catch 763 takes less code but it does not have a general, trivial solution either. 757 764 758 765 So, given that the two patterns do not trivially translate into each other, 759 766 it becomes a matter of which on should be encouraged and made the default. 760 From the premise that if a handler thatcould handle an exception then it767 From the premise that if a handler could handle an exception then it 761 768 should, it follows that checking as many handlers as possible is preferred. 762 So conditional catch and checking later handlers is a good default.769 So, conditional catch and checking later handlers is a good default. 763 770 764 771 \section{Finally Clauses} 765 772 \label{s:FinallyClauses} 766 Finally clauses are used to p reform unconditional clean-up when leaving a773 Finally clauses are used to perform unconditional cleanup when leaving a 767 774 scope and are placed at the end of a try statement after any handler clauses: 768 775 \begin{cfa} … … 782 789 Execution of the finally block should always finish, meaning control runs off 783 790 the end of the block. This requirement ensures control always continues as if 784 the finally clause is not present, \ie finally is for cleanup not changing791 the finally clause is not present, \ie finally is for cleanup, not changing 785 792 control flow. 786 793 Because of this requirement, local control flow out of the finally block 787 794 is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or 788 795 @return@ that causes control to leave the finally block. Other ways to leave 789 the finally block, such as a long jumpor termination are much harder to check,790 and at best requir ingadditional run-time overhead, and so are only796 the finally block, such as a @longjmp@ or termination are much harder to check, 797 and at best require additional run-time overhead, and so are only 791 798 discouraged. 792 799 793 Not all languages with unwinding have finally clauses. Notably \Cpp does800 Not all languages with unwinding have finally clauses. Notably, \Cpp does 794 801 without it as destructors, and the RAII design pattern, serve a similar role. 795 802 Although destructors and finally clauses can be used for the same cases, … … 798 805 Destructors take more work to create, but if there is clean-up code 799 806 that needs to be run every time a type is used, they are much easier 800 to set -up for each use. % It's automatic.801 On the other hand finally clauses capture the local context, so iseasy to802 use when the clean -up is not dependent on the type of a variable or requires807 to set up for each use. % It's automatic. 808 On the other hand, finally clauses capture the local context, so are easy to 809 use when the cleanup is not dependent on the type of a variable or requires 803 810 information from multiple variables. 804 811 … … 807 814 Cancellation is a stack-level abort, which can be thought of as as an 808 815 uncatchable termination. It unwinds the entire current stack, and if 809 possible forwards the cancellation exception to a different stack.816 possible, forwards the cancellation exception to a different stack. 810 817 811 818 Cancellation is not an exception operation like termination or resumption. 812 819 There is no special statement for starting a cancellation; instead the standard 813 library function @cancel_stack@ is called passing an exception. Unlike a814 raise, this exception is not used in matching only to pass information about820 library function @cancel_stack@ is called, passing an exception. Unlike a 821 raise, this exception is not used in matching, only to pass information about 815 822 the cause of the cancellation. 816 823 Finally, as no handler is provided, there is no default handler. 817 824 818 After @cancel_stack@ is called the exception is copied into the EHM's memory825 After @cancel_stack@ is called, the exception is copied into the EHM's memory 819 826 and the current stack is unwound. 820 827 The behaviour after that depends on the kind of stack being cancelled. 821 828 822 829 \paragraph{Main Stack} 823 The main stack is the one used by the program main at the start of execution, 830 The main stack is the one used by 831 the program's main function at the start of execution, 824 832 and is the only stack in a sequential program. 825 After the main stack is unwound there is a program-level abort.833 After the main stack is unwound, there is a program-level abort. 826 834 827 835 The first reason for this behaviour is for sequential programs where there 828 is only one stack, and hence to stack to pass information to.836 is only one stack, and hence no stack to pass information to. 829 837 Second, even in concurrent programs, the main stack has no dependency 830 838 on another stack and no reliable way to find another living stack. … … 842 850 and an implicit join (from a destructor call). The explicit join takes the 843 851 default handler (@defaultResumptionHandler@) from its calling context while 844 the implicit join provides its own ;which does a program abort if the852 the implicit join provides its own, which does a program abort if the 845 853 @ThreadCancelled@ exception cannot be handled. 846 854 -
doc/theses/andrew_beach_MMath/future.tex
rd0b9247 r9cdfa5fb 3 3 4 4 The following discussion covers both possible interesting research 5 that could follow from this work as longas simple implementation5 that could follow from this work as well as simple implementation 6 6 improvements. 7 7 … … 10 10 \CFA is a developing programming language. As such, there are partially or 11 11 unimplemented features (including several broken components) 12 that I had to work around while building the EHM largely in12 that I had to work around while building the EHM largely in 13 13 the \CFA language (some C components). Below are a few of these issues 14 14 and how implementing/fixing them would affect the EHM. 15 In addition there are some simple improvements that had no interesting15 In addition, there are some simple improvements that had no interesting 16 16 research attached to them but would make using the language easier. 17 17 \begin{itemize} … … 28 28 Termination handlers cannot use local control-flow transfers, \eg by @break@, 29 29 @return@, \etc. The reason is that current code generation hoists a handler 30 into a nested function for convenience (versus assembl e-code generation at the30 into a nested function for convenience (versus assembly-code generation at the 31 31 try statement). Hence, when the handler runs, it can still access local 32 32 variables in the lexical scope of the try statement. Still, it does mean 33 33 that seemingly local control flow is not in fact local and crosses a function 34 34 boundary. 35 Making the termination handler s code within the surrounding35 Making the termination handler's code within the surrounding 36 36 function would remove this limitation. 37 37 % Try blocks are much more difficult to do practically (requires our own 38 38 % assembly) and resumption handlers have some theoretical complexity. 39 39 \item 40 There is no detection of colliding unwinds. It is possible for clean -up code41 run during an unwind to trigger another unwind that escapes the clean -up code42 itself ;such as a termination exception caught further down the stack or a40 There is no detection of colliding unwinds. It is possible for cleanup code 41 run during an unwind to trigger another unwind that escapes the cleanup code 42 itself, such as a termination exception caught further down the stack or a 43 43 cancellation. There do exist ways to handle this case, but currently there is 44 44 no detection and the first unwind will simply be forgotten, often leaving … … 64 64 Other features of the virtual system could also remove some of the 65 65 special cases around exception virtual tables, such as the generation 66 of the @msg@ function , could be removed.66 of the @msg@ function. 67 67 68 68 The full virtual system might also include other improvement like associated … … 74 74 \section{Additional Raises} 75 75 Several other kinds of exception raises were considered beyond termination 76 (@throw@), resumption (@throwResume@), and re raise.76 (@throw@), resumption (@throwResume@), and re-raise. 77 77 78 78 The first is a non-local/concurrent raise providing asynchronous exceptions, … … 110 110 passed on. 111 111 112 However checked exceptions were never seriously considered for this project112 Checked exceptions were never seriously considered for this project 113 113 because they have significant trade-offs in usability and code reuse in 114 114 exchange for the increased safety. … … 116 116 higher-order functions from the functions the user passed into the 117 117 higher-order function. There are no well known solutions to this problem 118 that were satisfactory for \CFA (which carries some of C's flexibility119 oversafety design) so additional research is needed.118 that were satisfactory for \CFA (which carries some of C's 119 flexibility-over-safety design) so additional research is needed. 120 120 121 121 Follow-up work might add some form of checked exceptions to \CFA, … … 140 140 Zero-cost resumptions is still an open problem. First, because libunwind does 141 141 not support a successful-exiting stack-search without doing an unwind. 142 Workarounds are possible but awkward. Ideally an extension to libunwind could142 Workarounds are possible but awkward. Ideally, an extension to libunwind could 143 143 be made, but that would either require separate maintenance or gaining enough 144 144 support to have it folded into the official library itself. 145 145 146 Also new techniques to skip previously searched parts of the stack need to be146 Also, new techniques to skip previously searched parts of the stack need to be 147 147 developed to handle the recursive resume problem and support advanced algebraic 148 148 effects. -
doc/theses/andrew_beach_MMath/implement.tex
rd0b9247 r9cdfa5fb 14 14 \label{s:VirtualSystem} 15 15 % Virtual table rules. Virtual tables, the pointer to them and the cast. 16 While the \CFA virtual system currently has only onepublic features, virtual16 While the \CFA virtual system currently has only two public features, virtual 17 17 cast and virtual tables, 18 % ??? refs (see the virtual cast feature \vpageref{p:VirtualCast}),19 18 substantial structure is required to support them, 20 19 and provide features for exception handling and the standard library. … … 35 34 as part of field-by-field construction. 36 35 37 \subsection{Type I d}38 Every virtual type has a unique id.36 \subsection{Type ID} 37 Every virtual type has a unique ID. 39 38 These are used in type equality, to check if the representation of two values 40 39 are the same, and to access the type's type information. … … 44 43 45 44 Our approach for program uniqueness is using a static declaration for each 46 type id, where the run-time storage address of that variable is guaranteed to45 type ID, where the run-time storage address of that variable is guaranteed to 47 46 be unique during program execution. 48 The type idstorage can also be used for other purposes,47 The type ID storage can also be used for other purposes, 49 48 and is used for type information. 50 49 51 The problem is that a type idmay appear in multiple TUs that compose a52 program (see \autoref{ss:VirtualTable}) ;so the initial solution would seem53 to be make it external in each translation unit. Hovever, the type idmust50 The problem is that a type ID may appear in multiple TUs that compose a 51 program (see \autoref{ss:VirtualTable}), so the initial solution would seem 52 to be make it external in each translation unit. Hovever, the type ID must 54 53 have a declaration in (exactly) one of the TUs to create the storage. 55 54 No other declaration related to the virtual type has this property, so doing 56 55 this through standard C declarations would require the user to do it manually. 57 56 58 Instead the linker is used to handle this problem.57 Instead, the linker is used to handle this problem. 59 58 % I did not base anything off of C++17; they are solving the same problem. 60 59 A new feature has been added to \CFA for this purpose, the special attribute 61 60 \snake{cfa_linkonce}, which uses the special section @.gnu.linkonce@. 62 When used as a prefix (\eg @.gnu.linkonce.example@) the linker does61 When used as a prefix (\eg @.gnu.linkonce.example@), the linker does 63 62 not combine these sections, but instead discards all but one with the same 64 63 full name. 65 64 66 So each type id must be given a unique section name with the linkonce67 prefix. Luckily \CFA already has a way to get unique names, the name mangler.65 So, each type ID must be given a unique section name with the \snake{linkonce} 66 prefix. Luckily, \CFA already has a way to get unique names, the name mangler. 68 67 For example, this could be written directly in \CFA: 69 68 \begin{cfa} … … 74 73 __attribute__((section(".gnu.linkonce._X1fFv___1"))) void _X1fFv___1() {} 75 74 \end{cfa} 76 This is done internally to access the name mangler s.75 This is done internally to access the name mangler. 77 76 This attribute is useful for other purposes, any other place a unique 78 77 instance required, and should eventually be made part of a public and … … 81 80 \subsection{Type Information} 82 81 83 There is data stored at the type id's declaration, the type information.84 The type information currently is only the parent's type idor, if the82 There is data stored at the type ID's declaration, the type information. 83 The type information currently is only the parent's type ID or, if the 85 84 type has no parent, the null pointer. 86 The ancestors of a virtual type are found by traversing type ids through85 The ancestors of a virtual type are found by traversing type IDs through 87 86 the type information. 88 87 An example using helper macros looks like: … … 105 104 \item 106 105 Generate a new structure definition to store the type 107 information. The layout is the same in each case, just the parent's type id,106 information. The layout is the same in each case, just the parent's type ID, 108 107 but the types used change from instance to instance. 109 108 The generated name is used for both this structure and, if relevant, the … … 115 114 \item 116 115 The definition is generated and initialized. 117 The parent idis set to the null pointer or to the address of the parent's116 The parent ID is set to the null pointer or to the address of the parent's 118 117 type information instance. Name resolution handles the rest. 119 118 \item … … 151 150 file as if it was a forward declaration, except no definition is required. 152 151 153 This technique is used for type -idinstances. A link-once definition is152 This technique is used for type ID instances. A link-once definition is 154 153 generated each time the structure is seen. This will result in multiple 155 154 copies but the link-once attribute ensures all but one are removed for a … … 168 167 \subsection{Virtual Table} 169 168 \label{ss:VirtualTable} 170 Each virtual type has a virtual table type that stores its type id and 169 %\todo{Clarify virtual table type vs. virtual table instance.} 170 Each virtual type has a virtual table type that stores its type ID and 171 171 virtual members. 172 172 Each virtual type instance is bound to a table instance that is filled with … … 176 176 177 177 The layout always comes in three parts (see \autoref{f:VirtualTableLayout}). 178 The first section is just the type idat the head of the table. It is always178 The first section is just the type ID at the head of the table. It is always 179 179 there to ensure that it can be found even when the accessing code does not 180 180 know which virtual type it has. 181 The second section areall the virtual members of the parent, in the same181 The second section is all the virtual members of the parent, in the same 182 182 order as they appear in the parent's virtual table. Note that the type may 183 183 change slightly as references to the ``this" change. This is limited to … … 199 199 This, combined with the fixed offset to the virtual table pointer, means that 200 200 for any virtual type, it is always safe to access its virtual table and, 201 from there, it is safe to check the type idto identify the exact type of the201 from there, it is safe to check the type ID to identify the exact type of the 202 202 underlying object, access any of the virtual members and pass the object to 203 203 any of the method-like virtual members. … … 207 207 the context of the declaration. 208 208 209 The type id is always fixed;with each virtual table type having210 exactly one possible type id.209 The type ID is always fixed, with each virtual table type having 210 exactly one possible type ID. 211 211 The virtual members are usually filled in by type resolution. 212 212 The best match for a given name and type at the declaration site is used. 213 213 There are two exceptions to that rule: the @size@ field, the type's size, 214 is set using a @sizeof@ expression and the @align@ field, the214 is set using a @sizeof@ expression, and the @align@ field, the 215 215 type's alignment, is set using an @alignof@ expression. 216 216 217 217 Most of these tools are already inside the compiler. Using simple 218 code transformations early on in compilation ,allows most of that work to be218 code transformations early on in compilation allows most of that work to be 219 219 handed off to the existing tools. \autoref{f:VirtualTableTransformation} 220 shows an example transformation ,this example shows an exception virtual table.220 shows an example transformation; this example shows an exception virtual table. 221 221 It also shows the transformation on the full declaration. 222 222 For a forward declaration, the @extern@ keyword is preserved and the … … 312 312 struct __cfavir_type_id * const * child ); 313 313 \end{cfa} 314 The type idfor the target type of the virtual cast is passed in as314 The type ID for the target type of the virtual cast is passed in as 315 315 @parent@ and 316 316 the cast target is passed in as @child@. … … 322 322 The virtual cast either returns the original pointer or the null pointer 323 323 as the new type. 324 So the function does the parent check and returns the appropriate value.325 The parent check is a simple linear search of child's ancestors using the324 The function does the parent check and returns the appropriate value. 325 The parent check is a simple linear search of the child's ancestors using the 326 326 type information. 327 327 … … 329 329 % The implementation of exception types. 330 330 331 Creating exceptions can roughly divided into two parts,331 Creating exceptions can be roughly divided into two parts: 332 332 the exceptions themselves and the virtual system interactions. 333 333 … … 361 361 362 362 All types associated with a virtual type, 363 the types of the virtual table and the type id,363 the types of the virtual table and the type ID, 364 364 are generated when the virtual type (the exception) is first found. 365 The type id(the instance) is generated with the exception, if it is365 The type ID (the instance) is generated with the exception, if it is 366 366 a monomorphic type. 367 However, if the exception is polymorphic, then a different type idhas to367 However, if the exception is polymorphic, then a different type ID has to 368 368 be generated for every instance. In this case, generation is delayed 369 369 until a virtual table is created. … … 372 372 When a virtual table is created and initialized, two functions are created 373 373 to fill in the list of virtual members. 374 The first is a copyfunction that adapts the exception's copy constructor374 The first is the @copy@ function that adapts the exception's copy constructor 375 375 to work with pointers, avoiding some issues with the current copy constructor 376 376 interface. 377 Second is the msgfunction that returns a C-string with the type's name,377 Second is the @msg@ function that returns a C-string with the type's name, 378 378 including any polymorphic parameters. 379 379 … … 402 402 403 403 % Discussing multiple frame stack unwinding: 404 Unwinding across multiple stack frames is more complex because that404 Unwinding across multiple stack frames is more complex, because that 405 405 information is no longer contained within the current function. 406 406 With separate compilation, 407 407 a function does not know its callers nor their frame layout. 408 408 Even using the return address, that information is encoded in terms of 409 actions in code, intermixed with the actions required finish the function.409 actions in code, intermixed with the actions required to finish the function. 410 410 Without changing the main code path it is impossible to select one of those 411 411 two groups of actions at the return site. 412 412 413 The traditional unwinding mechanism for C is implemented by saving a snap -shot414 of a function's state with @setjmp@ and restoring that snap -shot with413 The traditional unwinding mechanism for C is implemented by saving a snapshot 414 of a function's state with @setjmp@ and restoring that snapshot with 415 415 @longjmp@. This approach bypasses the need to know stack details by simply 416 reseting to a snap -shot of an arbitrary but existing function frame on the417 stack. It is up to the programmer to ensure the snap -shot is valid when it is418 reset and that all required clean -up from the unwound stacks is performed.416 reseting to a snapshot of an arbitrary but existing function frame on the 417 stack. It is up to the programmer to ensure the snapshot is valid when it is 418 reset and that all required cleanup from the unwound stacks is performed. 419 419 This approach is fragile and requires extra work in the surrounding code. 420 420 421 421 With respect to the extra work in the surrounding code, 422 many languages define clean -up actions that must be taken when certain423 sections of the stack are removed . Such as when the storage for a variable422 many languages define cleanup actions that must be taken when certain 423 sections of the stack are removed, such as when the storage for a variable 424 424 is removed from the stack, possibly requiring a destructor call, 425 425 or when a try statement with a finally clause is 426 426 (conceptually) popped from the stack. 427 None of these cases should be handled by the user -- -that would contradict the428 intention of these features -- -so they need to be handled automatically.427 None of these cases should be handled by the user -- that would contradict the 428 intention of these features -- so they need to be handled automatically. 429 429 430 430 To safely remove sections of the stack, the language must be able to find and 431 run these clean -up actions even when removing multiple functions unknown at431 run these cleanup actions even when removing multiple functions unknown at 432 432 the beginning of the unwinding. 433 433 … … 529 529 provided storage object. It has two public fields: the @exception_class@, 530 530 which is described above, and the @exception_cleanup@ function. 531 The clean -up function is used by the EHM to clean-up the exception, if it531 The cleanup function is used by the EHM to clean up the exception. If it 532 532 should need to be freed at an unusual time, it takes an argument that says 533 533 why it had to be cleaned up. … … 551 551 of the most recent stack frame. It continues to call personality functions 552 552 traversing the stack from newest to oldest until a function finds a handler or 553 the end of the stack is reached. In the latter case, raise exception returns554 @_U RC_END_OF_STACK@.555 556 Second, when a handler is matched, raise exception moves to the clean-up557 phase and walks the stack a second time.553 the end of the stack is reached. In the latter case, 554 @_Unwind_RaiseException@ returns @_URC_END_OF_STACK@. 555 556 Second, when a handler is matched, @_Unwind_RaiseException@ 557 moves to the cleanup phase and walks the stack a second time. 558 558 Once again, it calls the personality functions of each stack frame from newest 559 559 to oldest. This pass stops at the stack frame containing the matching handler. 560 If that personality function has not install a handler, it is an error.561 562 If an error is encountered, raise exceptionreturns either560 If that personality function has not installed a handler, it is an error. 561 562 If an error is encountered, @_Unwind_RaiseException@ returns either 563 563 @_URC_FATAL_PHASE1_ERROR@ or @_URC_FATAL_PHASE2_ERROR@ depending on when the 564 564 error occurred. … … 571 571 _Unwind_Stop_Fn, void *); 572 572 \end{cfa} 573 It also unwinds the stack but it does not use the search phase. Instead another 573 It also unwinds the stack but it does not use the search phase. Instead, 574 another 574 575 function, the stop function, is used to stop searching. The exception is the 575 same as the one passed to raise exception. The extra arguments are the stop 576 same as the one passed to @_Unwind_RaiseException@. 577 The extra arguments are the stop 576 578 function and the stop parameter. The stop function has a similar interface as a 577 579 personality function, except it is also passed the stop parameter. … … 721 723 one list per stack, with the 722 724 list head stored in the exception context. Within each linked list, the most 723 recently thrown exception is at the head followed by older thrown725 recently thrown exception is at the head, followed by older thrown 724 726 exceptions. This format allows exceptions to be thrown, while a different 725 727 exception is being handled. The exception at the head of the list is currently … … 732 734 exception into managed memory. After the exception is handled, the free 733 735 function is used to clean up the exception and then the entire node is 734 passed to free, returning the memory back to the heap.736 passed to @free@, returning the memory back to the heap. 735 737 736 738 \subsection{Try Statements and Catch Clauses} … … 757 759 The three functions passed to try terminate are: 758 760 \begin{description} 759 \item[try function:] This function is the try block , it is where all the code761 \item[try function:] This function is the try block. It is where all the code 760 762 from inside the try block is placed. It takes no parameters and has no 761 763 return value. This function is called during regular execution to run the try … … 766 768 from the conditional part of each handler and runs each check, top to bottom, 767 769 in turn, to see if the exception matches this handler. 768 The match is performed in two steps , firsta virtual cast is used to check770 The match is performed in two steps: first, a virtual cast is used to check 769 771 if the raised exception is an instance of the declared exception type or 770 772 one of its descendant types, and then the condition is evaluated, if 771 773 present. 772 774 The match function takes a pointer to the exception and returns 0 if the 773 exception is not handled here. Otherwise the return value is the idof the775 exception is not handled here. Otherwise, the return value is the ID of the 774 776 handler that matches the exception. 775 777 … … 782 784 \end{description} 783 785 All three functions are created with GCC nested functions. GCC nested functions 784 can be used to create closures ,786 can be used to create closures; 785 787 in other words, 786 functions that can refer to variables in their lexical scope even 788 functions that can refer to variables in their lexical scope even though 787 789 those variables are part of a different function. 788 790 This approach allows the functions to refer to all the … … 869 871 At each node, the EHM checks to see if the try statement the node represents 870 872 can handle the exception. If it can, then the exception is handled and 871 the operation finishes , otherwisethe search continues to the next node.873 the operation finishes; otherwise, the search continues to the next node. 872 874 If the search reaches the end of the list without finding a try statement 873 875 with a handler clause … … 879 881 if the exception is handled and false otherwise. 880 882 The handler function checks each of its internal handlers in order, 881 top-to-bottom, until it f unds a match. If a match is found that handler is883 top-to-bottom, until it finds a match. If a match is found that handler is 882 884 run, after which the function returns true, ignoring all remaining handlers. 883 885 If no match is found the function returns false. 884 The match is performed in two steps , first a virtual cast is used to see886 The match is performed in two steps. First a virtual cast is used to see 885 887 if the raised exception is an instance of the declared exception type or one 886 of its descendant types, if so then it is passed to the custom predicate 888 of its descendant types, if so, then the second step is to see if the 889 exception passes the custom predicate 887 890 if one is defined. 888 891 % You need to make sure the type is correct before running the predicate … … 936 939 % Recursive Resumption Stuff: 937 940 \autoref{f:ResumptionMarking} shows search skipping 938 (see \ vpageref{s:ResumptionMarking}), which ignores parts of941 (see \autoref{s:ResumptionMarking}), which ignores parts of 939 942 the stack 940 943 already examined, and is accomplished by updating the front of the list as … … 951 954 This structure also supports new handlers added while the resumption is being 952 955 handled. These are added to the front of the list, pointing back along the 953 stack -- - the first one points over all the checked handlers ---956 stack -- the first one points over all the checked handlers -- 954 957 and the ordering is maintained. 955 958 … … 979 982 %\autoref{code:cleanup} 980 983 A finally clause is handled by converting it into a once-off destructor. 981 The code inside the clause is placed into GCC nested-function984 The code inside the clause is placed into a GCC nested-function 982 985 with a unique name, and no arguments or return values. 983 986 This nested function is 984 987 then set as the cleanup function of an empty object that is declared at the 985 988 beginning of a block placed around the context of the associated try 986 statement (see \autoref{f:FinallyTransformation}).989 statement, as shown in \autoref{f:FinallyTransformation}. 987 990 988 991 \begin{figure} … … 1024 1027 % Stack selections, the three internal unwind functions. 1025 1028 1026 Cancellation also uses libunwind to do its stack traversal and unwinding ,1027 howeverit uses a different primary function: @_Unwind_ForcedUnwind@. Details1028 of its interface can be found in theSection~\vref{s:ForcedUnwind}.1029 Cancellation also uses libunwind to do its stack traversal and unwinding. 1030 However, it uses a different primary function: @_Unwind_ForcedUnwind@. Details 1031 of its interface can be found in Section~\vref{s:ForcedUnwind}. 1029 1032 1030 1033 The first step of cancellation is to find the cancelled stack and its type: -
doc/theses/andrew_beach_MMath/intro.tex
rd0b9247 r9cdfa5fb 25 25 All types of exception handling link a raise with a handler. 26 26 Both operations are usually language primitives, although raises can be 27 treated as a primitivefunction that takes an exception argument.28 Handlers are more complex as they are added to and removed from the stack29 during execution, must specify what they can handle and give the code to27 treated as a function that takes an exception argument. 28 Handlers are more complex, as they are added to and removed from the stack 29 during execution, must specify what they can handle and must give the code to 30 30 handle the exception. 31 31 … … 41 41 \input{termination} 42 42 \end{center} 43 %\todo{What does the right half of termination.fig mean?} 43 44 44 45 Resumption exception handling searches the stack for a handler and then calls … … 46 47 The handler is run on top of the existing stack, often as a new function or 47 48 closure capturing the context in which the handler was defined. 48 After the handler has finished running it returns control to the function49 After the handler has finished running, it returns control to the function 49 50 that preformed the raise, usually starting after the raise. 50 51 \begin{center} … … 53 54 54 55 Although a powerful feature, exception handling tends to be complex to set up 55 and expensive to use 56 and expensive to use, 56 57 so it is often limited to unusual or ``exceptional" cases. 57 The classic example is error handling ,exceptions can be used to58 The classic example is error handling; exceptions can be used to 58 59 remove error handling logic from the main execution path, and pay 59 60 most of the cost only when the error actually occurs. … … 63 64 The \CFA EHM implements all of the common exception features (or an 64 65 equivalent) found in most other EHMs and adds some features of its own. 65 The design of all the features had to be adapted to \CFA's feature set as66 The design of all the features had to be adapted to \CFA's feature set, as 66 67 some of the underlying tools used to implement and express exception handling 67 68 in other languages are absent in \CFA. 68 Still the resulting syntax resembles that of other languages:69 Still, the resulting syntax resembles that of other languages: 69 70 \begin{cfa} 70 71 try { … … 88 89 covering both changes to the compiler and the run-time. 89 90 In addition, a suite of test cases and performance benchmarks were created 90 along 91 alongside the implementation. 91 92 The implementation techniques are generally applicable in other programming 92 93 languages and much of the design is as well. … … 100 101 \item Implementing stack unwinding and the \CFA EHM, including updating 101 102 the \CFA compiler and the run-time environment. 102 \item Design ed and implementeda prototype virtual system.103 \item Designing and implementing a prototype virtual system. 103 104 % I think the virtual system and per-call site default handlers are the only 104 105 % "new" features, everything else is a matter of implementation. 105 106 \item Creating tests to check the behaviour of the EHM. 106 \item Creating benchmarks to check the performance sof the EHM,107 \item Creating benchmarks to check the performance of the EHM, 107 108 as compared to other languages. 108 109 \end{enumerate} … … 110 111 The rest of this thesis is organized as follows. 111 112 The current state of exceptions is covered in \autoref{s:background}. 112 The existing state of \CFA is alsocovered in \autoref{c:existing}.113 The existing state of \CFA is covered in \autoref{c:existing}. 113 114 New EHM features are introduced in \autoref{c:features}, 114 115 covering their usage and design. … … 137 138 inheriting from 138 139 \code{C++}{std::exception}. 139 Although there is a special catch-all syntax (@catch(...)@) there are no140 Although there is a special catch-all syntax (@catch(...)@), there are no 140 141 operations that can be performed on the caught value, not even type inspection. 141 Instead the base exception-type \code{C++}{std::exception} defines common142 Instead, the base exception-type \code{C++}{std::exception} defines common 142 143 functionality (such as 143 144 the ability to describe the reason the exception was raised) and all … … 148 149 149 150 Java was the next popular language to use exceptions.\cite{Java8} 150 Its exception system largely reflects that of \Cpp, except that requires151 Its exception system largely reflects that of \Cpp, except that it requires 151 152 you throw a child type of \code{Java}{java.lang.Throwable} 152 153 and it uses checked exceptions. 153 154 Checked exceptions are part of a function's interface, 154 155 the exception signature of the function. 155 Every function that could be raised from a function, either directly or156 Every exception that could be raised from a function, either directly or 156 157 because it is not handled from a called function, is given. 157 158 Using this information, it is possible to statically verify if any given 158 exception is handled and guarantee that no exception will go unhandled.159 exception is handled, and guarantee that no exception will go unhandled. 159 160 Making exception information explicit improves clarity and safety, 160 161 but can slow down or restrict programming. … … 169 170 recovery or repair. In theory that could be good enough to properly handle 170 171 the exception, but more often is used to ignore an exception that the 171 programmer does not feel is worth the effort of handling it, for instance if172 programmer does not feel is worth the effort of handling, for instance if 172 173 they do not believe it will ever be raised. 173 If they are incorrect the exception will be silenced, while in a similar174 If they are incorrect, the exception will be silenced, while in a similar 174 175 situation with unchecked exceptions the exception would at least activate 175 the language's unhandled exception code (usually program abort with an176 the language's unhandled exception code (usually, a program abort with an 176 177 error message). 177 178 178 179 %\subsection 179 180 Resumption exceptions are less popular, 180 although resumption is as old as termination; hence, few181 although resumption is as old as termination; that is, few 181 182 programming languages have implemented them. 182 183 % http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/parc/techReports/ … … 186 187 included in the \Cpp standard. 187 188 % https://en.wikipedia.org/wiki/Exception_handling 188 Since then resumptions have been ignored in main-stream programming languages.189 Since then, resumptions have been ignored in main-stream programming languages. 189 190 However, resumption is being revisited in the context of decades of other 190 191 developments in programming languages. 191 192 While rejecting resumption may have been the right decision in the past, 192 193 the situation has changed since then. 193 Some developments, such as the function programming equivalent to resumptions,194 Some developments, such as the functional programming equivalent to resumptions, 194 195 algebraic effects\cite{Zhang19}, are enjoying success. 195 A complete reexamination of resumption sis beyond this thesis,196 but the re reemergence is enoughto try them in \CFA.196 A complete reexamination of resumption is beyond this thesis, 197 but their reemergence is enough reason to try them in \CFA. 197 198 % Especially considering how much easier they are to implement than 198 199 % termination exceptions and how much Peter likes them. … … 208 209 209 210 %\subsection 210 More recently exceptions seem to be vanishing from newer programming211 More recently exceptions, seem to be vanishing from newer programming 211 212 languages, replaced by ``panic". 212 213 In Rust, a panic is just a program level abort that may be implemented by … … 218 219 219 220 %\subsection 220 Whileexception handling's most common use cases are in error handling,221 As exception handling's most common use cases are in error handling, 221 222 here are some other ways to handle errors with comparisons with exceptions. 222 223 \begin{itemize} … … 233 234 is discarded to avoid this problem. 234 235 Checking error codes also bloats the main execution path, 235 especially if the error is not handled immediately hand has to be passed236 especially if the error is not handled immediately and has to be passed 236 237 through multiple functions before it is addressed. 237 238 238 239 \item\emph{Special Return with Global Store}: 239 240 Similar to the error codes pattern but the function itself only returns 240 that there was an error 241 and store the reason for the error in a fixed global location.242 For example many routines in the C standard library will only return some241 that there was an error, 242 and stores the reason for the error in a fixed global location. 243 For example, many routines in the C standard library will only return some 243 244 error value (such as -1 or a null pointer) and the error code is written into 244 245 the standard variable @errno@. … … 253 254 Success is one tag and the errors are another. 254 255 It is also possible to make each possible error its own tag and carry its own 255 additional information, but the two 256 additional information, but the two-branch format is easy to make generic 256 257 so that one type can be used everywhere in error handling code. 257 258 … … 261 262 % Rust's \code{rust}{Result<T, E>} 262 263 The main advantage is that an arbitrary object can be used to represent an 263 error so it can include a lot more information than a simple error code.264 error, so it can include a lot more information than a simple error code. 264 265 The disadvantages include that the it does have to be checked along the main 265 execution and if there aren't primitive tagged unions properusage can be266 execution, and if there aren't primitive tagged unions proper, usage can be 266 267 hard to enforce. 267 268 … … 274 275 variable). 275 276 C++ uses this approach as its fallback system if exception handling fails, 276 such as \snake{std::terminate_handler} and, for a time, 277 \snake{std::unexpected_handler}. 277 such as \snake{std::terminate} and, for a time, 278 \snake{std::unexpected}.\footnote{\snake{std::unexpected} was part of the 279 Dynamic Exception Specification, which has been removed from the standard 280 as of C++20.\cite{CppExceptSpec}} 278 281 279 282 Handler functions work a lot like resumption exceptions, … … 291 294 happily making them expensive to use in exchange. 292 295 This difference is less important in higher-level scripting languages, 293 where using exception for other tasks is more common.296 where using exceptions for other tasks is more common. 294 297 An iconic example is Python's 295 \code{Python}{StopIteration}\cite{PythonExceptions} exception that298 \code{Python}{StopIteration}\cite{PythonExceptions} exception, that 296 299 is thrown by an iterator to indicate that it is exhausted. 297 When paired with Python's iterator-based for-loop this will be thrown every300 When paired with Python's iterator-based for-loop, this will be thrown every 298 301 time the end of the loop is reached.\cite{PythonForLoop} -
doc/theses/andrew_beach_MMath/performance.tex
rd0b9247 r9cdfa5fb 5 5 Instead, the focus was to get the features working. The only performance 6 6 requirement is to ensure the tests for correctness run in a reasonable 7 amount of time. Hence, a few basic performance tests were performed to7 amount of time. Hence, only a few basic performance tests were performed to 8 8 check this requirement. 9 9 … … 13 13 one with termination and one with resumption. 14 14 15 C++ is the most comparable language because both it and \CFA use the same15 GCC C++ is the most comparable language because both it and \CFA use the same 16 16 framework, libunwind. 17 17 In fact, the comparison is almost entirely in quality of implementation. … … 46 46 the number used in the timing runs is given with the results per test. 47 47 The Java tests run the main loop 1000 times before 48 beginning the actual test to ``warm -up" the JVM.48 beginning the actual test to ``warm up" the JVM. 49 49 % All other languages are precompiled or interpreted. 50 50 … … 54 54 unhandled exceptions in \Cpp and Java as that would cause the process to 55 55 terminate. 56 Luckily, performance on the ``give -up and kill the process" path is not56 Luckily, performance on the ``give up and kill the process" path is not 57 57 critical. 58 58 … … 76 76 using gcc-10 10.3.0 as a backend. 77 77 g++-10 10.3.0 is used for \Cpp. 78 Java tests are complied and run with version 11.0.11.79 Python used version 3.8.10.78 Java tests are complied and run with Oracle OpenJDK version 11.0.11. 79 Python used CPython version 3.8.10. 80 80 The machines used to run the tests are: 81 81 \begin{itemize}[nosep] … … 85 85 \lstinline{@} 2.5 GHz running Linux v5.11.0-25 86 86 \end{itemize} 87 Representingthe two major families of hardware architecture.87 These represent the two major families of hardware architecture. 88 88 89 89 \section{Tests} … … 93 93 94 94 \paragraph{Stack Traversal} 95 This group measures the cost of traversing the stack,95 This group of tests measures the cost of traversing the stack 96 96 (and in termination, unwinding it). 97 97 Inside the main loop is a call to a recursive function. … … 147 147 This group of tests measures the cost for setting up exception handling, 148 148 if it is 149 not used (because the exceptional case did not occur).149 not used because the exceptional case did not occur. 150 150 Tests repeatedly cross (enter, execute and leave) a try statement but never 151 151 perform a raise. … … 222 222 for that language and the result is marked N/A. 223 223 There are also cases where the feature is supported but measuring its 224 cost is impossible. This happened with Java, which uses a JIT that optimize 225 away the tests and itcannot be stopped.\cite{Dice21}224 cost is impossible. This happened with Java, which uses a JIT that optimizes 225 away the tests and cannot be stopped.\cite{Dice21} 226 226 These tests are marked N/C. 227 227 To get results in a consistent range (1 second to 1 minute is ideal, … … 230 230 results and has a value in the millions. 231 231 232 An anomaly in some results came from \CFA's use of gccnested functions.232 An anomaly in some results came from \CFA's use of GCC nested functions. 233 233 These nested functions are used to create closures that can access stack 234 234 variables in their lexical scope. 235 However, if they do so, then they can cause the benchmark's run -time to235 However, if they do so, then they can cause the benchmark's run time to 236 236 increase by an order of magnitude. 237 237 The simplest solution is to make those values global variables instead 238 of function 238 of function-local variables. 239 239 % Do we know if editing a global inside nested function is a problem? 240 240 Tests that had to be modified to avoid this problem have been marked … … 312 312 \CFA, \Cpp and Java. 313 313 % To be exact, the Match All and Match None cases. 314 %\todo{Not true in Python.} 314 315 The most likely explanation is that, since exceptions 315 316 are rarely considered to be the common case, the more optimized languages … … 346 347 Performance is similar to Empty Traversal in all languages that support finally 347 348 clauses. Only Python seems to have a larger than random noise change in 348 its run -time and it is still not large.349 its run time and it is still not large. 349 350 Despite the similarity between finally clauses and destructors, 350 finally clauses seem to avoid the spike that run -time destructors have.351 finally clauses seem to avoid the spike that run time destructors have. 351 352 Possibly some optimization removes the cost of changing contexts. 352 353 … … 356 357 This results in a significant jump. 357 358 358 Other languages experience a small increase in run -time.359 Other languages experience a small increase in run time. 359 360 The small increase likely comes from running the checks, 360 361 but they could avoid the spike by not having the same kind of overhead for … … 362 363 363 364 \item[Cross Handler] 364 Here \CFA falls behind \Cpp by a much more significant margin.365 This is likely due to the fact \CFA has to insert two extra function366 calls, while \Cpp does not have to doexecute any other instructions.365 Here, \CFA falls behind \Cpp by a much more significant margin. 366 This is likely due to the fact that \CFA has to insert two extra function 367 calls, while \Cpp does not have to execute any other instructions. 367 368 Python is much further behind. 368 369 … … 375 376 \item[Conditional Match] 376 377 Both of the conditional matching tests can be considered on their own. 377 However for evaluating the value of conditional matching itself, the378 However, for evaluating the value of conditional matching itself, the 378 379 comparison of the two sets of results is useful. 379 Consider the massive jump in run -time for \Cpp going from match all to match380 Consider the massive jump in run time for \Cpp going from match all to match 380 381 none, which none of the other languages have. 381 Some strange interaction is causing run -time to more than double for doing382 Some strange interaction is causing run time to more than double for doing 382 383 twice as many raises. 383 Java and Python avoid this problem and have similar run -time for both tests,384 Java and Python avoid this problem and have similar run time for both tests, 384 385 possibly through resource reuse or their program representation. 385 However \CFA is built like \Cpp and avoids the problem as well, this matches 386 However, \CFA is built like \Cpp, and avoids the problem as well. 387 This matches 386 388 the pattern of the conditional match, which makes the two execution paths 387 389 very similar. … … 391 393 \subsection{Resumption \texorpdfstring{(\autoref{t:PerformanceResumption})}{}} 392 394 393 Moving on to resumption, there is one general note ,395 Moving on to resumption, there is one general note: 394 396 resumption is \textit{fast}. The only test where it fell 395 397 behind termination is Cross Handler. 396 398 In every other case, the number of iterations had to be increased by a 397 factor of 10 to get the run -time in an appropriate range399 factor of 10 to get the run time in an appropriate range 398 400 and in some cases resumption still took less time. 399 401 … … 408 410 409 411 \item[D'tor Traversal] 410 Resumption does have the same spike in run -time that termination has.411 The run -time is actually very similar to Finally Traversal.412 Resumption does have the same spike in run time that termination has. 413 The run time is actually very similar to Finally Traversal. 412 414 As resumption does not unwind the stack, both destructors and finally 413 415 clauses are run while walking down the stack during the recursive returns. … … 416 418 \item[Finally Traversal] 417 419 Same as D'tor Traversal, 418 except termination did not have a spike in run -time on this test case.420 except termination did not have a spike in run time on this test case. 419 421 420 422 \item[Other Traversal] … … 427 429 The only test case where resumption could not keep up with termination, 428 430 although the difference is not as significant as many other cases. 429 It is simply a matter of where the costs come from ,430 both termination and resumption have some work to set -up or tear-down a431 It is simply a matter of where the costs come from: 432 both termination and resumption have some work to set up or tear down a 431 433 handler. It just so happens that resumption's work is slightly slower. 432 434 … … 434 436 Resumption shows a slight slowdown if the exception is not matched 435 437 by the first handler, which follows from the fact the second handler now has 436 to be checked. However the difference is not large.438 to be checked. However, the difference is not large. 437 439 438 440 \end{description} … … 448 450 More experiments could try to tease out the exact trade-offs, 449 451 but the prototype's only performance goal is to be reasonable. 450 It has already in that range, and \CFA's fixup routine simulation is452 It is already in that range, and \CFA's fixup routine simulation is 451 453 one of the faster simulations as well. 452 Plus exceptions add features and remove syntactic overhead,453 so even at similar performance resumptions have advantages454 Plus, exceptions add features and remove syntactic overhead, 455 so even at similar performance, resumptions have advantages 454 456 over fixup routines. -
doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex
rd0b9247 r9cdfa5fb 137 137 This thesis covers the design and implementation of the \CFA EHM, 138 138 along with a review of the other required \CFA features. 139 The EHM includes common features of termination exception handling and 140 similar support for resumption exception handling. 139 The EHM includes common features of termination exception handling, 140 which abandons and recovers from an operation, 141 and similar support for resumption exception handling, 142 which repairs and continues with an operation. 141 143 The design of both has been adapted to utilize other tools \CFA provides, 142 144 as well as fit with the assertion based interfaces of the language. … … 144 146 The EHM has been implemented into the \CFA compiler and run-time environment. 145 147 Although it has not yet been optimized, performance testing has shown it has 146 comparable performance to other EHM 's,148 comparable performance to other EHMs, 147 149 which is sufficient for use in current \CFA programs. 148 150 -
doc/theses/andrew_beach_MMath/uw-ethesis.bib
rd0b9247 r9cdfa5fb 40 40 } 41 41 42 @misc{CppExceptSpec, 43 author={C++ Community}, 44 key={Cpp Reference Exception Specification}, 45 howpublished={\href{https://en.cppreference.com/w/cpp/language/except_spec}{https://\-en.cppreference.com/\-w/\-cpp/\-language/\-except\_spec}}, 46 addendum={Accessed 2021-09-08}, 47 } 48 42 49 @misc{RustPanicMacro, 43 50 author={The Rust Team},
Note: See TracChangeset
for help on using the changeset viewer.