source: doc/proposals/exceptions.md@ 8136df1

Last change on this file since 8136df1 was b1f225e5, checked in by Andrew Beach <ajbeach@…>, 5 months ago

Wrote up a document describing problems with the current exception/virtual system.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1Exception Update Proposal
2=========================
3
4Exceptions have pretty constant since the end of Andrew's project (*), with
5the one major addition being some convenience macros. Experience, though, has
6highlighted problems, particular some difficult to understand sections.
7
8(* I'm Andrew, I am writing this in third person so other people can update
9 it easily, but I'm not beating on myself.)
10
11A lot of this should be viewed in the context of the "Proposal For Use of
12Virtual Tables" (see `vtable.md`), and will refer to parts of it. In fact,
13a lot of what to be discussed about exceptions is actually how it uses
14that proposal, and at the same time, enabling exceptions is the primary
15motivation behind virtual tables, with others being largely abstract.
16
17Note that the following problem areas are also inter-related with each other,
18the virtual table code (as above) and the exception feature list.
19
20Type/Function Binding
21---------------------
22Exceptions (and the virtual table system) attempt to use the location based
23binding like the rest of Cforall. However, because exceptions are created and
24used in very different places, without stepping through all the intermediate
25locations. This is the largest user issue the system faces right now.
26
27The full list of things you have to do:
28+ Define the structure (in the header).
29+ Implement the required functions (in implementation).
30+ Forward declare a virtual table instance (in the header).
31+ Define the virtual table (in implementation).
32+ Pass in the table reference to a constructed exception (at usage).
33
34Even this example has some automation. For example, defining the virtual
35table automatically defines some of the associated functions. This means that
36you cannot control the implementation of those functions.
37
38Helper macros have been plastered all over this process to try and reduce
39the number of steps. It is annoying, repetitive and error prone. It does open
40up new options for customization, similar to call-site binding, but this does
41not get used very often (as of yet, no examples have come up naturally).
42
43It turns out that you usually, almost always even, want a single binding
44between a type and its implementing function. Call-site binding has some
45similar issues, but the extra work for the flexibility is almost entirely
46on the compiler. (See Stack Unwinding for information on why we can't just
47resolve at the throw site.) We have also currently fixed implementations for
48that one binding because of all the short-cut.
49
50There are a couple of directions to go with this, but the root cause is just
51that contextual binding does not work great with large shifts in context.
52There are a couple of ways
53+ Add universal (non-contextual) type/function binding. If a given type
54 always have the same assertions associated with it, which then must be
55 static, this problem goes away. This is a slight loss of functionality,
56 but is the strategy used by most type-class systems as well as in
57 object-orientated programming, which fits well with exceptions.
58+ Improve the user interface. It may not be a logical change so much as
59 just a user interface improvement to the system. The limits around
60 life-time, memory allocation and resolution timing remain, but new tools
61 could at least make the simple use cases easier and less error prone.
62+ Remove the need for a stable binding entirely. This would allow the
63 contextual binding to be used as it is in the rest of Cforall. However,
64 it would likely require the largest changes to exceptions. It would be
65 something like separately resolving the assertions at both sites.
66
67Stack Unwinding and Lifetime
68----------------------------
69Termination exceptions unwind the stack between the throw and the catch.
70This runs all the destructors and releases stored memory. The memory used
71by an exception must remain in scope past the unwind while the handler is
72run.
73
74There are two main ways to make sure memory/data remains live. First, is to
75make sure that the data already has a sufficient life-time. Because it is
76usually not known where an exception will be caught, that usually just means
77something with a static life-time. The second option is to manually extend
78the life-time by copying the data. Most exception handling mechanisms (EHMs)
79use both of these, copying some core data around that might refer to out to
80static information (usually code).
81
82The problem in Cforall, assertions can often be in neither of these areas.
83While the value of the assertion itself is a local value that could be
84copied around, but they often refer to stack allocated thunks, created when
85a polymorphic function was specialized (monomorphized) to a less polymorphic
86form. These are not static and we don't have the layout information to copy
87them either.
88
89The explicit virtual tables is an attempt to address this, because they
90create a minimum on the life-time of the assertions and thunks. This still
91could be unwound if the table is on the stack, but it explicitly shows where
92that limit is, unlike the automatic monomorphiation.
93
94This problem is really dependant on the constraints on it. There are minor
95improvements to be made, however large improvements may only be possible
96by changing the problem. Making non-contextual bindings
97(see Type/Function Bindings) means the information can be static which could
98allow it to be automatically located and reduce the issue.
99
100The only way to remove the life-time limit would be to avoid unwinding the
101stack. If the exception handling code only removes stack frames during
102clean-up, most of these problems go away.
103Resumption exceptions already does this. Termination exceptions might be able
104to work if you unwind after the handler runs.
105
106Exception Matching and Hierarchy
107--------------------------------
108When exceptions are caught, the primary tool to see if a given handler
109should handle a given exception is hierarchical matching.
110
111In terms of the underlying paradigms, this is the most fundamental mismatch,
112because it is borrowed from object-orientated programming, and Cforall is not
113an object-orientated programming language. But we added a limited system that
114mimics that, the virtual type hierarchy, and currently exceptions are the
115only supported use of that system. Also it isn't entirely implemented and
116would require a lot of features with relatively narrow use cases to implement it.
117
118Which does make updating it based on experience a bit harder, so far the only
119real problem is allocating memory in the header. (Currently addressed by the
120cfa_linkonce attribute.) But the missing implementation highlights that maybe
121we don't need the full hierarchy.
122
123If you can handle the exception fully, you can catch the leaf exception and
124run the handling code. If it doesn't matter because the guarded code is
125isolated, then you catch any exception, log it, and then move on.
126In other words, without the hierarchy and just exact matches and a separate
127catch all, that could handle the vast majority of cases.
128
129Even within this solution, there are variants in what do these two cases
130look like. The exact match case is fairly simple, it may not even have to
131pass assertions because the concrete type is known at both locations.
132The catch-all case is the tricky one, because we still have to manipulate
133the exception in a generic form. It does however mean there is a single
134generic interface in that case, which might still be simpler than the current
135system.
136
137(Also in this two layer system, it might also be worth revisiting checked
138exceptions for the exact match cases, because there is a more direct than
139usual logical binding there.)
Note: See TracBrowser for help on using the repository browser.