Changeset ef0b456 for doc/theses

Ignore:
Timestamp:
Feb 4, 2021, 10:03:29 PM (22 months ago)
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5ce9bea
Parents:
c292244 (diff), 9af0fe2d (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
doc/theses/andrew_beach_MMath
Files:
9 edited

Unmodified
Removed
• doc/theses/andrew_beach_MMath/existing.tex

 rc292244 \chapter{\texorpdfstring{\CFA Existing Features}{Cforall Existing Features}} \chapter{\CFA Existing Features} \CFA (C-for-all)~\cite{Cforall} is an open-source project extending ISO C with obvious to the reader. \section{\texorpdfstring{Overloading and \lstinline|extern|}{Overloading and extern}} \section{Overloading and \lstinline{extern}} \CFA has extensive overloading, allowing multiple definitions of the same name to be defined.~\cite{Moss18} \section{Reference Type} \CFA adds a rebindable reference type to C, but more expressive than the \CC \CFA adds a rebindable reference type to C, but more expressive than the \Cpp reference.  Multi-level references are allowed and act like auto-dereferenced pointers using the ampersand (@&@) instead of the pointer asterisk (@*@). \CFA Both constructors and destructors are operators, which means they are just functions with special operator names rather than type names in \CC. The functions with special operator names rather than type names in \Cpp. The special operator names may be used to call the functions explicitly (not allowed in \CC for constructors). allowed in \Cpp for constructors). In general, operator names in \CFA are constructed by bracketing an operator matching overloaded destructor @void ^?{}(T &);@ is called.  Without explicit definition, \CFA creates a default and copy constructor, destructor and assignment (like \CC). It is possible to define constructors/destructors for assignment (like \Cpp). It is possible to define constructors/destructors for basic and existing types. \CFA uses parametric polymorphism to create functions and types that are defined over multiple types. \CFA polymorphic declarations serve the same role as \CC templates or Java generics. The parametric'' means the polymorphism is as \Cpp templates or Java generics. The parametric'' means the polymorphism is accomplished by passing argument operations to associate \emph{parameters} at the call site, and these parameters are used in the function to differentiate Note, a function named @do_once@ is not required in the scope of @do_twice@ to compile it, unlike \CC template expansion. Furthermore, call-site inferencing compile it, unlike \Cpp template expansion. Furthermore, call-site inferencing allows local replacement of the most specific parametric functions needs for a call. } \end{cfa} The generic type @node(T)@ is an example of a polymorphic-type usage.  Like \CC The generic type @node(T)@ is an example of a polymorphic-type usage.  Like \Cpp templates usage, a polymorphic-type usage must specify a type parameter.
• doc/theses/andrew_beach_MMath/features.tex

 rc292244 \section{Virtuals} Virtual types and casts are not part of the exception system nor are they required for an exception system. But an object-oriented style hierarchy is a great way of organizing exceptions so a minimal virtual system has been added to \CFA. The pattern of a simple hierarchy was borrowed from object-oriented programming was chosen for several reasons. The first is that it allows new exceptions to be added in user code and in libraries independently of each other. Another is it allows for different levels of exception grouping (all exceptions, all IO exceptions or a particular IO exception). Also it also provides a simple way of passing data back and forth across the throw. Virtual types and casts are not required for a basic exception-system but are useful for advanced exception features. However, \CFA is not object-oriented so there is no obvious concept of virtuals.  Hence, to create advanced exception features for this work, I needed to designed and implemented a virtual-like there is no obvious concept of virtuals. Hence, to create advanced exception features for this work, I needed to design and implement a virtual-like system for \CFA. % NOTE: Maybe we should but less of the rational here. Object-oriented languages often organized exceptions into a simple hierarchy, \eg Java. \end{center} The hierarchy provides the ability to handle an exception at different degrees of specificity (left to right).  Hence, it is possible to catch a more general of specificity (left to right). Hence, it is possible to catch a more general exception-type in higher-level code where the implementation details are unknown, which reduces tight coupling to the lower-level implementation. While much of the virtual infrastructure is created, it is currently only used internally for exception handling. The only user-level feature is the virtual cast, which is the same as the \CC \lstinline[language=C++]|dynamic_cast|. cast, which is the same as the \Cpp \lstinline[language=C++]|dynamic_cast|. \label{p:VirtualCast} \begin{cfa} (virtual TYPE)EXPRESSION \end{cfa} Note, the syntax and semantics matches a C-cast, rather than the unusual \CC syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be a pointer to a virtual type. The cast dynamically checks if the @EXPRESSION@ type is the same or a subtype of @TYPE@, and if true, returns a pointer to the Note, the syntax and semantics matches a C-cast, rather than the function-like \Cpp syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be a pointer to a virtual type. The cast dynamically checks if the @EXPRESSION@ type is the same or a subtype of @TYPE@, and if true, returns a pointer to the @EXPRESSION@ object, otherwise it returns @0p@ (null pointer). Exceptions are defined by the trait system; there are a series of traits, and if a type satisfies them, then it can be used as an exception.  The following if a type satisfies them, then it can be used as an exception. The following is the base trait all exceptions need to match. \begin{cfa} trait is_exception(exceptT &, virtualT &) { virtualT const & @get_exception_vtable@(exceptT *); virtualT const & get_exception_vtable(exceptT *); }; \end{cfa} The function takes any pointer, including the null pointer, and returns a reference to the virtual-table object. Defining this function also establishes the virtual type and a virtual-table pair to the \CFA type-resolver and promises @exceptT@ is a virtual type and a child of the base exception-type. {\color{blue} PAB: I do not understand this paragraph.} One odd thing about @get_exception_vtable@ is that it should always be a constant function, returning the same value regardless of its argument.  A pointer or reference to the virtual table instance could be used instead, however using a function has some ease of implementation advantages and allows for easier disambiguation because the virtual type name (or the address of an instance that is in scope) can be used instead of the mangled virtual table name.  Also note the use of the word promise'' in the trait description. Currently, \CFA cannot check to see if either @exceptT@ or @virtualT@ match the layout requirements. This is considered part of @get_exception_vtable@'s correct implementation. The trait is defined over two types, the exception type and the virtual table type. This should be one-to-one, each exception type has only one virtual table type and vice versa. The only assertion in the trait is @get_exception_vtable@, which takes a pointer of the exception type and returns a reference to the virtual table type instance. The function @get_exception_vtable@ is actually a constant function. Recardless of the value passed in (including the null pointer) it should return a reference to the virtual table instance for that type. The reason it is a function instead of a constant is that it make type annotations easier to write as you can use the exception type instead of the virtual table type; which usually has a mangled name. % Also \CFA's trait system handles functions better than constants and doing % it this way % I did have a note about how it is the programmer's responsibility to make % sure the function is implemented correctly. But this is true of every % similar system I know of (except Agda's I guess) so I took it out. \section{Raise} \CFA provides two kinds of exception raise: termination (see \VRef{s:Termination}) and resumption (see \VRef{s:Resumption}), which are \CFA provides two kinds of exception raise: termination \see{\VRef{s:Termination}} and resumption \see{\VRef{s:Resumption}}, which are specified with the following traits. \begin{cfa} trait is_termination_exception( exceptT &, virtualT & | is_exception(exceptT, virtualT)) { void @defaultTerminationHandler@(exceptT &); void defaultTerminationHandler(exceptT &); }; \end{cfa} trait is_resumption_exception( exceptT &, virtualT & | is_exception(exceptT, virtualT)) { void @defaultResumptionHandler@(exceptT &); void defaultResumptionHandler(exceptT &); }; \end{cfa} Finally there are three convenience macros for referring to the these traits: @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@.  Each takes the virtual type's name, and for polymorphic types only, the parenthesized list of polymorphic arguments. These macros do the name mangling to get the virtual-table name and provide the arguments to both sides {\color{blue}(PAB: What's a side''?)} @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. All three traits are hard to use while naming the virtual table as it has an internal mangled name. These macros take the exception name as their first argument and do the mangling. They all take a second argument for polymorphic types which is the parenthesized list of polymorphic arguments. These arguments are passed to both the exception type and the virtual table type as the arguments do have to match. For example consider a function that is polymorphic over types that have a defined arithmetic exception: \begin{cfa} forall(Num | IS_EXCEPTION(Arithmetic, (Num))) void some_math_function(Num & left, Num & right); \end{cfa} \subsection{Termination} throw EXPRESSION; \end{cfa} The expression must return a termination-exception reference, where the termination exception has a type with a @void defaultTerminationHandler(T &)@ (default handler) defined. The handler is found at the call site using \CFA's trait system and passed into the exception system along with the exception itself. At runtime, a representation of the exception type and an instance of the exception type is copied into managed memory (heap) to ensure it remains in The expression must return a reference to a termination exception, where the termination exception is any type that satifies @is_termination_exception@ at the call site. Through \CFA's trait system the functions in the traits are passed into the throw code. A new @defaultTerminationHandler@ can be defined in any scope to change the throw's behavior (see below). At runtime, the exception returned by the expression is copied into managed memory (heap) to ensure it remains in scope during unwinding. It is the user's responsibility to ensure the original exception object at the throw is freed when it goes out of scope. Being try { GUARDED_BLOCK } @catch (EXCEPTION_TYPE$$$_1$$$ * NAME)@ { // termination handler 1 } catch (EXCEPTION_TYPE$$$_1$$$ * NAME$$$_1$$$) { // termination handler 1 HANDLER_BLOCK$$$_1$$$ } @catch (EXCEPTION_TYPE$$$_2$$$ * NAME)@ { // termination handler 2 } catch (EXCEPTION_TYPE$$$_2$$$ * NAME$$$_2$$$) { // termination handler 2 HANDLER_BLOCK$$$_2$$$ } Exception matching checks the representation of the thrown exception-type is the same or a descendant type of the exception types in the handler clauses. If there is a match, a pointer to the exception object created at the throw is bound to @NAME@ and the statements in the associated @HANDLER_BLOCK@ are executed. If control reaches the end of the handler, the exception is freed, and control continues after the try statement. it is the same of a descendent of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ is bound to a pointer to the exception and the statements in @HANDLER_BLOCK@$_i$ are executed. If control reaches the end of the handler, the exception is freed and control continues after the try statement. The default handler visible at the throw statement is used if no matching termination handler is found after the entire stack is searched. At that point, the default handler is called with a reference to the exception object generated at the throw. If the default handler returns, the system default action is executed, which often terminates the program. This feature allows generated at the throw. If the default handler returns, control continues from after the throw statement. This feature allows each exception type to define its own action, such as printing an informative error message, when an exception is not handled in the program. However the default handler for all exception types triggers a cancellation using the exception. \subsection{Resumption} Resumption raise, called resume'', is as old as termination raise~\cite{Goodenough75} but is less popular. In many ways, resumption is simpler and easier to understand, as it is simply a dynamic call (as in Lisp). The semantics of resumption is: search the stack for a matching handler, simpler and easier to understand, as it is simply a dynamic call. The semantics of resumption is: search the stack for a matching handler, execute the handler, and continue execution after the resume. Notice, the stack cannot be unwound because execution returns to the raise point. Resumption is \end{cfa} The semantics of the @throwResume@ statement are like the @throw@, but the expression has a type with a @void defaultResumptionHandler(T &)@ (default handler) defined, where the handler is found at the call site by the type system.  At runtime, a representation of the exception type and an instance of the exception type is \emph{not} copied because the stack is maintained during the handler search. expression has return a reference a type that satifies the trait @is_resumption_exception@. Like with termination the exception system can use these assertions while (throwing/raising/handling) the exception. At runtime, no copies are made. As the stack is not unwound the exception and any values on the stack will remain in scope while the resumption is handled. Then the exception system searches the stack starting from the resume and proceeding towards the base of the stack, from callee to caller. At each stack proceeding to the base of the stack, from callee to caller. At each stack frame, a check is made for resumption handlers defined by the @catchResume@ clauses of a @try@ statement. try { GUARDED_BLOCK } @catchResume (EXCEPTION_TYPE$$$_1$$$ * NAME)@ { // resumption handler 1 } catchResume (EXCEPTION_TYPE$$$_1$$$ * NAME$$$_1$$$) { HANDLER_BLOCK$$$_1$$$ } @catchResume (EXCEPTION_TYPE$$$_2$$$ * NAME)@ { // resumption handler 2 } catchResume (EXCEPTION_TYPE$$$_2$$$ * NAME$$$_2$$$) { HANDLER_BLOCK$$$_2$$$ } current point on the stack because new try statements may have been pushed by the handler or functions called from the handler. If there is no match back to the point of the current handler, the search skips the stack frames already searched by the first resume and continues after the try statement. The default handler always continues from default handler associated with the point where the exception is created. the point of the current handler, the search skips\label{p:searchskip} the stack frames already searched by the first resume and continues after the try statement. The default handler always continues from default handler associated with the point where the exception is created. % This might need a diagram. But it is an important part of the justification \end{verbatim} This resumption search-pattern reflect the one for termination, which matches with programmer expectations. However, it avoids the \emph{recursive resumption} problem. If parts of the stack are searched multiple times, loops This resumption search pattern reflects the one for termination, and so should come naturally to most programmers. However, it avoids the \emph{recursive resumption} problem. If parts of the stack are searched multiple times, loops can easily form resulting in infinite recursion. \begin{cfa} try { throwResume$$$_1$$$ (E &){}; } catch( E * ) { throwResume; } \end{cfa} Based on termination semantics, programmer expectation is for the re-resume to continue searching the stack frames after the try statement. However, the current try statement is still on the stack below the handler issuing the reresume (see \VRef{s:Reraise}). Hence, the try statement catches the re-raise again and does another re-raise \emph{ad infinitum}, which is confusing and difficult to debug. The \CFA resumption search-pattern skips the try statement so the reresume search continues after the try, mathcing programmer expectation. throwResume (E &){}; // first } catchResume(E *) { throwResume (E &){}; // second } \end{cfa} If this handler is ever used it will be placed on top of the stack above the try statement. If the stack was not masked than the @throwResume@ in the handler would always be caught by the handler, leading to an infinite loop. Masking avoids this problem and other more complex versions of it involving multiple handlers and exception types. Other masking stratagies could be used; such as masking the handlers that have caught an exception. This one was choosen because it creates a symmetry with termination (masked sections of the stack would be unwound with termination) and having only one pattern to learn is easier. \section{Conditional Catch} Both termination and resumption handler-clauses may perform conditional matching: Both termination and resumption handler clauses can be given an additional condition to further control which exceptions they handle: \begin{cfa} catch (EXCEPTION_TYPE * NAME ; @CONDITION@) exception matches, @CONDITION@ is executed. The condition expression may reference all names in scope at the beginning of the try block and @NAME@ introduced in the handler clause.  If the condition is true, then the handler introduced in the handler clause. If the condition is true, then the handler matches. Otherwise, the exception search continues at the next appropriate kind of handler clause in the try block. \section{Reraise} \color{red}{From Andrew: I recomend we talk about why the language doesn't have rethrows/reraises instead.} \label{s:Reraise} Within the handler block or functions called from the handler block, it is @throwResume@, respective. \begin{cfa} catch( ... ) { try { ... } catch( ... ) { ... throw; // rethrow } catchResume( ... ) { handler is generated that does a program-level abort. \section{Finally Clauses} A @finally@ clause may be placed at the end of a @try@ statement. try { GUARDED_BLOCK } ...   // any number or kind of handler clauses } finally { } ... // any number or kind of handler clauses ... finally { FINALLY_BLOCK } \end{cfa} The @FINALLY_BLOCK@ is executed when the try statement is unwound from the stack, \ie when the @GUARDED_BLOCK@ or any handler clause finishes. Hence, the finally block is always executed. The @FINALLY_BLOCK@ is executed when the try statement is removed from the stack, including when the @GUARDED_BLOCK@ or any handler clause finishes or during an unwind. The only time the block is not executed is if the program is exited before that happens. Execution of the finally block should always finish, meaning control runs off the end of the block. This requirement ensures always continues as if the finally clause is not present, \ie finally is for cleanup not changing control flow.  Because of this requirement, local control flow out of the finally block is forbidden.  The compiler precludes any @break@, @continue@, @fallthru@ or flow. Because of this requirement, local control flow out of the finally block is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or @return@ that causes control to leave the finally block. Other ways to leave the finally block, such as a long jump or termination are much harder to check, possible forwards the cancellation exception to a different stack. Cancellation is not an exception operation like termination or resumption. There is no special statement for starting a cancellation; instead the standard library function @cancel_stack@ is called passing an exception.  Unlike a library function @cancel_stack@ is called passing an exception. Unlike a raise, this exception is not used in matching only to pass information about the cause of the cancellation. \begin{description} \item[Main Stack:] The main stack is the one used by the program main at the start of execution, and is the only stack in a sequential program.  Hence, when cancellation is forwarded to the main stack, there is no other forwarding stack, so after the stack is unwound, there is a program-level abort. and is the only stack in a sequential program. Even in a concurrent program the main stack is only dependent on the environment that started the program. Hence, when the main stack is cancelled there is nowhere else in the program to notify. After the stack is unwound, there is a program-level abort. \item[Thread Stack:] A thread stack is created for a @thread@ object or object that satisfies the @is_thread@ trait.  A thread only has two points of communication that must @is_thread@ trait. A thread only has two points of communication that must happen: start and join. As the thread must be running to perform a cancellation, it must occur after start and before join, so join is a cancellation point.  After the stack is unwound, the thread halts and waits for another thread to join with it. The joining thread, checks for a cancellation, cancellation, it must occur after start and before join, so join is used for communication here. After the stack is unwound, the thread halts and waits for another thread to join with it. The joining thread checks for a cancellation, and if present, resumes exception @ThreadCancelled@. the exception is not caught. The implicit join does a program abort instead. This semantics is for safety. One difficult problem for any exception system is defining semantics when an exception is raised during an exception search: which exception has priority, the original or new exception? No matter which exception is selected, it is possible for the selected one to disrupt or destroy the context required for the other. {\color{blue} PAB: I do not understand the following sentences.} This loss of information can happen with join but as the thread destructor is always run when the stack is being unwound and one termination/cancellation is already active. Also since they are implicit they are easier to forget about. This semantics is for safety. If an unwind is triggered while another unwind is underway only one of them can proceed as they both want to consume'' the stack. Letting both try to proceed leads to very undefined behaviour. Both termination and cancellation involve unwinding and, since the default @defaultResumptionHandler@ preforms a termination that could more easily happen in an implicate join inside a destructor. So there is an error message and an abort instead. The recommended way to avoid the abort is to handle the intial resumption from the implicate join. If required you may put an explicate join inside a finally clause to disable the check and use the local @defaultResumptionHandler@ instead. \item[Coroutine Stack:] A coroutine stack is created for a @coroutine@ object or object that satisfies the @is_coroutine@ trait.  A coroutine only knows of two other coroutines, its starter and its last resumer.  The last resumer has the tightest coupling to the coroutine it activated.  Hence, cancellation of or object that satisfies the @is_coroutine@ trait. A coroutine only knows of two other coroutines, its starter and its last resumer. The last resumer has the tightest coupling to the coroutine it activated. Hence, cancellation of the active coroutine is forwarded to the last resumer after the stack is unwound, as the last resumer has the most precise knowledge about the current

• doc/theses/andrew_beach_MMath/implement.tex

 rc292244 % Goes over how all the features are implemented. The implementation work for this thesis covers two components: the virtual system and exceptions. Each component is discussed in detail. \section{Virtual System} \label{s:VirtualSystem} % Virtual table rules. Virtual tables, the pointer to them and the cast. The \CFA virtual system only has one public facing feature: virtual casts. However there is a lot of structure to support that and provide some other features for the standard library. All of this is accessed through a field inserted at the beginning of every virtual type. Currently it is called @virtual_table@ but it is not ment to be accessed by the user. This field is a pointer to the type's virtual table instance. It is assigned once during the object's construction and left alone after that. \subsection{Virtual Table Construction} For each virtual type a virtual table is constructed. This is both a new type and an instance of that type. Other instances of the type could be created but the system doesn't use them. So this section will go over the creation of the type and the instance. Creating the single instance is actually very important. The address of the table acts as the unique identifier for the virtual type. Similarly the first field in every virtual table is the parent's id; a pointer to the parent virtual table instance. The remaining fields contain the type's virtual members. First come the ones present on the parent type, in the same order as they were the parent, and then any that this type introduces. The types of the ones inherited from the parent may have a slightly modified type, in that references to the dispatched type are replaced with the current virtual type. These are always taken by pointer or reference. The structure itself is created where the virtual type is created. The name of the type is created by mangling the name of the base type. The name of the instance is also generated by name mangling. The fields are initialized automatically. While the \CFA virtual system currently has only one public feature, virtual cast \see{\VPageref{p:VirtualCast}}, substantial structure is required to support it, and provide features for exception handling and the standard library. \subsection{Virtual Table} The virtual system is accessed through a private constant field inserted at the beginning of every virtual type, called the virtual-table pointer. This field points at a type's virtual table and is assigned during the object's construction.  The address of a virtual table acts as the unique identifier for the virtual type, and the first field of a virtual table is a pointer to the parent virtual-table or @0p@.  The remaining fields are duplicated from the parent tables in this type's inheritance chain, followed by any fields this type introduces. Parent fields are duplicated so they can be changed (\CC \lstinline[language=c++]|override|), so that references to the dispatched type are replaced with the current virtual type. \PAB{Can you create a simple diagram of the layout?} % These are always taken by pointer or reference. % For each virtual type, a virtual table is constructed. This is both a new type % and an instance of that type. Other instances of the type could be created % but the system doesn't use them. So this section will go over the creation of % the type and the instance. A virtual table is created when the virtual type is created. The name of the type is created by mangling the name of the base type. The name of the instance is also generated by name mangling.  The fields are initialized automatically. The parent field is initialized by getting the type of the parent field and using that to calculate the mangled name of the parent's virtual table type. There are two special fields that are included like normal fields but have special initialization rules: the @size@ field is the type's size and is initialized with a sizeof expression, the @align@ field is the type's alignment and uses an alignof expression. The remaining fields are resolved to a name matching the field's name and type using the normal visibility and overload resolution rules of the type system. These operations are split up into several groups depending on where they take place which can vary for monomorphic and polymorphic types. The first devision is between the declarations and the definitions. Declarations, such as a function signature or a structure's name, must always be visible but may be repeated so they go in headers. Definitions, such as function bodies and a structure's layout, don't have to be visible on use but must occur exactly once and go into source files. initialized with a @sizeof@ expression, the @align@ field is the type's alignment and uses an @alignof@ expression. The remaining fields are resolved to a name matching the field's name and type using the normal visibility and overload resolution rules of the type system. These operations are split up into several groups depending on where they take place which varies for monomorphic and polymorphic types. The first devision is between the declarations and the definitions. Declarations, such as a function signature or a aggregate's name, must always be visible but may be repeated in the form of forward declarations in headers. Definitions, such as function bodies and a aggregate's layout, can be separately compiled but must occur exactly once in a source file. \begin{sloppypar} The declarations include the virtual type definition and forward declarations of the virtual table instance, constructor, message function and @get_exception_vtable@. The definition includes the storage and initialization of the virtual table instance and the bodies of the three functions. @get_exception_vtable@. The definition includes the storage and initialization of the virtual table instance and the bodies of the three functions. \end{sloppypar} Monomorphic instances put all of these two groups in one place each. Polymorphic instances also split out the core declarations and definitions from the per-instance information. The virtual table type and most of the functions are polymorphic so they are all part of the core. The virtual table instance and the @get_exception_vtable@ function. Polymorphic instances also split out the core declarations and definitions from the per-instance information. The virtual table type and most of the functions are polymorphic so they are all part of the core. The virtual table instance and the @get_exception_vtable@ function. \begin{sloppypar} Coroutines and threads need instances of @CoroutineCancelled@ and @ThreadCancelled@ respectively to use all of their functionality. When a new data type is declared with @coroutine@ or @thread@ the forward declaration for the instance is created as well. The definition of the virtual table is created at the definition of the main function. @ThreadCancelled@ respectively to use all of their functionality.  When a new data type is declared with @coroutine@ or @thread@ the forward declaration for the instance is created as well. The definition of the virtual table is created at the definition of the main function. \end{sloppypar} \subsection{Virtual Cast} Virtual casts are implemented as a function call that does the check and a old C-style cast to do the type conversion. The C-cast is just to make sure the generated code is correct so the rest of the section is about that function. The function is @__cfa__virtual_cast@ and it is implemented in the standard library. It takes a pointer to the target type's virtual table and the object pointer being cast. The function is very simple, getting the object's virtual table pointer and then checking to see if it or any of its ancestors, by using the parent pointers, are the same as the target type virtual table pointer. It does this in a simple loop. For the generated code a forward decaration of the virtual works as follows. There is a forward declaration of @__cfa__virtual_cast@ in every cfa file so it can just be used. The object argument is the expression being cast so that is just placed in the argument list. To build the target type parameter the compiler will create a mapping from concrete type-name -- so for polymorphic types the parameters are filled in -- to virtual table address. Every virtual table declaraction is added to the this table; repeats are ignored unless they have conflicting definitions. This does mean the declaractions have to be in scope, but they should usually be introduced as part of the type definition. Virtual casts are implemented as a function call that does the subtype check and a C coercion-cast to do the type conversion. % The C-cast is just to make sure the generated code is correct so the rest of % the section is about that function. The function is \begin{cfa} void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent, struct __cfa__parent_vtable const * const * child ); } \end{cfa} and it is implemented in the standard library. It takes a pointer to the target type's virtual table and the object pointer being cast. The function performs a linear search starting at the object's virtual-table and walking through the the parent pointers, checking to if it or any of its ancestors are the same as the target-type virtual table-pointer. For the generated code, a forward declaration of the virtual works as follows. There is a forward declaration of @__cfa__virtual_cast@ in every \CFA file so it can just be used. The object argument is the expression being cast so that is just placed in the argument list. To build the target type parameter, the compiler creates a mapping from concrete type-name -- so for polymorphic types the parameters are filled in -- to virtual table address. Every virtual table declaration is added to the this table; repeats are ignored unless they have conflicting definitions.  Note, these declarations do not have to be in scope, but they should usually be introduced as part of the type definition. \PAB{I do not understood all of \VRef{s:VirtualSystem}. I think you need to write more to make it clear.} \section{Exceptions} % resumption doesn't as well. Many modern languages work with an interal stack that function push and pop their local data to. Stack unwinding removes large sections of the stack, often across functions. At a very basic level this can be done with @setjmp@ \& @longjmp@ which simply move the top of the stack, discarding everything on the stack above a certain point. However this ignores all the clean-up code that should be run when certain sections of the stack are removed (for \CFA these are from destructors and finally clauses) and also requires that the point to which the stack is being unwound is known ahead of time. libunwind is used to address both of these problems. Libunwind, provided in @unwind.h@ on most platorms, is a C library that provides \CPP style stack unwinding. Its operation is divided into two phases. The search phase -- phase 1 -- is used to scan the stack and decide where the unwinding will stop, this allows for a dynamic target. The clean-up phase -- phase 2 -- does the actual unwinding and also runs any clean-up code as it goes. To use the libunwind each function must have a personality function and an LSDA (Language Specific Data Area). Libunwind actually does very little, it simply moves down the stack from function to function. Most of the actions are implemented by the personality function which libunwind calls on every function. Since this is shared across many functions or even every function in a language it will need a bit more information. This is provided by the LSDA which has the unique information for each function. Theoretically the LSDA can contain anything but conventionally it is a table with entries reperenting areas of the function and what has to be done there during unwinding. These areas are described in terms of where the instruction pointer is. If the current value of the instruction pointer is between two values reperenting the beginning and end of a region then execution is currently being executed. These are used to mark out try blocks and the scopes of objects with destructors to run. GCC will generate an LSDA and attach its personality function with the @-fexceptions@ flag. However this only handles the cleanup attribute. This attribute is used on a variable and specifies a function that should be run when the variable goes out of scope. The function is passed a pointer to the object as well so it can be used to mimic destructors. It however cannot be used to mimic try statements. \subsection{Implementing Personality Functions} Personality functions have a complex interface specified by libunwind. This section will cover some of the important parts of that interface. \begin{lstlisting} typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( int version, _Unwind_Action action, _Unwind_Exception_Class exception_class, _Unwind_Exception * exception, struct _Unwind_Context * context); % Many modern languages work with an interal stack that function push and pop % their local data to. Stack unwinding removes large sections of the stack, % often across functions. Stack unwinding is the process of removing stack frames (activations) from the stack. On function entry and return, unwinding is handled directly by the code embedded in the function. Usually, the stack-frame size is known statically based on parameter and local variable declarations.  For dynamically-sized local variables, a runtime computation is necessary to know the frame size. Finally, a function's frame-size may change during execution as local variables (static or dynamic sized) go in and out of scope. Allocating/deallocating stack space is usually an $O(1)$ operation achieved by bumping the hardware stack-pointer up or down as needed. Unwinding across multiple stack frames is more complex because individual stack management code associated with each frame is bypassed. That is, the location of a function's frame-management code is largely unknown and dispersed throughout the function, hence the current frame size managed by that code is also unknown. Hence, code unwinding across frames does not have direct knowledge about what is on the stack, and hence, how much of the stack needs to be removed. % At a very basic level this can be done with @setjmp@ \& @longjmp@ which simply % move the top of the stack, discarding everything on the stack above a certain % point. However this ignores all the cleanup code that should be run when % certain sections of the stack are removed (for \CFA these are from destructors % and finally clauses) and also requires that the point to which the stack is % being unwound is known ahead of time. libunwind is used to address both of % these problems. The traditional unwinding mechanism for C is implemented by saving a snap-shot of a function's state with @setjmp@ and restoring that snap-shot with @longjmp@. This approach bypasses the need to know stack details by simply reseting to a snap-shot of an arbitrary but existing function frame on the stack. It is up to the programmer to ensure the snap-shot is valid when it is reset, making this unwinding approach fragile with potential errors that are difficult to debug because the stack becomes corrupted. However, many languages define cleanup actions that must be taken when objects are deallocated from the stack or blocks end, such as running a variable's destructor or a @try@ statement's @finally@ clause. Handling these mechanisms requires walking the stack and checking each stack frame for these potential actions. For exceptions, it must be possible to walk the stack frames in search of @try@ statements to match and execute a handler. For termination exceptions, it must also be possible to unwind all stack frames from the throw to the matching catch, and each of these frames must be checked for cleanup actions. Stack walking is where most of the complexity and expense of exception handling appears. One of the most popular tools for stack management is libunwind, a low-level library that provides tools for stack walking, handler execution, and unwinding. What follows is an overview of all the relevant features of libunwind needed for this work, and how \CFA uses them to implement exception handling. \subsection{libunwind Usage} Libunwind, accessed through @unwind.h@ on most platforms, is a C library that provides \CC-style stack-unwinding. Its operation is divided into two phases: search and cleanup. The dynamic target search -- phase 1 -- is used to scan the stack and decide where unwinding should stop (but no unwinding occurs). The cleanup -- phase 2 -- does the unwinding and also runs any cleanup code. To use libunwind, each function must have a personality function and a Language Specific Data Area (LSDA).  The LSDA has the unique information for each function to tell the personality function where a function is executing, its current stack frame, and what handlers should be checked.  Theoretically, the LSDA can contain any information but conventionally it is a table with entries representing regions of the function and what has to be done there during unwinding. These regions are bracketed by the instruction pointer. If the instruction pointer is within a region's start/end, then execution is currently executing in that region. Regions are used to mark out the scopes of objects with destructors and try blocks. % Libunwind actually does very little, it simply moves down the stack from % function to function. Most of the actions are implemented by the personality % function which libunwind calls on every function. Since this is shared across % many functions or even every function in a language it will need a bit more % information. The GCC compilation flag @-fexceptions@ causes the generation of an LSDA and attaches its personality function. \PAB{to what is it attached?}  However, this flag only handles the cleanup attribute \begin{cfa} void clean_up( int * var ) { ... } int avar __attribute__(( __cleanup(clean_up) )); \end{cfa} which is used on a variable and specifies a function, \eg @clean_up@, run when the variable goes out of scope. The function is passed a pointer to the object so it can be used to mimic destructors. However, this feature cannot be used to mimic @try@ statements. \subsection{Personality Functions} Personality functions have a complex interface specified by libunwind.  This section covers some of the important parts of the interface. A personality function performs four tasks, although not all have to be present. \begin{lstlisting}[language=C,{moredelim=**[is][\color{red}]{@}{@}}] typedef _Unwind_Reason_Code (*@_Unwind_Personality_Fn@) ( _Unwind_Action @action@, _Unwind_Exception_Class @exception_class@, _Unwind_Exception * @exception@, struct _Unwind_Context * @context@ ); \end{lstlisting} The return value, the reason code, is an enumeration of possible messages The @action@ argument is a bitmask of possible actions: \begin{enumerate} \item @_UA_SEARCH_PHASE@ specifies a search phase and tells the personality function to check for handlers.  If there is a handler in a stack frame, as defined by the language, the personality function returns @_URC_HANDLER_FOUND@; otherwise it return @_URC_CONTINUE_UNWIND@. \item @_UA_CLEANUP_PHASE@ specifies a cleanup phase, where the entire frame is unwound and all cleanup code is run. The personality function does whatever cleanup the language defines (such as running destructors/finalizers) and then generally returns @_URC_CONTINUE_UNWIND@. \item \begin{sloppypar} @_UA_HANDLER_FRAME@ specifies a cleanup phase on a function frame that found a handler. The personality function must prepare to return to normal code execution and return @_URC_INSTALL_CONTEXT@. \end{sloppypar} \item @_UA_FORCE_UNWIND@ specifies a forced unwind call. Forced unwind only performs the cleanup phase and uses a different means to decide when to stop \see{\VRef{s:ForcedUnwind}}. \end{enumerate} The @exception_class@ argument is a copy of the \lstinline[language=C]|exception|'s @exception_class@ field. The \lstinline[language=C]|exception| argument is a pointer to the user provided storage object. It has two public fields, the exception class, which is actually just a number, identifying the exception handling mechanism that created it, and the cleanup function. The cleanup function is called if required by the exception. The @context@ argument is a pointer to an opaque type passed to helper functions called inside the personality function. The return value, @_Unwind_Reason_Code@, is an enumeration of possible messages that can be passed several places in libunwind. It includes a number of messages for special cases (some of which should never be used by the personality function should always return @_URC_CONTINUE_UNWIND@. The @version@ argument is the verson of the implementation that is calling the personality function. At this point it appears to always be 1 and it will likely stay that way until a new version of the API is updated. The @action@ argument is set of flags that tell the personality function when it is being called and what it must do on this invocation. The flags are as follows: \begin{itemize} \item@_UA_SEARCH_PHASE@: This flag is set whenever the personality function is called during the search phase. The personality function should decide if unwinding will stop in this function or not. If it does then the personality function should return @_URC_HANDLER_FOUND@. \item@_UA_CLEANUP_PHASE@: This flag is set whenever the personality function is called during the cleanup phase. If no other flags are set this means the entire frame will be unwound and all cleanup code should be run. \item@_UA_HANDLER_FRAME@: This flag is set during the cleanup phase on the function frame that found the handler. The personality function must prepare to return to normal code execution and return @_URC_INSTALL_CONTEXT@. \item@_UA_FORCE_UNWIND@: This flag is set if the personality function is called through a forced unwind call. Forced unwind only performs the cleanup phase and uses a different means to decide when to stop. See its section below. \end{itemize} The @exception_class@ argument is a copy of the @exception@'s @exception_class@ field. The @exception@ argument is a pointer to the user provided storage object. It has two public fields, the exception class which is actually just a number that identifies the exception handling mechanism that created it and the other is the clean-up function. The clean-up function is called if the exception needs to The @context@ argument is a pointer to an opaque type. This is passed to the many helper functions that can be called inside the personality function. \subsection{Raise Exception} This could be considered the central function of libunwind. It preforms the two staged unwinding the library is built around and most of the rest of the interface of libunwind is here to support it. It's signature is as follows: \begin{lstlisting} Raising an exception is the central function of libunwind and it performs a two-staged unwinding. \begin{cfa} _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *); \end{cfa} First, the function begins the search phase, calling the personality function of the most recent stack frame. It continues to call personality functions traversing the stack from newest to oldest until a function finds a handler or the end of the stack is reached. In the latter case, raise exception returns @_URC_END_OF_STACK@. Second, when a handler is matched, raise exception continues onto the cleanup phase. Once again, it calls the personality functions of each stack frame from newest to oldest. This pass stops at the stack frame containing the matching handler. If that personality function has not install a handler, it is an error. If an error is encountered, raise exception returns either @_URC_FATAL_PHASE1_ERROR@ or @_URC_FATAL_PHASE2_ERROR@ depending on when the error occurred. \subsection{Forced Unwind} \label{s:ForcedUnwind} Forced Unwind is the other central function in libunwind. \begin{cfa} _Unwind_Reason_Code _Unwind_ForcedUnwind( _Unwind_Exception *, _Unwind_Stop_Fn, void *); \end{cfa} It also unwinds the stack but it does not use the search phase. Instead another function, the stop function, is used to stop searching.  The exception is the same as the one passed to raise exception. The extra arguments are the stop function and the stop parameter. The stop function has a similar interface as a personality function, except it is also passed the stop parameter. \begin{lstlisting}[language=C,{moredelim=**[is][\color{red}]{@}{@}}] typedef _Unwind_Reason_Code (*@_Unwind_Stop_Fn@)( _Unwind_Action @action@, _Unwind_Exception_Class @exception_class@, _Unwind_Exception * @exception@, struct _Unwind_Context * @context@, void * @stop_parameter@); \end{lstlisting} When called the function begins the search phase, calling the personality function of the most recent stack frame. It will continue to call personality functions traversing the stack new-to-old until a function finds a handler or the end of the stack is reached. In the latter case raise exception will return with @_URC_END_OF_STACK@. Once a handler has been found raise exception continues onto the the cleanup phase. Once again it will call the personality functins of each stack frame from newest to oldest. This pass will stop at the stack frame that found the handler last time, if that personality function does not install the handler it is an error. If an error is encountered raise exception will return either @_URC_FATAL_PHASE1_ERROR@ or @_URC_FATAL_PHASE2_ERROR@ depending on when the error occured. \subsection{Forced Unwind} This is the second big function in libunwind. It also unwinds a stack but it does not use the search phase. Instead another function, the stop function, is used to decide when to stop. \begin{lstlisting} _Unwind_Reason_Code _Unwind_ForcedUnwind( _Unwind_Exception *, _Unwind_Stop_Fn, void *); \end{lstlisting} The exception is the same as the one passed to raise exception. The extra arguments are the stop function and the stop parameter. The stop function has a similar interface as a personality function, except it is also passed the stop parameter. \begin{lstlisting} typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)( int version, _Unwind_Action action, _Unwind_Exception_Class exception_class, _Unwind_Exception * exception, struct _Unwind_Context * context, void * stop_parameter); \end{lstlisting} The stop function is called at every stack frame before the personality function is called and then once more once after all frames of the stack have been unwound. Each time it is called the stop function should return @_URC_NO_REASON@ or transfer control directly to other code outside of libunwind. The framework does not provide any assistance here. Its arguments are the same as the paired personality function. The actions @_UA_CLEANUP_PHASE@ and @_UA_FORCE_UNWIND@ are always set when it is called. By the official standard that is all but both GCC and Clang add an extra action on the last call at the end of the stack: @_UA_END_OF_STACK@. function is called and then once more after all frames of the stack are unwound. Each time it is called, the stop function should return @_URC_NO_REASON@ or transfer control directly to other code outside of libunwind. The framework does not provide any assistance here. \begin{sloppypar} Its arguments are the same as the paired personality function.  The actions @_UA_CLEANUP_PHASE@ and @_UA_FORCE_UNWIND@ are always set when it is called. Beyond the libunwind standard, both GCC and Clang add an extra action on the last call at the end of the stack: @_UA_END_OF_STACK@. \end{sloppypar} \section{Exception Context} % Should I have another independent section? % There are only two things in it, top_resume and current_exception. How it is % stored changes depending on wheither or not the thread-library is linked. The exception context is a piece of global storage used to maintain data across different exception operations and to communicate between different components. Each stack has its own exception context. In a purely sequental program, using only core Cforall, there is only one stack and the context is global. However if the library @libcfathread@ is linked then there can be multiple stacks so they will each need their own. To handle this code always gets the exception context from the function @this_exception_context@. The main exception handling code is in @libcfa@ and that library also defines the function as a weak symbol so it acts as a default. Meanwhile in @libcfathread@ the function is defined as a strong symbol that replaces it when the libraries are linked together. The version of the function defined in @libcfa@ is very simple. It returns a pointer to a global static variable. With only one stack this global instance is associated with the only stack. The version of the function defined in @libcfathread@ has to handle more as there are multiple stacks. The exception context is included as part of the per-stack data stored as part of coroutines. In the cold data section, stored at the base of each stack, is the exception context for that stack. The @this_exception_context@ uses the concurrency library to get the current coroutine and through it the cold data section and the exception context. % stored changes depending on whether or not the thread-library is linked. The exception context is global storage used to maintain data across different exception operations and to communicate among different components. Each stack must have its own exception context. In a sequential \CFA program, there is only one stack with a single global exception-context. However, when the library @libcfathread@ is linked, there are multiple stacks where each needs its own exception context. General access to the exception context is provided by function @this_exception_context@. For sequential execution, this function is defined as a weak symbol in the \CFA system-library, @libcfa@. When a \CFA program is concurrent, it links with @libcfathread@, where this function is defined with a strong symbol replacing the sequential version. % The version of the function defined in @libcfa@ is very simple. It returns a % pointer to a global static variable. With only one stack this global instance % is associated with the only stack. For coroutines, @this_exception_context@ accesses the exception context stored at the base of the stack. For threads, @this_exception_context@ uses the concurrency library to access the current stack of the thread or coroutine being executed by the thread, and then accesses the exception context stored at the base of this stack. \section{Termination} % catches. Talk about GCC nested functions. Termination exceptions use libunwind quite heavily because it matches the intended use from \CPP exceptions very closely. The main complication is that since the \CFA compiler works by translating to C code it cannot generate the assembly to form the LSDA for try blocks or destructors. Termination exceptions use libunwind heavily because it matches the intended use from \CC exceptions closely. The main complication for \CFA is that the compiler generates C code, making it very difficult to generate the assembly to form the LSDA for try blocks or destructors. \subsection{Memory Management} The first step of termination is to copy the exception into memory managed by the exception system. Currently the system just uses malloc, without reserved memory or and small allocation" optimizations. The exception handling mechanism manages memory for the exception as well as memory for libunwind and the system's own per-exception storage. Exceptions are stored in variable sized block. The first component is a fixed sized data structure that contains the information for libunwind and the exception system. The second component is a blob of memory that is big enough to store the exception. Macros with pointer arthritic and type cast are used to move between the components or go from the embedded The first step of a termination raise is to copy the exception into memory managed by the exception system. Currently, the system uses @malloc@, rather than reserved memory or the stack top. The exception handling mechanism manages memory for the exception as well as memory for libunwind and the system's own per-exception storage. Exceptions are stored in variable-sized blocks. \PAB{Show a memory layout figure.} The first component is a fixed sized data structure that contains the information for libunwind and the exception system. The second component is an area of memory big enough to store the exception. Macros with pointer arthritic and type cast are used to move between the components or go from the embedded @_Unwind_Exception@ to the entire node. All of these nodes are strung together in a linked list. One linked list per stack, with the head stored in the exception context. Within each linked list the most recently thrown exception is at the head and the older exceptions are further down the list. This list format allows exceptions to be thrown while a different exception is being handled. Only the exception at the head of the list is currently being handled, the other will wait for the exceptions before them to be removed. The virtual members in the exception's virtual table. The size of the exception, the copy function and the free function are all in the virtual table so they are decided per-exception type. The size and copy function are used right away when the exception is copied in to managed memory. After the exception is handled the free function is used to clean up the exception and then the entire node is passed to free. \subsection{Try Statements \& Catch Clauses} The try statements with termination handlers have a pretty complex conversion to compensate for the lack of assembly generation. Libunwind requires an LSDA (Language Specific Data Area) and personality function for a function to unwind across it. The LSDA in particular is hard to generate at the level of C which is what the \CFA compiler outputs so a work-around is used. This work around is a function called @__cfaehm_try_terminate@ in the standard library. The contents of a try block and the termination handlers are converted into functions. These are then passed to the try terminate function and it calls them. This puts the try statements in their own functions so that no function has to deal with both termination handlers and destructors. This function has some custom embedded assembly that defines its personality function and LSDA. This is hand coded in C which is why there is only one version of it, the compiler has no capability to generate it. The personality function is structured so that it may be expanded, but really it only handles this one function. Notably it does not handle any destructors so the function is constructed so that it does need to run it. All of these nodes are linked together in a list, one list per stack, with the list head stored in the exception context. Within each linked list, the most recently thrown exception is at the head followed by older thrown exceptions. This format allows exceptions to be thrown, while a different exception is being handled. The exception at the head of the list is currently being handled, while other exceptions wait for the exceptions before them to be removed. The virtual members in the exception's virtual table provide the size of the exception, the copy function, and the free function, so they are specific to an exception type. The size and copy function are used immediately to copy an exception into managed memory. After the exception is handled the free function is used to clean up the exception and then the entire node is passed to free. \subsection{Try Statements and Catch Clauses} The try statement with termination handlers is complex because it must compensate for the lack of assembly-code generated from \CFA. Libunwind requires an LSDA and personality function for control to unwind across a function. The LSDA in particular is hard to mimic in generated C code. The workaround is a function called @__cfaehm_try_terminate@ in the standard library. The contents of a try block and the termination handlers are converted into functions. These are then passed to the try terminate function and it calls them. This approach puts a try statement in its own functions so that no function has to deal with both termination handlers and destructors. \PAB{I do not understand the previous sentence.} This function has some custom embedded assembly that defines \emph{its} personality function and LSDA. The assembly is created with handcrafted C @asm@ statements, which is why there is only one version of it. The personality function is structured so that it can be expanded, but currently it only handles this one function.  Notably, it does not handle any destructors so the function is constructed so that it does need to run it. \PAB{I do not understand the previous sentence.} The three functions passed to try terminate are: \begin{itemize} \item The try function: This function is the try block, all the code inside the try block is placed inside the try function. It takes no parameters and has no return value. This function is called during regular execution to run the try block. \item The match function: This function decides if this try statement should handle any given termination exception. It takes a pointer to the exception and returns 0 if the exception is not handled here. Otherwise the return value is the id of the handler that should handle the exception. It is called during the search phase. It is constructed from the conditional part of each handler. It runs each check in turn, first checking to see if the object \item The catch function: This function handles the exception. It takes a pointer to the exception and the handler's id and returns nothing. It is called after the clean-up phase. It is constructed by stitching together the bodies of each handler \end{itemize} All three are created with GCC nested functions. GCC nested functions can be used to create closures, functions that can refer to the state of other functions on the stack. This allows the functions to refer to the main function and all the variables in scope. These nested functions and all other functions besides @__cfaehm_try_terminate@ in \CFA use the GCC personality function and the @-fexceptions@ flag to generate the LSDA. This allows destructors to be implemented with the cleanup attribute. \begin{description} \item[try function:] This function is the try block, all the code inside the try block is placed inside the try function. It takes no parameters and has no return value. This function is called during regular execution to run the try block. \item[match function:] This function is called during the search phase and decides if a catch clause matches the termination exception.  It is constructed from the conditional part of each handler and runs each check, top to bottom, in turn, first checking to see if the exception type matches and then if the condition is true. It takes a pointer to the exception and returns 0 if the exception is not handled here. Otherwise the return value is the id of the handler that matches the exception. \item[handler function:] This function handles the exception. It takes a pointer to the exception and the handler's id and returns nothing. It is called after the cleanup phase.  It is constructed by stitching together the bodies of each handler and dispatches to the selected handler. \end{description} All three functions are created with GCC nested functions. GCC nested functions can be used to create closures, functions that can refer to the state of other functions on the stack. This approach allows the functions to refer to all the variables in scope for the function containing the @try@ statement.  These nested functions and all other functions besides @__cfaehm_try_terminate@ in \CFA use the GCC personality function and the @-fexceptions@ flag to generate the LSDA. This allows destructors to be implemented with the cleanup attribute. \section{Resumption} % The stack-local data, the linked list of nodes. Resumption uses a list of nodes for its stack traversal. The head of the list is stored in the exception context. The nodes in the list just have a pointer Resumption simple to implement because there is no stack unwinding. The resumption raise uses a list of nodes for its stack traversal. The head of the list is stored in the exception context. The nodes in the list have a pointer to the next node and a pointer to the handler function. The on a resumption throw the this list is traversed. At each node the handler function is called and is passed the exception by pointer. It returns true if the exception was handled and false otherwise. The handler function does both the matching and catching. It tries each the condition of @catchResume@ in order, top-to-bottom and until it finds a handler that matches. If no handler matches then the function returns false. Otherwise the matching handler is run, if it completes successfully the function returns true. Rethrows, through the @throwResume;@ statement, cause the function to return true. A resumption raise traverses this list. At each node the handler function is called, passing the exception by pointer. It returns true if the exception is handled and false otherwise. The handler function does both the matching and handling. It computes the condition of each @catchResume@ in top-to-bottom order, until it finds a handler that matches. If no handler matches then the function returns false. Otherwise the matching handler is run; if it completes successfully, the function returns true. Reresume, through the @throwResume;@ statement, cause the function to return true. % Recursive Resumption Stuff: Blocking out part of the stack is accomplished by updating the front of the list as the search continues. Before the handler at a node is called the head of the list is updated to the next node of the current node. After the search is complete, successful or not, the head of the list is reset. This means the current handler and every handler that has already been checked are not on the list while a handler is run. If a resumption is thrown during the handling of another resumption the active handlers and all the other handler checked up to this point will not be checked again. Search skipping \see{\VPageref{p:searchskip}}, which ignores parts of the stack already examined, is accomplished by updating the front of the list as the search continues. Before the handler at a node is called the head of the list is updated to the next node of the current node. After the search is complete, successful or not, the head of the list is reset. This mechanism means the current handler and every handler that has already been checked are not on the list while a handler is run. If a resumption is thrown during the handling of another resumption the active handlers and all the other handler checked up to this point are not checked again. This structure also supports new handler added while the resumption is being handled. These are added to the front of the list, pointing back along the stack -- the first one will point over all the checked handlers -- and the ordering is maintained. \subsection{Libunwind Compatibility} Resumption does not use libunwind for two simple reasons. The first is that it does not have to unwind anything so would never need to use the clean-up phase. Still the search phase could be used to make it free to enter or exit a try statement with resumption handlers in the same way termination handlers are for the same trade off in the cost of the throw. This is where the second reason comes in, there is no way to return from a search without installing a handler or raising an error. Although work arounds could be created none seemed to be worth it for the prototype. This implementation has no difference in behaviour and is much simpler. stack -- the first one points over all the checked handlers -- and the ordering is maintained. \label{p:zero-cost} Note, the resumption implementation has a cost for entering/exiting a @try@ statement with @catchResume@ clauses, whereas a @try@ statement with @catch@ clauses has zero-cost entry/exit. While resumption does not need the stack unwinding and cleanup provided by libunwind, it could use the search phase to providing zero-cost enter/exit using the LSDA. Unfortunately, there is no way to return from a libunwind search without installing a handler or raising an error.  Although workarounds might be possible, they are beyond the scope of this thesis. The current resumption implementation has simplicity in its favour. % Seriously, just compare the size of the two chapters and then consider % that unwind is required knowledge for that chapter. \section{Finally} % Uses destructors and GCC nested functions. Finally clauses are a simple decomposition to some of the existing features. The code in the block is placed into a GCC nested function with a unique name, no arguments or return values. This nested function is then set as the clean-up function of an empty object that is declared at the beginning of a block placed around the contexts of the try statement. Finally clauses is placed into a GCC nested-function with a unique name, and no arguments or return values. This nested function is then set as the cleanup function of an empty object that is declared at the beginning of a block placed around the context of the associated @try@ statement. The rest is handled by GCC. The try block and all handlers are inside the block. When they are complete control exits the block and the empty object is cleaned up, which runs the function that contains the finally code. block. At completion, control exits the block and the empty object is cleaned up, which runs the function that contains the finally code. \section{Cancellation} Cancellation also uses libunwind to do its stack traversal and unwinding, however it uses a different primary function @_Unwind_ForcedUnwind@. Details of its interface can be found in the unwind section. The first step of cancellation is to find the stack was cancelled and which type of stack it is. Luckily the threads library stores the main thread pointer and the current thread pointer and every thread stores a pointer to however it uses a different primary function @_Unwind_ForcedUnwind@.  Details of its interface can be found in the \VRef{s:ForcedUnwind}. The first step of cancellation is to find the cancelled stack and its type: coroutine or thread. Fortunately, the thread library stores the main thread pointer and the current thread pointer, and every thread stores a pointer to its main coroutine and the coroutine it is currently executing. So if the the current thread's main and current coroutine do not match, it is a coroutine cancellation. Otherwise if the main and current thread do not match, it is a thread cancellation. Otherwise it is a main thread cancellation. However if the threading library is not linked then execution must be on the main stack as that is the only one that exists. So the entire check is skipped using the linker and weak symbols. Instead the main thread cancellation is unconditionally preformed. Regardless of how they are choosen afterwords the stop function and the stop parameter are passed to the forced unwind functon. The general pattern of all three stop functions is the same, they continue unwinding until the end of stack when they do there primary work. Main stack cancellation it is very simple. The transfer" is just an abort, the program stops executing. The coroutine cancellation stores the exception on the coroutine and then does a coroutine context switch. The rest is handled inside resume. Every time control returns from a resumed thread there is a check to see if it is cancelled. If it is the exception is retrieved and the CoroutineCancelled exception is constructed and loaded. It is then thrown as a regular exception with the default handler coming from the context of the resumption call. The thread cancellation stores the exception on the thread's main stack and then returns to the scheduler. The rest is handled by the joiner. The wait for the joined thread to finish works the same but after that it checks to see if there was a cancellation. If there was the exception is retrieved and the ThreadCancelled exception is constructed. The default handler is passed in as a function pointer. If it is null (as it is for the auto-generated joins on destructor call) it a default is used that simply calls abort; which gives the required handling on implicate join. The first check is if the current thread's main and current coroutine do not match, implying a coroutine cancellation; otherwise, it is a thread cancellation. Otherwise it is a main thread cancellation. \PAB{Previous sentence does not make sense.} However, if the threading library is not linked, the sequential execution is on the main stack. Hence, the entire check is skipped because the weak-symbol function is loaded. Therefore, a main thread cancellation is unconditionally performed. Regardless of how the stack is chosen, the stop function and parameter are passed to the forced-unwind function. The general pattern of all three stop functions is the same: they continue unwinding until the end of stack when they do there primary work. For main stack cancellation, the transfer is just a program abort. For coroutine cancellation, the exception is stored on the coroutine's stack, and the coroutine context switches to its last resumer. The rest is handled on the backside of the resume, which check if the resumed coroutine is cancelled. If cancelled, the exception is retrieved from the resumed coroutine, and a @CoroutineCancelled@ exception is constructed and loaded with the cancelled exception. It is then resumed as a regular exception with the default handler coming from the context of the resumption call. For thread cancellation, the exception is stored on the thread's main stack and then context switched to the scheduler. The rest is handled by the thread joiner. When the join is complete, the joiner checks if the joined thread is cancelled. If cancelled, the exception is retrieved and the joined thread, and a @ThreadCancelled@ exception is constructed and loaded with the cancelled exception. The default handler is passed in as a function pointer. If it is null (as it is for the auto-generated joins on destructor call), the default is used, which is a program abort. %; which gives the required handling on implicate join.
• doc/theses/andrew_beach_MMath/thesis-frontpgs.tex

 rc292244 A thesis \\ presented to the University of Waterloo \\ presented to the University of Waterloo \\ in fulfillment of the \\ thesis requirement for the degree of \\ \cleardoublepage %---------------------------------------------------------------------- % EXAMINING COMMITTEE (Required for Ph.D. theses only) \begin{center}\textbf{Examining Committee Membership}\end{center} \noindent The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. \bigskip \noindent \begin{tabbing} Internal-External Member: \=  \kill % using longest text to define tab length External Examiner: \>  Bruce Bruce \\ The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. \bigskip \noindent \begin{tabbing} Internal-External Member: \=  \kill % using longest text to define tab length External Examiner: \>  Bruce Bruce \\ \> Professor, Dept. of Philosophy of Zoology, University of Wallamaloo \\ \end{tabbing} \bigskip \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} % December 13th, 2006.  It is designed for an electronic thesis. \noindent I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. \bigskip I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. \bigskip \noindent I understand that my thesis may be made electronically available to the public.
• doc/theses/andrew_beach_MMath/thesis.tex

 rc292244 % FRONT MATERIAL %---------------------------------------------------------------------- \input{thesis-frontpgs} \input{thesis-frontpgs} %---------------------------------------------------------------------- A \gls{computer} could compute $\pi$ all day long. In fact, subsets of digits of $\pi$'s decimal approximation would make a good source for psuedo-random vectors, \gls{rvec} . vectors, \gls{rvec} . %---------------------------------------------------------------------- \begin{itemize} \item A well-prepared PDF should be \item A well-prepared PDF should be \begin{enumerate} \item Of reasonable size, {\it i.e.} photos cropped and compressed. \item Scalable, to allow enlargment of text and drawings. \end{enumerate} \item Scalable, to allow enlargment of text and drawings. \end{enumerate} \item Photos must be bit maps, and so are not scaleable by definition. TIFF and BMP are uncompressed formats, while JPEG is compressed. Most photos can be compressed without losing their illustrative value. \item Drawings that you make should be scalable vector graphics, \emph{not} \item Drawings that you make should be scalable vector graphics, \emph{not} bit maps. Some scalable vector file formats are: EPS, SVG, PNG, WMF. These can all be converted into PNG or PDF, that pdflatex recognizes. Your drawing package probably can export to one of these formats directly. Otherwise, a common procedure is to print-to-file through a Postscript printer driver to create a PS file, then convert that to EPS (encapsulated PS, which has a bounding box to describe its exact size rather than a whole page). all be converted into PNG or PDF, that pdflatex recognizes. Your drawing package probably can export to one of these formats directly. Otherwise, a common procedure is to print-to-file through a Postscript printer driver to create a PS file, then convert that to EPS (encapsulated PS, which has a bounding box to describe its exact size rather than a whole page). Programs such as GSView (a Ghostscript GUI) can create both EPS and PDF from PS files. Appendix~\ref{AppendixA} shows how to generate properly sized Matlab plots and save them as PDF. \item It's important to crop your photos and draw your figures to the size that you want to appear in your thesis. Scaling photos with the includegraphics command will cause loss of resolution. And scaling down you want to appear in your thesis. Scaling photos with the includegraphics command will cause loss of resolution. And scaling down drawings may cause any text annotations to become too small. \end{itemize} For more information on \LaTeX\, see the uWaterloo Skills for the Academic Workplace \href{https://uwaterloo.ca/information-systems-technology/services/electronic-thesis-preparation-and-submission-support/ethesis-guide/creating-pdf-version-your-thesis/creating-pdf-files-using-latex/latex-ethesis-and-large-documents}{course notes}. Academic Workplace \href{https://uwaterloo.ca/information-systems-technology/services/electronic-thesis-preparation-and-submission-support/ethesis-guide/creating-pdf-version-your-thesis/creating-pdf-files-using-latex/latex-ethesis-and-large-documents}{course notes}. \footnote{ Note that while it is possible to include hyperlinks to external documents, it is not wise to do so, since anything you can't control may change over time. It \emph{would} be appropriate and necessary to provide external links to additional resources for a multimedia enhanced'' thesis. But also note that if the \package{hyperref} package is not included, as for the print-optimized option in this thesis template, any \cmmd{href} it is not wise to do so, since anything you can't control may change over time. It \emph{would} be appropriate and necessary to provide external links to additional resources for a multimedia enhanced'' thesis. But also note that if the \package{hyperref} package is not included, as for the print-optimized option in this thesis template, any \cmmd{href} commands in your logical document are no longer defined. A work-around employed by this thesis template is to define a dummy \cmmd{href} command (which does nothing) in the preamble of the document, before the \package{hyperref} package is included. \cmmd{href} command (which does nothing) in the preamble of the document, before the \package{hyperref} package is included. The dummy definition is then redifined by the \package{hyperref} package when it is included. The classic book by Leslie Lamport \cite{lamport.book}, author of \LaTeX , is worth a look too, and the many available add-on packages are described by worth a look too, and the many available add-on packages are described by Goossens \textit{et al} \cite{goossens.book}. Export Setup button in the figure Property Editor. \section{From the Command Line} \section{From the Command Line} All figure properties can also be manipulated from the command line. Here's an example: example: \begin{verbatim} x=[0:0.1:pi];
• doc/theses/andrew_beach_MMath/unwinding.tex

 rc292244 \chapter{\texorpdfstring{Unwinding in \CFA}{Unwinding in Cforall}} \chapter{Unwinding in \CFA} Stack unwinding is the process of removing things from the stack. Within functions and on function return this is handled directly by the code in the function itself as it knows exactly what is on the stack just from the current location in the function. Unwinding across stack frames means that it is no longer knows exactly what is on the stack or even how much of the stack needs to be removed. Stack unwinding is the process of removing stack frames (activations) from the stack. On function entry and return, unwinding is handled directly by the code embedded in the function. Usually, the stack-frame size is known statically based on parameters and local variable declarations.  For dynamically-sized local variables, a runtime computation is necessary to know the frame size. Finally, a function's frame-size may change during execution as local variables (static or dynamic sized) go in and out of scope. Allocating/deallocating stack space is usually an $O(1)$ operation achieved by bumping the hardware stack-pointer up or down as needed. Even this is fairly simple if nothing needs to happen when the stack unwinds. Traditional C can unwind the stack by saving and restoring state (with @setjmp@ \& @longjmp@). However many languages define actions that have to be taken when something is removed from the stack, such as running a variable's destructor or a @try@ statement's @finally@ clause. Handling this requires walking the stack going through each stack frame. Unwinding across multiple stack frames is more complex because individual stack management code associated with each frame is bypassed. That is, the location of a function's frame code is largely unknown and dispersed throughout the function, hence the current stack-frame size managed by that code is also unknown. Hence, code unwinding across frames does not have direct knowledge about what is on the stack, and hence, how much of the stack needs to be removed. For exceptions, this means everything from the point the exception is raised to the point it is caught, while checking each frame for handlers during the stack walk to find out where it should be caught. This is where the most of the expense and complexity of exception handling comes from. The traditional unwinding mechanism for C is implemented by saving a snap-shot of a function's state with @setjmp@ and restoring that snap-shot with @longjmp@. This approach bypasses the need to know stack details by simply reseting to a snap-shot of an arbitrary but existing function frame on the stack. It is up to the programmer to ensure the snap-shot is valid when it is reset, making the code fragile with potential errors that are difficult to debug because the stack becomes corrupted. To do all of this we use libunwind, a low level library that provides tools for stack walking and stack unwinding. What follows is an overview of all the relivant features of libunwind and then how \CFA uses them to implement its exception handling. However, many languages define cleanup actions that have to be taken when something is deallocated from the stack or blocks end, such as running a variable's destructor or a @try@ statement's @finally@ clause. Handling these mechanisms requires walking the stack and checking each stack frame for these potential actions. For exceptions, it must be possible to walk the stack frames in search of try statements with handlers to perform exception matching. For termination exceptions, it must be possible to unwind all stack frames from the throw to the matching catch, and each of these frames must be checked for cleanup actions. Stack walking is where the most of the complexity and expense of exception handling comes from. One of the most popular tools for stack management is libunwind, a low level library that provides tools for stack walking and unwinding. What follows is an overview of all the relevant features of libunwind and how \CFA uses them to implement its exception handling. \section{libunwind Usage} \CFA uses two primary functions in libunwind to create most of its exceptional control-flow: @_Unwind_RaiseException@ and @_Unwind_ForcedUnwind@. Their operation is divided into two phases: search and clean-up. The search phase -- phase 1 -- is used to scan the stack but not unwinding it. The clean-up phase -- phase 2 -- is used for unwinding. \CFA uses two primary functions in libunwind to create most of its exceptional control-flow: @_Unwind_RaiseException@ and @_Unwind_ForcedUnwind@.  Their operation is divided into two phases: search and clean-up. The search phase -- phase 1 -- is used to scan the stack but not unwinding it. The clean-up phase -- phase 2 -- is used for unwinding. The raise-exception function uses both phases. It starts by searching for a A personality function performs three tasks, although not all have to be present. The tasks performed are decided by the actions provided. @_Unwind_Action@ is a bitmask of possible actions and an argument of this type is passed into the personality function. @_Unwind_Action@ is a bitmask of possible actions and an argument of this type is passed into the personality function. \begin{itemize} \item@_UA_SEARCH_PHASE@ is passed in search phase and tells the personality function to check for handlers. If there is a handler in this stack frame, as defined by the language, the personality function should return @_URC_HANDLER_FOUND@. Otherwise it should return @_URC_CONTINUE_UNWIND@. \item@_UA_CLEANUP_PHASE@ is passed in during the clean-up phase and means part or all of the stack frame is removed. The personality function should do whatever clean-up the language defines (such as running destructors/finalizers) and then generally returns @_URC_CONTINUE_UNWIND@. \item@_UA_HANDLER_FRAME@ means the personality function must install a handler. It is also passed in during the clean-up phase and is in addition to the clean-up action. libunwind provides several helpers for the personality function here. Once it is done, the personality function must return @_URC_INSTALL_CONTEXT@. \item \begin{sloppypar} @_UA_SEARCH_PHASE@ is passed in for the search phase and tells the personality function to check for handlers. If there is a handler in a stack frame, as defined by the language, the personality function returns @_URC_HANDLER_FOUND@; otherwise it return @_URC_CONTINUE_UNWIND@. \end{sloppypar} \item @_UA_CLEANUP_PHASE@ is passed in during the clean-up phase and means part or all of the stack frame is removed. The personality function does whatever clean-up the language defines (such as running destructors/finalizers) and then generally returns @_URC_CONTINUE_UNWIND@. \item @_UA_HANDLER_FRAME@ means the personality function must install a handler. It is also passed in during the clean-up phase and is in addition to the clean-up action. libunwind provides several helpers for the personality function. Once it is done, the personality function returns @_URC_INSTALL_CONTEXT@. \end{itemize} The personality function is given a number of other arguments. Some are for compatability and there is the @struct _Unwind_Context@ pointer which passed to many helpers to get information about the current stack frame. The personality function is given a number of other arguments. Some arguments are for compatibility, and there is the @struct _Unwind_Context@ pointer which is passed to many helpers to get information about the current stack frame. Forced-unwind only performs the clean-up phase. It takes three arguments: a pointer to the exception, a pointer to the stop function and a pointer to the stop parameter. It does most of the same things as phase two of raise-exception but with some extras. The first it passes in an extra action to the personality function on each stack frame, @_UA_FORCE_UNWIND@, which means a handler cannot be For cancellation, forced-unwind only performs the clean-up phase. It takes three arguments: a pointer to the exception, a pointer to the stop function and a pointer to the stop parameter. It does most of the same actions as phase two of raise-exception but passes in an extra action to the personality function on each stack frame, @_UA_FORCE_UNWIND@, which means a handler cannot be installed. The big change is that forced-unwind calls the stop function. Each time it steps into a frame, before calling the personality function, it calls the stop function. The stop function receives all the same arguments as the personality function will and the stop parameter supplied to forced-unwind. As well, forced-unwind calls the stop function each time it steps into a frame, before calling the personality function. The stop function receives all the same arguments as the personality function and the stop parameter supplied to forced-unwind. The stop function is called one more time at the end of the stack after all stack frames have been removed. By the standard API this is marked by setting stack frames have been removed. The standard API marks this frame by setting the stack pointer inside the context passed to the stop function. However both GCC and Clang add an extra action for this case @_UA_END_OF_STACK@. Each time function the stop function is called it can do one or two things. When it is not the end of the stack it can return @_URC_NO_REASON@ to continue unwinding. Each time the stop function is called, it can do one or two things.  When it is not the end of the stack it can return @_URC_NO_REASON@ to continue unwinding. % Is there a reason that NO_REASON is used instead of CONTINUE_UNWIND? Its only other option is to use its own means to transfer control elsewhere and never return to its caller. It may always do this and no additional tools are provided to do it. The other option is to use some other means to transfer control elsewhere and never return to its caller. libunwind provides no additional tools for alternate transfers of control. \section{\texorpdfstring{\CFA Implementation}{Cforall Implementation}} \section{\CFA Implementation} To use libunwind, \CFA provides several wrappers, its own storage, personality functions, and a stop function. To use libunwind, \CFA provides several wrappers, its own storage, personality functions, and a stop function. The wrappers perform three tasks: set-up, clean-up and controlling the The core control code is called every time a throw -- after set-up -- or re-throw is run. It uses raise-exception to search for a handler and to run it if one is found. If no handler is found and raise-exception returns then if one is found. If no handler is found and raise-exception returns, then forced-unwind is called to run all destructors on the stack before terminating the process. The stop function is very simple. It checks the end of stack flag to see if it is finished unwinding. If so, it calls @exit@ to end the process, otherwise it returns with no-reason to continue unwinding. The stop function is simple. It checks for the end of stack flag to see if unwinding is finished. If so, it calls @exit@ to end the process, otherwise it returns with no-reason to continue unwinding. % Yeah, this is going to have to change. The personality routine is more complex because it has to obtain information about the function by scanning the LSDA (Language Specific Data Area). This about the function by scanning the Language Specific Data Area (LSDA). This step allows a single personality function to be used for multiple functions and let that personaliity function figure out exactly where in the function execution was, what is currently in the stack frame and what handlers should be checked. lets that personality function figure out exactly where in the function execution is, what is currently in the stack frame, and what handlers should be checked. % Not that we do that yet. However, generating the LSDA is difficult. It requires knowledge about the location of the instruction pointer and stack layout, which varies with compiler and optimization levels. So for frames where there are only destructors, GCC's attribute cleanup with the @-fexception@ flag is sufficient to handle unwinding. It is also necessary to generate the LSDA, which is difficult. It requires knowledge about the location of the instruction pointer and stack layout, which varies with compiler and optimization levels. Fortunately, for frames where there are only destructors, GCC's attribute cleanup with the @-fexception@ flag is sufficient to handle unwinding. The only functions that require more than that are those that contain @try@ statements. A @try@ statement has a @try@ clause, some number of @catch@ clauses and @catchResume@ clauses and may have a @finally@ clause. Of these only @try@ statements with @catch@ clauses need to be transformed and only they and the @try@ clause are involved. The only functions that require more information are those containing @try@ statements. Specifically, only @try@ statements with @catch@ clauses need to be transformed.  The @try@ statement is converted into a series of closures that can access other parts of the function according to scoping rules but can be passed around. The @catch@ clauses are converted into two functions: the match function and the handler function. The @try@ statement is converted into a series of closures which can access other parts of the function according to scoping rules but can be passed around. The @try@ clause is converted into the try functions, almost entirely unchanged. The @catch@ clauses are converted into two functions; the match function and the catch function. Together the match function and the catch function form the code that runs when an exception passes out of the guarded block for a try statement. The match function is used during the search phase: it is passed an exception and checks each handler to see if the raised exception matches the handler exception. It returns an index that represents which handler matched or there is no match. The catch function is used during the clean-up phase, it is passed an exception and the index of a handler. It casts the exception to the exception type declared in that handler and then runs the handler's body. Together the match function and the catch function form the code that runs when an exception passes out of a try block. The match function is used during the search phase, it is passed an exception and checks each handler to see if it will handle the exception. It returns an index that repersents which handler matched or that none of them did. The catch function is used during the clean-up phase, it is passed an exception and the index of a handler. It casts the exception to the exception type declared in that handler and then runs the handler's body. These three functions are passed to @try_terminate@. This is an These three functions are passed to @try_terminate@, which is an % Maybe I shouldn't quote that, it isn't its actual name. internal hand-written function that has its own personality function and custom assembly LSD does the exception handling in \CFA. During normal execution all this function does is call the try function and then return. It is only when exceptions are thrown that anything interesting happens. internal hand-written function that has its own personality function and custom assembly LSDA for doing the exception handling in \CFA. During normal execution, this function calls the try function and then return.  It is only when exceptions are thrown that anything interesting happens. During the search phase the personality function gets the pointer to the match function and calls it. If the match function returns a handler index the function and calls it. If the match function returns a handler index, the personality function saves it and reports that the handler has been found, otherwise unwinding continues. During the clean-up phase the personality function only does anything if the handler was found in this frame. If it was then the personality function installs the handler, which is setting the instruction pointer in @try_terminate@ to an otherwise unused section that calls the catch function, passing it the current exception and handler index. @try_terminate@ returns as soon as the catch function returns. otherwise unwinding continues.  During the clean-up phase, the personality function only performs an action, when a handler is found in a frame. For each found frame, the personality function installs the handler, which sets the instruction pointer in @try_terminate@ to an otherwise unused section that calls the catch function, passing it the current exception and handler index. @try_terminate@ returns as soon as the catch function returns.  At this point control has returned to normal control flow. At this point control has returned to normal control flow. \PAB{Maybe a diagram would be helpful?}
• doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex

 rc292244 \vspace*{1.0cm} \Huge {\bf Exception Handling in \CFA} {\Huge\bf Exception Handling in \CFA} \vspace*{1.0cm} \normalsize by \\ \vspace*{1.0cm} \Large Andrew James Beach \\ {\Large Andrew James Beach} \\ \vspace*{3.0cm} \normalsize A thesis \\ presented to the University of Waterloo \\ presented to the University of Waterloo \\ in fulfillment of the \\ thesis requirement for the degree of \\ \vspace*{1.0cm} \copyright\ Andrew James Beach \the\year \\ \copyright{} Andrew James Beach \the\year \\ \end{center} \end{titlepage} % The rest of the front pages should contain no headers and be numbered using Roman numerals starting with ii' % The rest of the front pages should contain no headers and be numbered using % Roman numerals starting with ii'. \pagestyle{plain} \setcounter{page}{2} \cleardoublepage % Ends the current page and causes all figures and tables that have so far appeared in the input to be printed. % In a two-sided printing style, it also makes the next page a right-hand (odd-numbered) page, producing a blank page if necessary. \cleardoublepage % Ends the current page and causes all figures and tables % that have so far appeared in the input to be printed. In a two-sided % printing style, it also makes the next page a right-hand (odd-numbered) % page, producing a blank page if necessary. \begin{comment} \begin{comment} % E X A M I N I N G   C O M M I T T E E (Required for Ph.D. theses only) % Remove or comment out the lines below to remove this page \begin{center}\textbf{Examining Committee Membership}\end{center} \noindent The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. The following served on the Examining Committee for this thesis. The decision of the Examining Committee is by majority vote. \bigskip \noindent \begin{tabbing} Internal-External Member: \=  \kill % using longest text to define tab length External Examiner: \>  Bruce Bruce \\ External Examiner: \>  Bruce Bruce \\ \> Professor, Dept. of Philosophy of Zoology, University of Wallamaloo \\ \end{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} \end{tabbing} \bigskip \noindent \begin{tabbing} % December 13th, 2006.  It is designed for an electronic thesis. \begin{center}\textbf{Author's Declaration}\end{center} \noindent I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. \bigskip \noindent I understand that my thesis may be made electronically available to the public.