Changeset 5a40e4e for doc/theses/andrew_beach_MMath/implement.tex
- Timestamp:
- Sep 9, 2021, 3:56:32 PM (4 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- d0b9247
- Parents:
- dd1cc02 (diff), d8d512e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
doc/theses/andrew_beach_MMath/implement.tex (modified) (37 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/andrew_beach_MMath/implement.tex
rdd1cc02 r5a40e4e 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 one public feature, virtual 17 cast (see the virtual cast feature \vpageref{p:VirtualCast}), 18 substantial structure is required to support it, 16 While the \CFA virtual system currently has only one public features, virtual 17 cast and virtual tables, 18 % ??? refs (see the virtual cast feature \vpageref{p:VirtualCast}), 19 substantial structure is required to support them, 19 20 and provide features for exception handling and the standard library. 20 21 21 22 \subsection{Virtual Type} 22 Virtual types only have one change to their structure: the addition of a 23 pointer to the virtual table, which is called the \emph{virtual-table pointer}. 24 Internally, the field is called \snake{virtual_table}. 25 The field is fixed after construction. It is always the first field in the 23 A virtual type~(see \autoref{s:virtuals}) has a pointer to a virtual table, 24 called the \emph{virtual-table pointer}, 25 which binds each instance of a virtual type to a virtual table. 26 Internally, the field is called \snake{virtual_table} 27 and is fixed after construction. 28 This pointer is also the table's id and how the system accesses the 29 virtual table and the virtual members there. 30 It is always the first field in the 26 31 structure so that its location is always known. 27 \todo{Talk about constructors for virtual types (after they are working).} 28 29 The virtual table pointer binds an instance of a virtual type 30 to a virtual table. 31 The pointer is also the table's id and how the system accesses the 32 virtual table and the virtual members there. 32 33 % We have no special rules for these constructors. 34 Virtual table pointers are passed to the constructors of virtual types 35 as part of field-by-field construction. 33 36 34 37 \subsection{Type Id} 35 38 Every virtual type has a unique id. 36 Type ids can be compared for equality, 37 which checks if the types reperented are the same, 38 or used to access the type's type information. 39 These are used in type equality, to check if the representation of two values 40 are the same, and to access the type's type information. 41 This uniqueness means across a program composed of multiple translation 42 units (TU), not uniqueness across all programs or even across multiple 43 processes on the same machine. 44 45 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 to 47 be unique during program execution. 48 The type id storage can also be used for other purposes, 49 and is used for type information. 50 51 The problem is that a type id may appear in multiple TUs that compose a 52 program (see \autoref{ss:VirtualTable}); so the initial solution would seem 53 to be make it external in each translation unit. Hovever, the type id must 54 have a declaration in (exactly) one of the TUs to create the storage. 55 No other declaration related to the virtual type has this property, so doing 56 this through standard C declarations would require the user to do it manually. 57 58 Instead the linker is used to handle this problem. 59 % I did not base anything off of C++17; they are solving the same problem. 60 A new feature has been added to \CFA for this purpose, the special attribute 61 \snake{cfa_linkonce}, which uses the special section @.gnu.linkonce@. 62 When used as a prefix (\eg @.gnu.linkonce.example@) the linker does 63 not combine these sections, but instead discards all but one with the same 64 full name. 65 66 So each type id must be given a unique section name with the linkonce 67 prefix. Luckily \CFA already has a way to get unique names, the name mangler. 68 For example, this could be written directly in \CFA: 69 \begin{cfa} 70 __attribute__((cfa_linkonce)) void f() {} 71 \end{cfa} 72 This is translated to: 73 \begin{cfa} 74 __attribute__((section(".gnu.linkonce._X1fFv___1"))) void _X1fFv___1() {} 75 \end{cfa} 76 This is done internally to access the name manglers. 77 This attribute is useful for other purposes, any other place a unique 78 instance required, and should eventually be made part of a public and 79 stable feature in \CFA. 80 81 \subsection{Type Information} 82 83 There is data stored at the type id's declaration, the type information. 39 84 The type information currently is only the parent's type id or, if the 40 85 type has no parent, the null pointer. 41 42 The id's are implemented as pointers to the type's type information instance.43 Dereferencing the pointer gets the type information.44 86 The ancestors of a virtual type are found by traversing type ids through 45 87 the type information. 46 The information pushes the issue of creating a unique value (for 47 the type id) to the problem of creating a unique instance (for type 48 information), which the linker can solve. 49 50 The advanced linker support is used here to avoid having to create 51 a new declaration to attach this data to. 52 With C/\CFA's header/implementation file divide for something to appear 53 exactly once it must come from a declaration that appears in exactly one 54 implementation file; the declarations in header files may exist only once 55 they can be included in many different translation units. 56 Therefore, structure's declaration will not work. 57 Neither will attaching the type information to the virtual table -- although 58 a vtable declarations are in implemention files they are not unique, see 59 \autoref{ss:VirtualTable}. 60 Instead the same type information is generated multiple times and then 61 the new attribute \snake{cfa_linkone} is used to removed duplicates. 88 An example using helper macros looks like: 89 \begin{cfa} 90 struct INFO_TYPE(TYPE) { 91 INFO_TYPE(PARENT) const * parent; 92 }; 93 94 __attribute__((cfa_linkonce)) 95 INFO_TYPE(TYPE) const INFO_NAME(TYPE) = { 96 &INFO_NAME(PARENT), 97 }; 98 \end{cfa} 62 99 63 100 Type information is constructed as follows: 64 \begin{enumerate} 101 \begin{enumerate}[nosep] 65 102 \item 66 Use the type's name to generate a name for the type information structure .67 This is saved so it maybe reused.103 Use the type's name to generate a name for the type information structure, 104 which is saved so it can be reused. 68 105 \item 69 106 Generate a new structure definition to store the type 70 107 information. The layout is the same in each case, just the parent's type id, 71 108 but the types used change from instance to instance. 72 The generated name is used for both this structure and, if rel ivant, the109 The generated name is used for both this structure and, if relevant, the 73 110 parent pointer. 74 111 If the virtual type is polymorphic then the type information structure is 75 112 polymorphic as well, with the same polymorphic arguments. 76 113 \item 77 A sep erate name for instances is generated from the type's name.114 A separate name for instances is generated from the type's name. 78 115 \item 79 The definition is generated and initiali sed.116 The definition is generated and initialized. 80 117 The parent id is set to the null pointer or to the address of the parent's 81 118 type information instance. Name resolution handles the rest. 82 119 \item 83 120 \CFA's name mangler does its regular name mangling encoding the type of 84 the declaration into the instance name. This gives a completely unique name 121 the declaration into the instance name. 122 This process gives a completely unique name 85 123 including different instances of the same polymorphic type. 86 124 \end{enumerate} 87 \todo{The list is making me realise, some of this isn't ordered.}88 125 89 126 Writing that code manually, with helper macros for the early name mangling, … … 100 137 \end{cfa} 101 138 139 \begin{comment} 102 140 \subsubsection{\lstinline{cfa\_linkonce} Attribute} 103 % I just reali sed: This is an extension of the inline keyword.141 % I just realized: This is an extension of the inline keyword. 104 142 % An extension of C's at least, it is very similar to C++'s. 105 143 Another feature added to \CFA is a new attribute: \texttt{cfa\_linkonce}. … … 126 164 everything that comes after the special prefix, then only one is used 127 165 and the other is discarded. 166 \end{comment} 128 167 129 168 \subsection{Virtual Table} … … 136 175 below. 137 176 138 The layout always comes in three parts. 139 \todo{Add labels to the virtual table layout figure.} 177 The layout always comes in three parts (see \autoref{f:VirtualTableLayout}). 140 178 The first section is just the type id at the head of the table. It is always 141 179 there to ensure that it can be found even when the accessing code does not … … 143 181 The second section are all the virtual members of the parent, in the same 144 182 order as they appear in the parent's virtual table. Note that the type may 145 change slightly as references to the ``this" willchange. This is limited to183 change slightly as references to the ``this" change. This is limited to 146 184 inside pointers/references and via function pointers so that the size (and 147 185 hence the offsets) are the same. … … 150 188 151 189 \begin{figure} 190 \begin{center} 152 191 \input{vtable-layout} 192 \end{center} 153 193 \caption{Virtual Table Layout} 154 194 \label{f:VirtualTableLayout} 155 \todo*{Improve the Virtual Table Layout diagram.}156 195 \end{figure} 157 196 … … 176 215 type's alignment, is set using an @alignof@ expression. 177 216 178 \subsubsection{Concurrency Integration} 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 be 219 handed off to the existing tools. \autoref{f:VirtualTableTransformation} 220 shows an example transformation, this example shows an exception virtual table. 221 It also shows the transformation on the full declaration. 222 For a forward declaration, the @extern@ keyword is preserved and the 223 initializer is not added. 224 225 \begin{figure}[htb] 226 \begin{cfa} 227 vtable(example_type) example_name; 228 \end{cfa} 229 \transformline 230 % Check mangling. 231 \begin{cfa} 232 const struct example_type_vtable example_name = { 233 .__cfavir_typeid : &__cfatid_example_type, 234 .size : sizeof(example_type), 235 .copy : copy, 236 .^?{} : ^?{}, 237 .msg : msg, 238 }; 239 \end{cfa} 240 \caption{Virtual Table Transformation} 241 \label{f:VirtualTableTransformation} 242 \end{figure} 243 244 \subsection{Concurrency Integration} 179 245 Coroutines and threads need instances of @CoroutineCancelled@ and 180 246 @ThreadCancelled@ respectively to use all of their functionality. When a new … … 183 249 at the definition of the main function. 184 250 185 This is showned through code re-writing in 186 \autoref{f:ConcurrencyTypeTransformation} and 187 \autoref{f:ConcurrencyMainTransformation}. 188 In both cases the original declaration is not modified, 251 These transformations are shown through code re-writing in 252 \autoref{f:CoroutineTypeTransformation} and 253 \autoref{f:CoroutineMainTransformation}. 254 Threads use the same pattern, with some names and types changed. 255 In both cases, the original declaration is not modified, 189 256 only new ones are added. 190 257 191 \begin{figure} 258 \begin{figure}[htb] 192 259 \begin{cfa} 193 260 coroutine Example { … … 207 274 extern CoroutineCancelled_vtable & _default_vtable; 208 275 \end{cfa} 209 \caption{Co ncurrencyType Transformation}210 \label{f:Co ncurrencyTypeTransformation}276 \caption{Coroutine Type Transformation} 277 \label{f:CoroutineTypeTransformation} 211 278 \end{figure} 212 279 213 \begin{figure} 280 \begin{figure}[htb] 214 281 \begin{cfa} 215 282 void main(Example & this) { … … 229 296 &_default_vtable_object_declaration; 230 297 \end{cfa} 231 \caption{Co ncurrencyMain Transformation}232 \label{f:Co ncurrencyMainTransformation}298 \caption{Coroutine Main Transformation} 299 \label{f:CoroutineMainTransformation} 233 300 \end{figure} 234 301 … … 242 309 \begin{cfa} 243 310 void * __cfa__virtual_cast( 244 struct __cfavir_type_td parent, 245 struct __cfavir_type_id const * child ); 246 \end{cfa} 247 The type id of target type of the virtual cast is passed in as @parent@ and 311 struct __cfavir_type_id * parent, 312 struct __cfavir_type_id * const * child ); 313 \end{cfa} 314 The type id for the target type of the virtual cast is passed in as 315 @parent@ and 248 316 the cast target is passed in as @child@. 249 250 For generated C code wraps both arguments and the result with type casts. 317 The generated C code wraps both arguments and the result with type casts. 251 318 There is also an internal check inside the compiler to make sure that the 252 319 target type is a virtual type. … … 260 327 261 328 \section{Exceptions} 262 % Anything about exception construction. 329 % The implementation of exception types. 330 331 Creating exceptions can roughly divided into two parts, 332 the exceptions themselves and the virtual system interactions. 333 334 Creating an exception type is just a matter of prepending the field 335 with the virtual table pointer to the list of the fields 336 (see \autoref{f:ExceptionTypeTransformation}). 337 338 \begin{figure}[htb] 339 \begin{cfa} 340 exception new_exception { 341 // EXISTING FIELDS 342 }; 343 \end{cfa} 344 \transformline 345 \begin{cfa} 346 struct new_exception { 347 struct new_exception_vtable const * virtual_table; 348 // EXISTING FIELDS 349 }; 350 \end{cfa} 351 \caption{Exception Type Transformation} 352 \label{f:ExceptionTypeTransformation} 353 \end{figure} 354 355 The integration between exceptions and the virtual system is a bit more 356 complex simply because of the nature of the virtual system prototype. 357 The primary issue is that the virtual system has no way to detect when it 358 should generate any of its internal types and data. This is handled by 359 the exception code, which tells the virtual system when to generate 360 its components. 361 362 All types associated with a virtual type, 363 the types of the virtual table and the type id, 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 is 366 a monomorphic type. 367 However, if the exception is polymorphic, then a different type id has to 368 be generated for every instance. In this case, generation is delayed 369 until a virtual table is created. 370 % There are actually some problems with this, which is why it is not used 371 % for monomorphic types. 372 When a virtual table is created and initialized, two functions are created 373 to fill in the list of virtual members. 374 The first is a copy function that adapts the exception's copy constructor 375 to work with pointers, avoiding some issues with the current copy constructor 376 interface. 377 Second is the msg function that returns a C-string with the type's name, 378 including any polymorphic parameters. 263 379 264 380 \section{Unwinding} … … 274 390 stack. On function entry and return, unwinding is handled directly by the 275 391 call/return code embedded in the function. 276 In many cases, the position of the instruction pointer (relative to parameter 277 and local declarations) is enough to know the current size of the stack 278 frame. 279 392 393 % Discussing normal stack unwinding: 280 394 Usually, the stack-frame size is known statically based on parameter and 281 local variable declarations. Even withdynamic stack-size, the information395 local variable declarations. Even for a dynamic stack-size, the information 282 396 to determine how much of the stack has to be removed is still contained 283 397 within the function. … … 285 399 bumping the hardware stack-pointer up or down as needed. 286 400 Constructing/destructing values within a stack frame has 287 a similar complexity but can add additional work and take longer. 288 401 a similar complexity but larger constants. 402 403 % Discussing multiple frame stack unwinding: 289 404 Unwinding across multiple stack frames is more complex because that 290 405 information is no longer contained within the current function. 291 With seperate compilation a function has no way of knowing what its callers 292 are so it can't know how large those frames are. 293 Without altering the main code path it is also hard to pass that work off 294 to the caller. 406 With separate compilation, 407 a function does not know its callers nor their frame layout. 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. 410 Without changing the main code path it is impossible to select one of those 411 two groups of actions at the return site. 295 412 296 413 The traditional unwinding mechanism for C is implemented by saving a snap-shot … … 302 419 This approach is fragile and requires extra work in the surrounding code. 303 420 304 With respect to the extra work in the sur ounding code,421 With respect to the extra work in the surrounding code, 305 422 many languages define clean-up actions that must be taken when certain 306 423 sections of the stack are removed. Such as when the storage for a variable 307 is removed from the stack or when a try statement with a finally clause is 424 is removed from the stack, possibly requiring a destructor call, 425 or when a try statement with a finally clause is 308 426 (conceptually) popped from the stack. 309 None of these should be handled by the user --- that would contradict the427 None of these cases should be handled by the user --- that would contradict the 310 428 intention of these features --- so they need to be handled automatically. 311 429 … … 348 466 In plain C (which \CFA currently compiles down to) this 349 467 flag only handles the cleanup attribute: 468 %\label{code:cleanup} 350 469 \begin{cfa} 351 470 void clean_up( int * var ) { ... } … … 355 474 in this case @clean_up@, run when the variable goes out of scope. 356 475 This feature is enough to mimic destructors, 357 but not try statements which can effect476 but not try statements that affect 358 477 the unwinding. 359 478 360 479 To get full unwinding support, all of these features must be handled directly 361 in assembly and assembler directives; parti ularly the cfi directives480 in assembly and assembler directives; particularly the cfi directives 362 481 \snake{.cfi_lsda} and \snake{.cfi_personality}. 363 482 … … 399 518 @_UA_FORCE_UNWIND@ specifies a forced unwind call. Forced unwind only performs 400 519 the cleanup phase and uses a different means to decide when to stop 401 (see \ vref{s:ForcedUnwind}).520 (see \autoref{s:ForcedUnwind}). 402 521 \end{enumerate} 403 522 404 523 The @exception_class@ argument is a copy of the 405 524 \code{C}{exception}'s @exception_class@ field, 406 which is a number that identifies the exception handling mechanism525 which is a number that identifies the EHM 407 526 that created the exception. 408 527 … … 494 613 needs its own exception context. 495 614 496 The exception context should be retrieved by calling the function615 The current exception context should be retrieved by calling the function 497 616 \snake{this_exception_context}. 498 617 For sequential execution, this function is defined as … … 519 638 The first step of a termination raise is to copy the exception into memory 520 639 managed by the exception system. Currently, the system uses @malloc@, rather 521 than reserved memory or the stack top. The exception handling mechanismmanages640 than reserved memory or the stack top. The EHM manages 522 641 memory for the exception as well as memory for libunwind and the system's own 523 642 per-exception storage. … … 554 673 \newsavebox{\stackBox} 555 674 \begin{lrbox}{\codeBox} 556 \begin{ lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]675 \begin{cfa} 557 676 unsigned num_exceptions = 0; 558 677 void throws() { … … 573 692 throws(); 574 693 } 575 \end{ lstlisting}694 \end{cfa} 576 695 \end{lrbox} 577 696 578 697 \begin{lrbox}{\stackBox} 579 698 \begin{lstlisting} 580 | try-finally581 | try -catch (Example)699 | finally block (Example) 700 | try block 582 701 throws() 583 | try-finally584 | try -catch (Example)702 | finally block (Example) 703 | try block 585 704 throws() 586 | try-finally587 | try -catch (Example)705 | finally block (Example) 706 | try block 588 707 throws() 589 708 main() … … 598 717 \label{f:MultipleExceptions} 599 718 \end{figure} 600 \todo*{Work on multiple exceptions code sample.}601 719 602 720 All exceptions are stored in nodes, which are then linked together in lists … … 618 736 \subsection{Try Statements and Catch Clauses} 619 737 The try statement with termination handlers is complex because it must 620 compensate for the C code-generation versus 738 compensate for the C code-generation versus proper 621 739 assembly-code generated from \CFA. Libunwind 622 740 requires an LSDA and personality function for control to unwind across a 623 741 function. The LSDA in particular is hard to mimic in generated C code. 624 742 625 The workaround is a function called @__cfaehm_try_terminate@ in the standard626 library. The contents of a try block and the termination handlers are converted 627 into functions. These are then passed to the try terminate function and it 628 calls them.743 The workaround is a function called \snake{__cfaehm_try_terminate} in the 744 standard \CFA library. The contents of a try block and the termination 745 handlers are converted into nested functions. These are then passed to the 746 try terminate function and it calls them, appropriately. 629 747 Because this function is known and fixed (and not an arbitrary function that 630 happens to contain a try statement), theLSDA can be generated ahead748 happens to contain a try statement), its LSDA can be generated ahead 631 749 of time. 632 750 633 Both the LSDA and the personality function are set ahead of time using 751 Both the LSDA and the personality function for \snake{__cfaehm_try_terminate} 752 are set ahead of time using 634 753 embedded assembly. This assembly code is handcrafted using C @asm@ statements 635 754 and contains 636 enough information for a single try statement the function repersents.755 enough information for the single try statement the function represents. 637 756 638 757 The three functions passed to try terminate are: … … 646 765 decides if a catch clause matches the termination exception. It is constructed 647 766 from the conditional part of each handler and runs each check, top to bottom, 648 in turn, first checking to see if the exception type matches and then if the 649 condition is true. It takes a pointer to the exception and returns 0 if the 767 in turn, to see if the exception matches this handler. 768 The match is performed in two steps, first a virtual cast is used to check 769 if the raised exception is an instance of the declared exception type or 770 one of its descendant types, and then the condition is evaluated, if 771 present. 772 The match function takes a pointer to the exception and returns 0 if the 650 773 exception is not handled here. Otherwise the return value is the id of the 651 774 handler that matches the exception. … … 660 783 All three functions are created with GCC nested functions. GCC nested functions 661 784 can be used to create closures, 662 in other words functions that can refer to the state of other 663 functions on the stack. This approach allows the functions to refer to all the 785 in other words, 786 functions that can refer to variables in their lexical scope even 787 those variables are part of a different function. 788 This approach allows the functions to refer to all the 664 789 variables in scope for the function containing the @try@ statement. These 665 790 nested functions and all other functions besides @__cfaehm_try_terminate@ in … … 669 794 670 795 \autoref{f:TerminationTransformation} shows the pattern used to transform 671 a \CFA try statement with catch clauses into the approprate C functions. 672 \todo{Explain the Termination Transformation figure.} 796 a \CFA try statement with catch clauses into the appropriate C functions. 673 797 674 798 \begin{figure} … … 728 852 \caption{Termination Transformation} 729 853 \label{f:TerminationTransformation} 730 \todo*{Improve (compress?) Termination Transformations.}731 854 \end{figure} 732 855 … … 738 861 Instead of storing the data in a special area using assembly, 739 862 there is just a linked list of possible handlers for each stack, 740 with each node on the list rep erenting a try statement on the stack.863 with each node on the list representing a try statement on the stack. 741 864 742 865 The head of the list is stored in the exception context. … … 744 867 to the head of the list. 745 868 Instead of traversing the stack, resumption handling traverses the list. 746 At each node, the EHM checks to see if the try statement the node rep ersents869 At each node, the EHM checks to see if the try statement the node represents 747 870 can handle the exception. If it can, then the exception is handled and 748 871 the operation finishes, otherwise the search continues to the next node. 749 872 If the search reaches the end of the list without finding a try statement 750 that can handle the exception, the default handler is executed and the 751 operation finishes. 873 with a handler clause 874 that can handle the exception, the default handler is executed. 875 If the default handler returns, control continues after the raise statement. 752 876 753 877 Each node has a handler function that does most of the work. 754 878 The handler function is passed the raised exception and returns true 755 879 if the exception is handled and false otherwise. 756 757 880 The handler function checks each of its internal handlers in order, 758 881 top-to-bottom, until it funds a match. If a match is found that handler is … … 760 883 If no match is found the function returns false. 761 884 The match is performed in two steps, first a virtual cast is used to see 762 if the thrown exception is an instance of the declared exception or one of 763 its descendant type, then check to see if passes the custom predicate if one 764 is defined. This ordering gives the type guarantee used in the predicate. 885 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 887 if one is defined. 888 % You need to make sure the type is correct before running the predicate 889 % because the predicate can depend on that. 765 890 766 891 \autoref{f:ResumptionTransformation} shows the pattern used to transform 767 a \CFA try statement with catch clauses into the approprate C functions.768 \todo{Explain the Resumption Transformation figure.} 892 a \CFA try statement with catchResume clauses into the appropriate 893 C functions. 769 894 770 895 \begin{figure} … … 807 932 \caption{Resumption Transformation} 808 933 \label{f:ResumptionTransformation} 809 \todo*{Improve (compress?) Resumption Transformations.}810 934 \end{figure} 811 935 … … 814 938 (see \vpageref{s:ResumptionMarking}), which ignores parts of 815 939 the stack 816 already examined, is accomplished by updating the front of the list as the 817 search continues. Before the handler at a node is called, the head of the list 940 already examined, and is accomplished by updating the front of the list as 941 the search continues. 942 Before the handler is called at a matching node, the head of the list 818 943 is updated to the next node of the current node. After the search is complete, 819 944 successful or not, the head of the list is reset. … … 822 947 been checked are not on the list while a handler is run. If a resumption is 823 948 thrown during the handling of another resumption, the active handlers and all 824 the other handler checked up to this point are not checked again.949 the other handlers checked up to this point are not checked again. 825 950 % No paragraph? 826 951 This structure also supports new handlers added while the resumption is being … … 830 955 831 956 \begin{figure} 957 \centering 832 958 \input{resumption-marking} 833 959 \caption{Resumption Marking} 834 960 \label{f:ResumptionMarking} 835 \todo*{Label Resumption Marking to aid clarity.}836 961 \end{figure} 837 962 … … 851 976 \section{Finally} 852 977 % Uses destructors and GCC nested functions. 853 A finally clause is placed into a GCC nested-function with a unique name, 854 and no arguments or return values. 855 This nested function is then set as the cleanup 856 function of an empty object that is declared at the beginning of a block placed 857 around the context of the associated @try@ statement. 858 859 The rest is handled by GCC. The try block and all handlers are inside this 860 block. At completion, control exits the block and the empty object is cleaned 978 979 %\autoref{code:cleanup} 980 A finally clause is handled by converting it into a once-off destructor. 981 The code inside the clause is placed into GCC nested-function 982 with a unique name, and no arguments or return values. 983 This nested function is 984 then set as the cleanup function of an empty object that is declared at the 985 beginning of a block placed around the context of the associated try 986 statement (see \autoref{f:FinallyTransformation}). 987 988 \begin{figure} 989 \begin{cfa} 990 try { 991 // TRY BLOCK 992 } finally { 993 // FINALLY BLOCK 994 } 995 \end{cfa} 996 997 \transformline 998 999 \begin{cfa} 1000 { 1001 void finally(void *__hook){ 1002 // FINALLY BLOCK 1003 } 1004 __attribute__ ((cleanup(finally))) 1005 struct __cfaehm_cleanup_hook __finally_hook; 1006 { 1007 // TRY BLOCK 1008 } 1009 } 1010 \end{cfa} 1011 1012 \caption{Finally Transformation} 1013 \label{f:FinallyTransformation} 1014 \end{figure} 1015 1016 The rest is handled by GCC. 1017 The TRY BLOCK 1018 contains the try block itself as well as all code generated for handlers. 1019 Once that code has completed, 1020 control exits the block and the empty object is cleaned 861 1021 up, which runs the function that contains the finally code. 862 1022 … … 887 1047 passed to the forced-unwind function. The general pattern of all three stop 888 1048 functions is the same: continue unwinding until the end of stack and 889 then p reform the appropriate transfer.1049 then perform the appropriate transfer. 890 1050 891 1051 For main stack cancellation, the transfer is just a program abort.
Note:
See TracChangeset
for help on using the changeset viewer.