Changeset 692f0c8


Ignore:
Timestamp:
May 4, 2021, 12:21:15 PM (3 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
c0c940a
Parents:
403f287
Message:

proofread implementation chapter

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/implement.tex

    r403f287 r692f0c8  
    1414
    1515\subsection{Virtual Type}
    16 Virtual types only have one change to their structure, the addition of a
    17 pointer to the virtual table. This is always the first field so that
    18 if it is cast to a supertype the field's location is still known.
    19 
    20 This field is set as part of all new generated constructors.
     16Virtual types only have one change to their structure: the addition of a
     17pointer to the virtual table, called the \emph{virtual-table pointer}.
     18Internally, the field is called
     19@virtual_table@.
     20This constant pointer is always the first field of the table so when
     21casting to a supertype, the field's location is always known.
     22The field is initialized as part of all generated constructors.
    2123\todo{They only come as part exceptions and don't work.}
    22 After the object is created the field is constant.
    23 
    24 However it can be read from, internally it is just a regular field called
    25 @virtual_table@. Dereferencing it gives the virtual table and access to the
     24%After the object is created the field is constant.
     25Dereferencing it gives the virtual table and access to the
    2626type's virtual members.
    2727
    2828\subsection{Virtual Table}
    29 Every time a virtual type is defined the new virtual table type must also be
    30 defined.
    31 
    32 The unique instance is important because the address of the virtual table
    33 instance is used as the identifier for the virtual type. So a pointer to the
    34 virtual table and the ID for the virtual type are interchangable.
     29% PAB: These 2 paragraphs are repeated below, and maybe some of the paragraph above, too.
     30\begin{comment}
     31Every time a virtual type is defined, a new virtual table-type is
     32instantiated.
     33The uniqueness of the virtual-table
     34instance is important because its address
     35is used as the identifier for the virtual type. Hence, a pointer to the
     36virtual table and the ID for the virtual type are interchangeable.
    3537\todo{Unique instances might be going so we will have to talk about the new
    3638system instead.}
    3739
    38 The first step in putting it all together is to create the virtual table type.
    39 The virtual table type is just a structure and can be described in terms of
    40 its fields. The first field is always the parent type ID (or a pointer to
    41 the parent virtual table) or 0 (the null pointer).
    42 Next are other fields on the parent virtual table are repeated.
    43 Finally are the fields used to store any new virtual members of the new
    44 The virtual type
    45 
    46 The virtual system is accessed through a private constant field inserted at the
    47 beginning of every virtual type, called the virtual-table pointer. This field
    48 points at a type's virtual table and is assigned during the object's
    49 construction. The address of a virtual table acts as the unique identifier for
     40The first step is creating the virtual-table type.
     41The virtual-table type is a structure and is described in terms of
     42its fields. The first field contains the parent-type ID (or a pointer to
     43the parent virtual-table) or 0 (null pointer).
     44Next are repeated fields from on the parent virtual-table.
     45Finally, the fields used to store any new virtual members of the new
     46the virtual type.
     47\end{comment}
     48
     49%The virtual system is accessed through a private constant field inserted at the
     50%beginning of every virtual type. This field
     51The virtual-table pointer
     52points at a type's virtual table (see Figure~\vref{f:VirtualTableLayout}).
     53%and is assigned during the object's
     54%construction.
     55The address of a virtual table acts as the unique identifier for
    5056the virtual type, and the first field of a virtual table is a pointer to the
    51 parent virtual-table or @0p@. The remaining fields are duplicated from the
     57parent virtual-table or @0p@ (null pointer). The remaining fields are duplicated from the
    5258parent tables in this type's inheritance chain, followed by any fields this type
    53 introduces. Parent fields are duplicated so they can be changed (all virtual
    54 members are overridable), so that references to the dispatched type
     59introduces. Parent fields are duplicated so they can be changed, \ie all virtual
     60members are overridable, while the parent pointer allows access to the original values.
     61Hence, references to the dispatched type
    5562are replaced with the current virtual type.
    5663% These are always taken by pointer or reference.
    5764
     65\begin{figure}
    5866% Simple ascii diragram:
    59 \begin{verbatim}
    60 parent_pointer  \
    61 parent_field0   |
    62 ...             | Same layout as parent.
    63 parent_fieldN   /
    64 child_field0
     67\begin{cfa}
     68parent_pointer  // \C{parent pointer to access its fields}
     69parent_field0   // \C{same layout as parent to allow replacement}
     70...
     71parent_fieldN
     72child_field0    // \C{new types for this virtual table}
    6573...
    6674child_fieldN
    67 \end{verbatim}
    68 \todo{Refine the diagram}
     75size
     76alignment
     77\end{cfa}
     78%\todo{Refine the diagram}
     79\caption{Virtual Table Layout}
     80\label{f:VirtualTableLayout}
     81\end{figure}
    6982
    7083% For each virtual type, a virtual table is constructed. This is both a new type
     
    7386% the type and the instance.
    7487
    75 A virtual table is created when the virtual type is created. The name of the
     88\begin{comment}
     89PAB: seems to be said already.
     90A virtual table is created when a virtual type is created. The name of the
    7691type is created by mangling the name of the base type. The name of the instance
    7792is also generated by name mangling. The fields are initialized automatically.
    7893The parent field is initialized by getting the type of the parent field and
    79 using that to calculate the mangled name of the parent's virtual table type.
     94using that to calculate the mangled name of the parent's virtual-table type.
     95\end{comment}
    8096There are two special fields that are included like normal fields but have
    8197special initialization rules: the @size@ field is the type's size and is
     
    86102
    87103These operations are split up into several groups depending on where they take
    88 place which varies for monomorphic and polymorphic types. The first devision is
     104place, which varies for monomorphic and polymorphic types. The first devision is
    89105between the declarations and the definitions. Declarations, such as a function
    90 signature or a aggregate's name, must always be visible but may be repeated in
     106signature or an aggregate's name, must always be visible but may be repeated in
    91107the form of forward declarations in headers. Definitions, such as function
    92108bodies and a aggregate's layout, can be separately compiled but must occur
    93109exactly once in a source file.
    94110
    95 \begin{sloppypar}
    96 The declarations include the virtual type definition and forward declarations
    97 of the virtual table instance, constructor, message function and
     111The declarations include the virtual-type definition and forward declarations
     112of the virtual-table instance, constructor, message function and
    98113@get_exception_vtable@. The definition includes the storage and initialization
    99114of the virtual table instance and the bodies of the three functions.
    100 \end{sloppypar}
    101 
    102 Monomorphic instances put all of these two groups in one place each.
    103 Polymorphic instances also split out the core declarations and definitions from
    104 the per-instance information. The virtual table type and most of the functions
    105 are polymorphic so they are all part of the core. The virtual table instance
    106 and the @get_exception_vtable@ function.
    107 
    108 \begin{sloppypar}
     115
     116Monomorphic instances put all of these two groups in one place.
     117Polymorphic instances split out the core declarations and definitions from
     118the per-instance information. The virtual-table type and most of the functions
     119are polymorphic so they are all part of the core. The virtual-table instance
     120and the @get_exception_vtable@ function \PAB{ are ...}.
     121
    109122Coroutines and threads need instances of @CoroutineCancelled@ and
    110123@ThreadCancelled@ respectively to use all of their functionality. When a new
    111 data type is declared with @coroutine@ or @thread@ the forward declaration for
     124data type is declared with @coroutine@ or @thread@, the forward declaration for
    112125the instance is created as well. The definition of the virtual table is created
    113126at the definition of the main function.
    114 \end{sloppypar}
     127
     128\PAB{You need an example here to show what happens for this case.}
     129
    115130
    116131\subsection{Virtual Cast}
     
    121136The function is
    122137\begin{cfa}
    123 void * __cfa__virtual_cast(
    124         struct __cfa__parent_vtable const * parent,
     138void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent,
    125139        struct __cfa__parent_vtable const * const * child );
    126140\end{cfa}
    127 and it is implemented in the standard library. The structure reperents the
    128 head of a vtable which is the pointer to the parent virtual table. The
    129 @parent@ points directly at the parent type virtual table while the @child@
    130 points at the object of the (possibe) child type.
    131 
    132 In terms of the virtual cast expression, @parent@ comes from looking up the
     141and it is implemented in the standard library. The structure represents the
     142head of a virtual table, which is the pointer to the parent virtual table. The
     143@parent@ points directly at the parent-type virtual-table, while the @child@
     144points at the object of the (possible) child type.
     145
     146\PAB{Need a figure to show this relationship.}
     147
     148In terms of the virtual-cast expression, @parent@ comes from looking up the
    133149type being cast to and @child@ is the result of the expression being cast.
    134 Because the complier outputs C code, some type C type casts are also used.
    135 The last bit of glue is an map that saves every virtual type the compiler
    136 sees. This is used to check the type used in a virtual cast is a virtual
     150Because the complier outputs C code, some C-type casts are also used.
     151The last bit of glue is a map that saves every virtual type the compiler
     152sees. This table is used to check the type used in a virtual cast is a virtual
    137153type and to get its virtual table.
    138154(It also checks for conflicting definitions.)
    139155
    140 Inside the function it is a simple conditional. If the type repersented by
    141 @parent@ is or is an ancestor of the type repersented by @*child@ (it
    142 requires one more level of derefence to pass through the object) then @child@
     156\PAB{Can this be rolled into the figure above?}
     157
     158Inside the function is a simple conditional. If the type represented by
     159@parent@ is an ancestor of the type represented by @*child@ (it
     160requires one more level of dereference to pass through the object) then @child@
    143161is returned, otherwise the null pointer is returned.
    144162
    145 The check itself is preformed is a simple linear search. If the child
    146 virtual table or any of its ancestors (which are retreved through the first
    147 field of every virtual table) are the same as the parent virtual table then
     163The check is a simple linear search (like \Cpp RTTI). If the child
     164virtual table or any of its ancestors (which are retrieved through the first
     165field of every virtual table) are the same as the parent virtual-table then
    148166the cast succeeds.
    149167
     
    156174% resumption doesn't as well.
    157175
    158 % Many modern languages work with an interal stack that function push and pop
     176% Many modern languages work with an internal stack that function push and pop
    159177% their local data to. Stack unwinding removes large sections of the stack,
    160178% often across functions.
    161179
    162180Stack unwinding is the process of removing stack frames (activations) from the
    163 stack. On function entry and return, unwinding is handled directly by the code
    164 embedded in the function. Usually, the stack-frame size is known statically
     181stack. On function entry and return, unwinding is handled directly by the call/return code
     182embedded in a function. Usually, the stack-frame size is known statically
    165183based on parameter and local variable declarations. For dynamically-sized
    166 local variables, a runtime computation is necessary to know the frame
     184local variables.
     185(Often called a variable-length array or VLA, even when the variable type is an aggregate.)
     186For VLAs, a runtime computation is necessary to know the frame
    167187size. Finally, a function's frame-size may change during execution as local
    168 variables (static or dynamic sized) go in and out of scope.
     188variables (static or dynamic sized) go in and out of scope, which is a form of VLA.
    169189Allocating/deallocating stack space is usually an $O(1)$ operation achieved by
    170190bumping the hardware stack-pointer up or down as needed.
    171191
    172 Unwinding across multiple stack frames is more complex because individual stack
    173 management code associated with each frame is bypassed. That is, the location
     192Unwinding across multiple stack frames is more complex because individual stack-management
     193code associated with each frame can be bypassed. That is, the location
    174194of a function's frame-management code is largely unknown and dispersed
    175195throughout the function, hence the current frame size managed by that code is
     
    191211reseting to a snap-shot of an arbitrary but existing function frame on the
    192212stack. It is up to the programmer to ensure the snap-shot is valid when it is
    193 reset, making this unwinding approach fragile with potential errors that are
     213reset and that unwound frames do not have side-effects.
     214Hence, this unwinding approach is fragile with potential errors that are
    194215difficult to debug because the stack becomes corrupted.
    195216
    196 However, many languages define cleanup actions that must be taken when objects
    197 are deallocated from the stack or blocks end, such as running a variable's
    198 destructor or a @try@ statement's @finally@ clause. Handling these mechanisms
     217With respect to stack side-effects, many languages define cleanup actions that must be taken when objects
     218are deallocated from the stack, when the function of blocks within the function end, such as running a variable's
     219destructor or a @try@ statement's @finally@ clause.
     220The purpose of these side-effects is to reestablish the global state of the program, such as dynamic memory-allocation or file access.
     221Handling these side-effect mechanisms
    199222requires walking the stack and checking each stack frame for these potential
    200 actions.
    201 
    202 For exceptions, it must be possible to walk the stack frames in search of @try@
     223actions, where a frame can be any block with declarations.
     224
     225In languages like \Cpp and Java, it must be possible to walk the stack frames in search of @try@
    203226statements to match and execute a handler. For termination exceptions, it must
    204227also be possible to unwind all stack frames from the throw to the matching
    205 catch, and each of these frames must be checked for cleanup actions. Stack
     228catch (including the @try@ block), and each of these frames must be checked for cleanup actions. Stack
    206229walking is where most of the complexity and expense of exception handling
    207230appears.
     
    226249LSDA can contain any information but conventionally it is a table with entries
    227250representing regions of the function and what has to be done there during
    228 unwinding. These regions are bracketed by the instruction pointer. If the
     251unwinding. These regions are bracketed by instruction addresses. If the
    229252instruction pointer is within a region's start/end, then execution is currently
    230253executing in that region. Regions are used to mark out the scopes of objects
     
    238261
    239262The GCC compilation flag @-fexceptions@ causes the generation of an LSDA and
    240 attaches its personality function. However, this
     263attaches its personality function.
     264It attaches a series of opaque directives (@.cfi_personality@ directive)
     265used internally and not part of this work.
     266However, this
    241267flag only handles the cleanup attribute:
    242 \todo{Peter: What is attached? Andrew: It uses the .cfi\_personality directive
    243 and that's all I know.}
    244268\begin{cfa}
    245269void clean_up( int * var ) { ... }
    246270int avar __attribute__(( cleanup(clean_up) ));
    247271\end{cfa}
    248 which is used on a variable and specifies a function, in this case @clean_up@,
    249 run when the variable goes out of scope.
    250 The function is passed a pointer to the object being removed from the stack
    251 so it can be used to mimic destructors.
     272that is used on a variable and specifies a function, in this case @clean_up@,
     273run when the variable goes out of scope, which is used to mimic destructors.
    252274However, this feature cannot be used to mimic @try@ statements as it cannot
    253275control the unwinding.
     
    257279section covers some of the important parts of the interface.
    258280
    259 A personality function can preform different actions depending on how it is
     281A personality function can perform different actions depending on how it is
    260282called.
    261283\begin{lstlisting}[language=C,{moredelim=**[is][\color{red}]{@}{@}}]
     
    268290\end{lstlisting}
    269291The @action@ argument is a bitmask of possible actions:
    270 \begin{enumerate}
     292\begin{enumerate}[topsep=5pt]
    271293\item
    272294@_UA_SEARCH_PHASE@ specifies a search phase and tells the personality function
     
    291313@_UA_FORCE_UNWIND@ specifies a forced unwind call. Forced unwind only performs
    292314the cleanup phase and uses a different means to decide when to stop
    293 (see \vref{s:ForcedUnwind}).
     315(see Section~\vref{s:ForcedUnwind}).
    294316\end{enumerate}
    295317
    296318The @exception_class@ argument is a copy of the
    297319\lstinline[language=C]|exception|'s @exception_class@ field.
     320\PAB{Say more.}
    298321
    299322The \lstinline[language=C]|exception| argument is a pointer to the user
    300323provided storage object. It has two public fields, the exception class, which
    301 is actually just a number, identifying the exception handling mechanism that
     324is just a number, identifying the exception handling mechanism that
    302325created it, and the cleanup function. The cleanup function is called if
    303326required by the exception.
     
    309332that can be passed several places in libunwind. It includes a number of
    310333messages for special cases (some of which should never be used by the
    311 personality function) and error codes but unless otherwise noted the
     334personality function) and error codes. However, unless otherwise noted, the
    312335personality function should always return @_URC_CONTINUE_UNWIND@.
    313336
     
    324347@_URC_END_OF_STACK@.
    325348
    326 Second, when a handler is matched, raise exception continues onto the cleanup
     349Second, when a handler is matched, raise exception walks the stack again performing the cleanup
    327350phase.
    328351Once again, it calls the personality functions of each stack frame from newest
     
    338361Forced Unwind is the other central function in libunwind.
    339362\begin{cfa}
    340 _Unwind_Reason_Code _Unwind_ForcedUnwind( _Unwind_Exception *,
     363_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *,
    341364        _Unwind_Stop_Fn, void *);
    342365\end{cfa}
     
    380403Each stack must have its own exception context. In a sequential \CFA program,
    381404there is only one stack with a single global exception-context. However, when
    382 the library @libcfathread@ is linked, there are multiple stacks where each
     405the library @libcfathread@ is linked, there are multiple stacks, where each
    383406needs its own exception context.
    384407
    385 General access to the exception context is provided by function
    386 @this_exception_context@. For sequential execution, this function is defined as
     408The function @this_exception_context@ provides general access to the exception context.
     409For sequential execution, this function is defined as
    387410a weak symbol in the \CFA system-library, @libcfa@. When a \CFA program is
    388411concurrent, it links with @libcfathread@, where this function is defined with a
     
    390413
    391414The sequential @this_exception_context@ returns a hard-coded pointer to the
    392 global execption context.
     415global exception context.
    393416The concurrent version adds the exception context to the data stored at the
    394 base of each stack. When @this_exception_context@ is called it retrieves the
     417base of each stack. When @this_exception_context@ is called, it retrieves the
    395418active stack and returns the address of the context saved there.
    396419
     
    399422% catches. Talk about GCC nested functions.
    400423
    401 Termination exceptions use libunwind heavily because it matches the intended
    402 use from \Cpp exceptions closely. The main complication for \CFA is that the
     424Termination exceptions use libunwind heavily because \CFA termination exceptions match
     425\Cpp exceptions closely. The main complication for \CFA is that the
    403426compiler generates C code, making it very difficult to generate the assembly to
    404427form the LSDA for try blocks or destructors.
     
    407430The first step of a termination raise is to copy the exception into memory
    408431managed by the exception system. Currently, the system uses @malloc@, rather
    409 than reserved memory or the stack top. The exception handling mechanism manages
     432than reserved memory or the stack top. The exception-handling mechanism manages
    410433memory for the exception as well as memory for libunwind and the system's own
    411434per-exception storage.
    412435
    413 [Quick ASCII diagram to get started.]
     436\begin{figure}
    414437\begin{verbatim}
    415438Fixed Header  | _Unwind_Exception   <- pointer target
     
    420443              V ...
    421444\end{verbatim}
    422 
    423 Exceptions are stored in variable-sized blocks.
    424 The first component is a fixed sized data structure that contains the
     445\caption{Exception Layout}
     446\label{f:ExceptionLayout}
     447\end{figure}
     448
     449Exceptions are stored in variable-sized blocks (see Figure~\vref{f:ExceptionLayout}).
     450The first component is a fixed-sized data-structure that contains the
    425451information for libunwind and the exception system. The second component is an
    426452area of memory big enough to store the exception. Macros with pointer arthritic
     
    428454@_Unwind_Exception@ to the entire node.
    429455
    430 All of these nodes are linked together in a list, one list per stack, with the
     456Multiple exceptions can exist because handlers can call functions that raise
     457exceptions.  Figure~\vref{f:MultipleExceptions} shows a \Cpp program where
     458exceptions are handled, and then a function is called from the handler that
     459raises a new exception. The previous exception must persist because it is
     460unhandled, and hence, control can return to the handler and that exception is
     461reraised.
     462
     463\begin{figure}
     464\centering
     465\newsavebox{\myboxA}
     466\newsavebox{\myboxB}
     467\begin{lrbox}{\myboxA}
     468\begin{lstlisting}[language=C++,{moredelim=**[is][\color{red}]{@}{@}}]
     469struct E {};
     470int cnt = 3;
     471void f( int i ) {
     472        if ( i == 0 ) @throw E();@
     473        try {
     474                @f( i - 1 );@
     475        } catch( E ) { // handler h
     476                cnt -= 1;
     477                if ( cnt > 0 ) @f( 2 );@
     478        }
     479}
     480int main() { @f( 2 );@ }
     481\end{lstlisting}
     482\end{lrbox}
     483
     484\begin{lrbox}{\myboxB}
     485\begin{lstlisting}
     486h  $\makebox[0pt][l]{\textbackslash}f$
     487   f
     488   f
     489h  $\makebox[0pt][l]{\textbackslash}f$  throw E$\(_2\)$
     490   f
     491   f
     492h  $\makebox[0pt][l]{\textbackslash}f$  throw E$\(_1\)$
     493   f
     494   f
     495\end{lstlisting}
     496\end{lrbox}
     497
     498{\usebox\myboxA}
     499\hspace{25pt}
     500{\usebox\myboxB}
     501
     502\caption{Multiple Exceptions}
     503\label{f:MultipleExceptions}
     504\end{figure}
     505
     506In this case, the exception nodes are linked together in a list, one list per stack, with the
    431507list head stored in the exception context. Within each linked list, the most
    432508recently thrown exception is at the head followed by older thrown
     
    439515exception, the copy function, and the free function, so they are specific to an
    440516exception type. The size and copy function are used immediately to copy an
    441 exception into managed memory. After the exception is handled the free function
     517exception into managed memory. After the exception is handled, the free function
    442518is used to clean up the exception and then the entire node is passed to free
    443519so the memory can be given back to the heap.
     
    445521\subsection{Try Statements and Catch Clauses}
    446522The try statement with termination handlers is complex because it must
    447 compensate for the lack of assembly-code generated from \CFA. Libunwind
     523compensate for the lack of assembly code generated from \CFA. Libunwind
    448524requires an LSDA and personality function for control to unwind across a
    449525function. The LSDA in particular is hard to mimic in generated C code.
     
    454530calls them.
    455531Because this function is known and fixed (and not an arbitrary function that
    456 happens to contain a try statement) this means the LSDA can be generated ahead
     532happens to contain a try statement), this means the LSDA can be generated ahead
    457533of time.
    458534
    459535Both the LSDA and the personality function are set ahead of time using
    460 embedded assembly. This is handcrafted using C @asm@ statements and contains
    461 enough information for the single try statement the function repersents.
     536embedded assembly. This assembly code is handcrafted using C @asm@ statements and contains
     537enough information for the single try statement the function represents.
    462538
    463539The three functions passed to try terminate are:
     
    487563nested functions and all other functions besides @__cfaehm_try_terminate@ in
    488564\CFA use the GCC personality function and the @-fexceptions@ flag to generate
    489 the LSDA. This allows destructors to be implemented with the cleanup attribute.
     565the LSDA. Through this mechanism, \CFA destructors are implemented via the cleanup attribute.
     566
     567\PAB{Try to put together an example try statement illustrating these components.}
    490568
    491569\section{Resumption}
    492570% The stack-local data, the linked list of nodes.
    493571
    494 Resumption simple to implement because there is no stack unwinding. The
     572Resumption is simpler to implement than termination because there is no stack
     573unwinding.  \PAB{You need to explain how the \lstinline{catchResume} clauses are
     574handled. Do you use the personality mechanism in libunwind or do you roll your
     575own mechanism?}
     576
     577The
    495578resumption raise uses a list of nodes for its stack traversal. The head of the
    496579list is stored in the exception context. The nodes in the list have a pointer
    497580to the next node and a pointer to the handler function.
    498 
    499581A resumption raise traverses this list. At each node the handler function is
    500582called, passing the exception by pointer. It returns true if the exception is
     
    512594the stack
    513595already examined, is accomplished by updating the front of the list as the
    514 search continues. Before the handler at a node is called the head of the list
     596search continues. Before the handler at a node is called, the head of the list
    515597is updated to the next node of the current node. After the search is complete,
    516598successful or not, the head of the list is reset.
     
    521603the other handler checked up to this point are not checked again.
    522604
    523 This structure also supports new handler added while the resumption is being
     605This structure also supports new handlers added while the resumption is being
    524606handled. These are added to the front of the list, pointing back along the
    525607stack -- the first one points over all the checked handlers -- and the ordering
    526608is maintained.
     609
     610\PAB{Again, a figure to show how this works would be helpful.}
    527611
    528612\label{p:zero-cost}
     
    539623% that unwind is required knowledge for that chapter.
    540624
     625\PAB{This paragraph needs to be moved to the start of this Section, where I have have my other comment.}
     626
    541627\section{Finally}
    542628% Uses destructors and GCC nested functions.
    543 Finally clauses is placed into a GCC nested-function with a unique name, and no
     629A finally clause is placed into a GCC nested-function with a unique mangled name, and no
    544630arguments or return values. This nested function is then set as the cleanup
    545631function of an empty object that is declared at the beginning of a block placed
    546 around the context of the associated @try@ statement.
    547 
    548 The rest is handled by GCC. The try block and all handlers are inside the
     632around the context of an associated @try@ statement.
     633
     634The rest is handled by GCC. The try block and all handlers are inside this
    549635block. At completion, control exits the block and the empty object is cleaned
    550636up, which runs the function that contains the finally code.
     
    554640
    555641Cancellation also uses libunwind to do its stack traversal and unwinding,
    556 however it uses a different primary function @_Unwind_ForcedUnwind@. Details
    557 of its interface can be found in the \vref{s:ForcedUnwind}.
     642however it uses a different primary function, @_Unwind_ForcedUnwind@. Details
     643of its interface can be found in Section~\vref{s:ForcedUnwind}.
    558644
    559645The first step of cancellation is to find the cancelled stack and its type:
    560 coroutine or thread. Fortunately, the thread library stores the main thread
    561 pointer and the current thread pointer, and every thread stores a pointer to
    562 its main coroutine and the coroutine it is currently executing.
    563 
    564 So if the active thread's main and current coroutine are the same. If they
    565 are then the current stack is a thread stack, otherwise it is a coroutine
    566 stack. If it is a thread stack then an equality check with the stored main
    567 thread pointer and current thread pointer is enough to tell if the current
    568 thread is the main thread or not.
    569 
     646coroutine or thread. Fortunately, the thread library stores the program-main thread
     647pointer and the current-thread pointer, and every thread stores a pointer to
     648the current coroutine it is executing.
     649
     650\PAB{I don't know if my corrections in the previous paragraph are correct.}
     651
     652When the active thread and coroutine are the same, the current stack is the thread stack, otherwise it is a coroutine
     653stack.
     654% PAB: repeated?
     655% If it is a thread stack, then an equality check with the stored main
     656% thread pointer and current thread pointer is enough to tell if the current
     657% thread is the main thread or not.
    570658However, if the threading library is not linked, the sequential execution is on
    571659the main stack. Hence, the entire check is skipped because the weak-symbol
     
    575663Regardless of how the stack is chosen, the stop function and parameter are
    576664passed to the forced-unwind function. The general pattern of all three stop
    577 functions is the same: they continue unwinding until the end of stack when they
    578 do there primary work.
    579 
     665functions is the same: continue unwinding until the end of stack.
     666%when they
     667%do there primary work.
    580668For main stack cancellation, the transfer is just a program abort.
    581669
    582 For coroutine cancellation, the exception is stored on the coroutine's stack,
     670For coroutine cancellation, the exception is stored in the coroutine's stack,
    583671and the coroutine context switches to its last resumer. The rest is handled on
    584672the backside of the resume, which check if the resumed coroutine is
Note: See TracChangeset for help on using the changeset viewer.