# Changeset 4260566

Ignore:
Timestamp:
Mar 24, 2021, 6:31:02 PM (19 months ago)
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
8d4c9f4
Parents:
4150779
Message:

Andrew MMath: Clean-up of features.tex. Put more general EHM information in the opening and started updating the virtual section.

File:
1 edited

### Legend:

Unmodified
 r4150779 This chapter covers the design and user interface of the \CFA exception-handling mechanism. \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 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. exception-handling mechanism (EHM). % or exception system. % We should cover what is an exception handling mechanism and what is an % exception before this. Probably in the introduction. Some of this could % move there. \paragraph{Raise / Handle} An exception operation has two main parts: raise and handle. These are the two parts that the user will write themselves and so might be the only two pieces of the EHM that have any syntax. These terms are sometimes also known as throw and catch but this work uses throw/catch as a particular kind of raise/handle. \subparagraph{Raise} The raise is the starting point for exception handling and usually how Some well known examples include the throw statements of \Cpp and Java and the raise statement from Python. For this overview a raise does nothing more kick off the handling of an exception, which is called raising the exception. This is inexact but close enough for the broad strokes of the overview. \subparagraph{Handle} The purpose of most exception operations is to run some sort of handler that contains user code. The try statement of \Cpp illistrates the common features Handlers have three common features: a region of code they apply to, an exception label that describes what exceptions they handle and code to run when they handle an exception. Each handler can handle exceptions raised in that region that match their exception label. Different EHMs will have different rules to pick a handler if multipe handlers could be used such as best match" or first found". \paragraph{Propagation} After an exception is raised comes what is usually the biggest step for the EHM, finding and setting up the handler. This can be broken up into three different tasks: searching for a handler, matching against the handler and installing the handler. First the EHM must search for possible handlers that could be used to handle the exception. Searching is usually independent of the exception that was thrown and instead depends on the call stack, the current function, its caller and repeating down the stack. Second it much match the exception with each handler to see which one is the best match and hence which one should be used to handle the exception. In languages where the best match is the first match these two are often intertwined, a match check is preformed immediately after the search finds a possible handler. Third, after a handler is chosen it must be made ready to run. What this actually involves can vary widely to fit with the rest of the design of the EHM. The installation step might be trivial or it could be the most expensive step in handling an exception. The latter tends to be the case when stack unwinding is involved. As an alternate third step if no appropriate handler is found then some sort of recovery has to be preformed. This is only required with unchecked exceptions as checked exceptions can promise that a handler is found. It also is also installing a handler but it is a special default that may be installed differently. \subparagraph{Hierarchy} In \CFA the EHM uses a hierarchial system to organise its exceptions. This stratagy is borrowed from object-orientated languages where the exception hierarchy is a natural extension of the object hierarchy. Consider the following hierarchy of exceptions: \begin{center} \setlength{\unitlength}{4000sp}% \end{picture}% \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 exception-type in higher-level code where the implementation details are unknown, which reduces tight coupling to the lower-level implementation. Otherwise, low-level code changes require higher-level code changes, \eg, changing from raising @underflow@ to @overflow@ at the low level means changing the matching catch at the high level versus catching the general @arithmetic@ exception. In detail, each virtual type may have a parent and can have any number of children. A type's descendants are its children and its children's descendants. A type may not be its own descendant. The exception hierarchy allows a handler (@catch@ clause) to match multiple exceptions, \eg a base-type handler catches both base and derived exception-types. \begin{cfa} try { ... } catch(arithmetic &) { ... // handle arithmetic, underflow, overflow, zerodivide } \end{cfa} Most exception mechanisms perform a linear search of the handlers and select the first matching handler, so the order of handers is now important because matching is many to one. Each virtual type needs an associated virtual table. A virtual table is a structure with fields for all the virtual members of a type. A virtual type has all the virtual members of its parent and can add more. It may also update the values of the virtual members and often does. A handler labelled with any given exception can handle exceptions of that type or any child type of that exception. The root of the exception hierarchy (here \texttt{exception}) acts as a catch-all, leaf types catch single types and the exceptions in the middle can be used to catch different groups of related exceptions. This system has some notable advantages, such as multiple levels of grouping, the ability for libraries to add new exception types and the isolation between different sub-hierarchies. So the design was adapted for a non-object-orientated language. % Could I cite the rational for the Python IO exception rework? \paragraph{Completion} After the handler has finished the entire exception operation has to complete and continue executing somewhere else. This step is usually very simple both logically and in its implementation as the installation of the handler usually does the heavy lifting. The EHM can return control to many different places. However, the most common is after the handler definition and the next most common is after the raise. \paragraph{Communication} For effective exception handling, additional information is usually required as this base model only communicates the exception's identity. Common additional methods of communication are putting fields on an exception and allowing a handler to access the lexical scope it is defined in (usually a function's local variables). \paragraph{Other Features} Any given exception handling mechanism is free at add other features on top of this. This is an overview of the base that all EHMs use but it is not an exaustive list of everything an EHM can do. \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 virtual system supports multiple trees" of types. Each tree is a simple hierarchy with a single root type. Each type in a tree has exactly one parent - except for the root type which has zero parents - and any number of children. Any type that belongs to any of these trees is called a virtual type. % A type's ancestors are its parent and its parent's ancestors. % The root type has no ancestors. % A type's decendents are its children and its children's decendents. Every virtual type also has a list of virtual members. Children inherit their parent's list of virtual members but may add new members to it. It is important to note that these are virtual members, not virtual methods. However as function pointers are allowed they can be used to mimic virtual methods as well. The unique id for the virtual type and all the virtual members are combined into a virtual table type. Each virtual type has a pointer to a virtual table as a hidden field. \todo{Open/Closed types and how that affects the virtual design.} While much of the virtual infrastructure is created, it is currently only used \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 The cast dynamically checks if the @EXPRESSION@ type is the same or a sub-type of @TYPE@, and if true, returns a pointer to the @EXPRESSION@ object, otherwise it returns @0p@ (null pointer). The function @get_exception_vtable@ is actually a constant function. Recardless of the value passed in (including the null pointer) it should Regardless 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 and their use will be detailed there. However all three of these traits can be trickly to use directly. However all three of these traits can be tricky to use directly. There is a bit of repetition required but the largest issue is that the virtual table type is mangled and not in a user list will be passed to both types. In the current set-up the base name and the polymorphic arguments have to match so these macros can be used without losing flexability. match so these macros can be used without losing flexibility. For example consider a function that is polymorphic over types that have a It is dynamic, non-local goto. If a throw is successful then the stack will be unwound and control will (usually) continue in a different function on the call stack. They are commonly used when an error has occured and recovery the call stack. They are commonly used when an error has occurred and recovery is impossible in the current function. \end{cfa} The expression must return a reference to a termination exception, where the termination exception is any type that satifies @is_termination_exception@ termination exception is any type that satisfies @is_termination_exception@ at the call site. Through \CFA's trait system the functions in the traits are passed into the The throw will copy the provided exception into managed memory. It is the user's responcibility to ensure the original exception is cleaned up if the user's responsibility to ensure the original exception is cleaned up if the stack is unwound (allocating it on the stack should be sufficient). } \end{cfa} When viewed on its own a try statement will simply exceute the statements in When viewed on its own a try statement will simply execute the statements in @GUARDED_BLOCK@ and when those are finished the try statement finishes. 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 it is the same of a descendent of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ is it is the same of a descendant 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 closure will be taken from up the stack and executed, after which the throwing function will continue executing. These are most often used when an error occured and if the error is repaired These are most often used when an error occurred and if the error is repaired then the function can continue. \end{cfa} The semantics of the @throwResume@ statement are like the @throw@, but the expression has return a reference a type that satifies the trait expression has return a reference a type that satisfies the trait @is_resumption_exception@. The assertions from this trait are available to the exception system while handling the exception. At runtime, no copies are made. As the stack is not unwound the exception and At run-time, 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. search and match the handler in the @catchResume@ clause. This will be call and placed on the stack on top of the try-block. The second throw then throws and will seach the same try block and put call another instance of the throws and will search the same try block and put call another instance of the same handler leading to an infinite loop. can form with multiple handlers and different exception types. To prevent all of these cases we mask sections of the stack, or equvilantly the try statements on the stack, so that the resumption seach skips over To prevent all of these cases we mask sections of the stack, or equivalently the try statements on the stack, so that the resumption search skips over them and continues with the next unmasked section of the stack. The symmetry with termination is why this pattern was picked. Other patterns, such as marking just the handlers that caught, also work but lack the symmetry whih means there is more to remember. symmetry which means there is more to remember. \section{Conditional Catch} } \end{cfa} Note, catching @IOFailure@, checking for @f1@ in the handler, and reraising the exception if not @f1@ is different because the reraise does not examine any of Note, catching @IOFailure@, checking for @f1@ in the handler, and re-raising the exception if not @f1@ is different because the re-raise does not examine any of remaining handlers in the current try statement. @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, and at best requiring additional run-time overhead, and so are mearly and at best requiring additional run-time overhead, and so are mealy discouraged. this point.} The recommended way to avoid the abort is to handle the intial resumption The recommended way to avoid the abort is to handle the initial 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