source: doc/theses/andrew_beach_MMath/intro.tex @ 678f259

ADTast-experimentalenumforall-pointer-decayjacob/cs343-translationpthread-emulationqualifiedEnum
Last change on this file since 678f259 was 6cf21ed8, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Andrew MMath: First pass on adding missing citations.

  • Property mode set to 100644
File size: 14.4 KB
Line 
1\chapter{Introduction}
2
3% The highest level overview of Cforall and EHMs. Get this done right away.
4This thesis covers the design and implementation of the exception handling
5mechanism (EHM) of
6\CFA (pronounced sea-for-all and may be written Cforall or CFA).
7\CFA is a new programming language that extends C, which maintains
8backwards-compatibility while introducing modern programming features.
9Adding exception handling to \CFA gives it new ways to handle errors and
10make large control-flow jumps.
11
12% Now take a step back and explain what exceptions are generally.
13Exception handling provides dynamic inter-function control flow.
14A language's EHM is a combination of language syntax and run-time
15components that construct, raise, propagate and handle exceptions,
16to provide all of that control flow.
17There are two forms of exception handling covered in this thesis:
18termination, which acts as a multi-level return,
19and resumption, which is a dynamic function call.
20% About other works:
21Often, when this separation is not made, termination exceptions are assumed
22as they are more common and may be the only form of handling provided in
23a language.
24
25All types of exception handling link a raise with a handler.
26Both operations are usually language primitives, although raises can be
27treated as a primitive function that takes an exception argument.
28Handlers are more complex as they are added to and removed from the stack
29during execution, must specify what they can handle and give the code to
30handle the exception.
31
32Exceptions work with different execution models but for the descriptions
33that follow a simple call stack, with functions added and removed in a
34first-in-last-out order, is assumed.
35
36Termination exception handling searches the stack for the handler, then
37unwinds the stack to where the handler was found before calling it.
38The handler is run inside the function that defined it and when it finishes
39it returns control to that function.
40\begin{center}
41\input{termination}
42\end{center}
43
44Resumption exception handling searches the stack for a handler and then calls
45it without removing any other stack frames.
46The handler is run on top of the existing stack, often as a new function or
47closure capturing the context in which the handler was defined.
48After the handler has finished running it returns control to the function
49that preformed the raise, usually starting after the raise.
50\begin{center}
51\input{resumption}
52\end{center}
53
54Although a powerful feature, exception handling tends to be complex to set up
55and expensive to use
56so it is often limited to unusual or ``exceptional" cases.
57The classic example is error handling, exceptions can be used to
58remove error handling logic from the main execution path, and pay
59most of the cost only when the error actually occurs.
60
61\section{Thesis Overview}
62This work describes the design and implementation of the \CFA EHM.
63The \CFA EHM implements all of the common exception features (or an
64equivalent) found in most other EHMs and adds some features of its own.
65The design of all the features had to be adapted to \CFA's feature set as
66some of the underlying tools used to implement and express exception handling
67in other languages are absent in \CFA.
68Still the resulting syntax resembles that of other languages:
69\begin{cfa}
70try {
71        ...
72        T * object = malloc(request_size);
73        if (!object) {
74                throw OutOfMemory{fixed_allocation, request_size};
75        }
76        ...
77} catch (OutOfMemory * error) {
78        ...
79}
80\end{cfa}
81% A note that yes, that was a very fast overview.
82The design and implementation of all of \CFA's EHM's features are
83described in detail throughout this thesis, whether they are a common feature
84or one unique to \CFA.
85
86% The current state of the project and what it contributes.
87All of these features have been implemented in \CFA,
88covering both changes to the compiler and the run-time.
89In addition, a suite of test cases and performance benchmarks were created
90along side the implementation.
91The implementation techniques are generally applicable in other programming
92languages and much of the design is as well.
93Some parts of the EHM use other features unique to \CFA and would be
94harder to replicate in other programming languages.
95
96The contributions of this work are:
97\begin{enumerate}
98\item Designing \CFA's exception handling mechanism, adapting designs from
99other programming languages and creating new features.
100\item Implementing stack unwinding and the \CFA EHM, including updating
101the \CFA compiler and the run-time environment.
102\item Designed and implemented a prototype virtual system.
103% I think the virtual system and per-call site default handlers are the only
104% "new" features, everything else is a matter of implementation.
105\item Creating tests to check the behaviour of the EHM.
106\item Creating benchmarks to check the performances of the EHM,
107as compared to other languages.
108\end{enumerate}
109
110The rest of this thesis is organized as follows.
111The current state of exceptions is covered in \autoref{s:background}.
112The existing state of \CFA is also covered in \autoref{c:existing}.
113New EHM features are introduced in \autoref{c:features},
114covering their usage and design.
115That is followed by the implementation of these features in
116\autoref{c:implement}.
117Performance results are examined in \autoref{c:performance}.
118Possibilities to extend this project are discussed in \autoref{c:future}.
119Finally, the project is summarized in \autoref{c:conclusion}.
120
121\section{Background}
122\label{s:background}
123
124Exception handling has been examined before in programming languages,
125with papers on the subject dating back 70s.\cite{Goodenough75}
126Early exceptions were often treated as signals, which carried no information
127except their identity.
128Ada originally used this system\cite{Ada}, but now allows for a string
129message as a payload\cite{Ada12}.
130
131The modern flag-ship for termination exceptions is \Cpp,
132which added them in its first major wave of non-object-orientated features
133in 1990.\cite{CppHistory}
134Many EHMs have special exception types,
135however \Cpp has the ability to use any type as an exception.
136These were found to be not very useful and have been pushed aside for classes
137inheriting from
138\code{C++}{std::exception}.
139Although there is a special catch-all syntax (@catch(...)@) there are no
140operations that can be performed on the caught value, not even type inspection.
141Instead the base exception-type \code{C++}{std::exception} defines common
142functionality (such as
143the ability to describe the reason the exception was raised) and all
144exceptions have this functionality.
145That trade-off, restricting usable types to gain guaranteed functionality,
146is almost universal now, as without some common functionality it is almost
147impossible to actually handle any errors.
148
149Java was the next popular language to use exceptions.\cite{Java8}
150Its exception system largely reflects that of \Cpp, except that requires
151you throw a child type of \code{Java}{java.lang.Throwable}
152and it uses checked exceptions.
153Checked exceptions are part of a function's interface,
154the exception signature of the function.
155Every function that could be raised from a function, either directly or
156because it is not handled from a called function, is given.
157Using this information, it is possible to statically verify if any given
158exception is handled and guarantee that no exception will go unhandled.
159Making exception information explicit improves clarity and safety,
160but can slow down or restrict programming.
161For example, programming high-order functions becomes much more complex
162if the argument functions could raise exceptions.
163However, as odd it may seem, the worst problems are rooted in the simple
164inconvenience of writing and updating exception signatures.
165This has caused Java programmers to develop multiple programming ``hacks''
166to circumvent checked exceptions, negating their advantages.
167One particularly problematic example is the ``catch-and-ignore'' pattern,
168where an empty handler is used to handle an exception without doing any
169recovery or repair. In theory that could be good enough to properly handle
170the exception, but more often is used to ignore an exception that the       
171programmer does not feel is worth the effort of handling it, for instance if
172they do not believe it will ever be raised.
173If they are incorrect the exception will be silenced, while in a similar
174situation with unchecked exceptions the exception would at least activate   
175the language's unhandled exception code (usually program abort with an 
176error message).
177
178%\subsection
179Resumption exceptions are less popular,
180although resumption is as old as termination; hence, few
181programming languages have implemented them.
182% http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/parc/techReports/
183%   CSL-79-3_Mesa_Language_Manual_Version_5.0.pdf
184Mesa is one programming language that did.\cite{Mesa} Experience with Mesa
185is quoted as being one of the reasons resumptions were not
186included in the \Cpp standard.
187% https://en.wikipedia.org/wiki/Exception_handling
188Since then resumptions have been ignored in main-stream programming languages.
189However, resumption is being revisited in the context of decades of other
190developments in programming languages.
191While rejecting resumption may have been the right decision in the past,
192the situation has changed since then.
193Some developments, such as the function programming equivalent to resumptions,
194algebraic effects\cite{Zhang19}, are enjoying success.
195A complete reexamination of resumptions is beyond this thesis,
196but there reemergence is enough to try them in \CFA.
197% Especially considering how much easier they are to implement than
198% termination exceptions and how much Peter likes them.
199
200%\subsection
201Functional languages tend to use other solutions for their primary error
202handling mechanism, but exception-like constructs still appear.
203Termination appears in the error construct, which marks the result of an
204expression as an error; then the result of any expression that tries to use
205it also results in an error, and so on until an appropriate handler is reached.
206Resumption appears in algebraic effects, where a function dispatches its
207side-effects to its caller for handling.
208
209%\subsection
210More recently exceptions seem to be vanishing from newer programming
211languages, replaced by ``panic".
212In Rust, a panic is just a program level abort that may be implemented by
213unwinding the stack like in termination exception
214handling.\cite{RustPanicMacro}\cite{RustPanicModule}
215Go's panic through is very similar to a termination, except it only supports
216a catch-all by calling \code{Go}{recover()}, simplifying the interface at
217the cost of flexibility.\cite{Go:2021}
218
219%\subsection
220While exception handling's most common use cases are in error handling,
221here are some other ways to handle errors with comparisons with exceptions.
222\begin{itemize}
223\item\emph{Error Codes}:
224This pattern has a function return an enumeration (or just a set of fixed
225values) to indicate if an error has occurred and possibly which error it was.
226
227Error codes mix exceptional/error and normal values, enlarging the range of
228possible return values. This can be addressed with multiple return values
229(or a tuple) or a tagged union.
230However, the main issue with error codes is forgetting to check them,
231which leads to an error being quietly and implicitly ignored.
232Some new languages and tools will try to issue warnings when an error code
233is discarded to avoid this problem.
234Checking error codes also bloats the main execution path,
235especially if the error is not handled immediately hand has to be passed
236through multiple functions before it is addressed.
237
238\item\emph{Special Return with Global Store}:
239Similar to the error codes pattern but the function itself only returns
240that there was an error
241and store the reason for the error in a fixed global location.
242For example many routines in the C standard library will only return some
243error value (such as -1 or a null pointer) and the error code is written into
244the standard variable @errno@.
245
246This approach avoids the multiple results issue encountered with straight
247error codes but otherwise has the same disadvantages and more.
248Every function that reads or writes to the global store must agree on all
249possible errors and managing it becomes more complex with concurrency.
250
251\item\emph{Return Union}:
252This pattern replaces error codes with a tagged union.
253Success is one tag and the errors are another.
254It is also possible to make each possible error its own tag and carry its own
255additional information, but the two branch format is easy to make generic
256so that one type can be used everywhere in error handling code.
257
258This pattern is very popular in any functional or semi-functional language
259with primitive support for tagged unions (or algebraic data types).
260% We need listing Rust/rust to format code snippets from it.
261% Rust's \code{rust}{Result<T, E>}
262The main advantage is that an arbitrary object can be used to represent an
263error so it can include a lot more information than a simple error code.
264The disadvantages include that the it does have to be checked along the main
265execution and if there aren't primitive tagged unions proper usage can be
266hard to enforce.
267
268\item\emph{Handler Functions}:
269This pattern associates errors with functions.
270On error, the function that produced the error calls another function to
271handle it.
272The handler function can be provided locally (passed in as an argument,
273either directly as as a field of a structure/object) or globally (a global
274variable).
275C++ uses this approach as its fallback system if exception handling fails,
276such as \snake{std::terminate_handler} and, for a time,
277\snake{std::unexpected_handler}.
278
279Handler functions work a lot like resumption exceptions,
280but without the dynamic search for a handler.
281Since setting up the handler can be more complex/expensive,
282especially when the handler has to be passed through multiple layers of
283function calls, but cheaper (constant time) to call,
284they are more suited to more frequent (less exceptional) situations.
285\end{itemize}
286
287%\subsection
288Because of their cost, exceptions are rarely used for hot paths of execution.
289Hence, there is an element of self-fulfilling prophecy as implementation
290techniques have been focused on making them cheap to set-up,
291happily making them expensive to use in exchange.
292This difference is less important in higher-level scripting languages,
293where using exception for other tasks is more common.
294An iconic example is Python's
295\code{Python}{StopIteration}\cite{PythonExceptions} exception that
296is thrown by an iterator to indicate that it is exhausted.
297When paired with Python's iterator-based for-loop this will be thrown every
298time the end of the loop is reached.\cite{PythonForLoop}
Note: See TracBrowser for help on using the repository browser.