Changeset 0c4df43


Ignore:
Timestamp:
May 4, 2021, 2:04:26 PM (17 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
9d7e5cb
Parents:
1716e1c
Message:

Revert "proofread implementation chapter", I've copied out the changes.

This reverts commit 692f0c895772f0dbe0cfe4f849661f820c7bc5eb.

File:
1 edited

Legend:

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

    r1716e1c r0c4df43  
    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, called the \emph{virtual-table pointer}.
    18 Internally, the field is called
    19 @virtual_table@.
    20 This constant pointer is always the first field of the table so when
    21 casting to a supertype, the field's location is always known.
    22 The field is initialized as part of all generated constructors.
     16Virtual types only have one change to their structure, the addition of a
     17pointer to the virtual table. This is always the first field so that
     18if it is cast to a supertype the field's location is still known.
     19
     20This field is set as part of all new generated constructors.
    2321\todo{They only come as part exceptions and don't work.}
    24 %After the object is created the field is constant.
    25 Dereferencing it gives the virtual table and access to the
     22After the object is created the field is constant.
     23
     24However 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
    2626type's virtual members.
    2727
    2828\subsection{Virtual Table}
    29 % PAB: These 2 paragraphs are repeated below, and maybe some of the paragraph above, too.
    30 \begin{comment}
    31 Every time a virtual type is defined, a new virtual table-type is
    32 instantiated.
    33 The uniqueness of the virtual-table
    34 instance is important because its address
    35 is used as the identifier for the virtual type. Hence, a pointer to the
    36 virtual table and the ID for the virtual type are interchangeable.
     29Every time a virtual type is defined the new virtual table type must also be
     30defined.
     31
     32The unique instance is important because the address of the virtual table
     33instance is used as the identifier for the virtual type. So a pointer to the
     34virtual table and the ID for the virtual type are interchangable.
    3735\todo{Unique instances might be going so we will have to talk about the new
    3836system instead.}
    3937
    40 The first step is creating the virtual-table type.
    41 The virtual-table type is a structure and is described in terms of
    42 its fields. The first field contains the parent-type ID (or a pointer to
    43 the parent virtual-table) or 0 (null pointer).
    44 Next are repeated fields from on the parent virtual-table.
    45 Finally, the fields used to store any new virtual members of the new
    46 the 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
    51 The virtual-table pointer
    52 points at a type's virtual table (see Figure~\vref{f:VirtualTableLayout}).
    53 %and is assigned during the object's
    54 %construction.
    55 The address of a virtual table acts as the unique identifier for
     38The first step in putting it all together is to create the virtual table type.
     39The virtual table type is just a structure and can be described in terms of
     40its fields. The first field is always the parent type ID (or a pointer to
     41the parent virtual table) or 0 (the null pointer).
     42Next are other fields on the parent virtual table are repeated.
     43Finally are the fields used to store any new virtual members of the new
     44The virtual type
     45
     46The virtual system is accessed through a private constant field inserted at the
     47beginning of every virtual type, called the virtual-table pointer. This field
     48points at a type's virtual table and is assigned during the object's
     49construction. The address of a virtual table acts as the unique identifier for
    5650the virtual type, and the first field of a virtual table is a pointer to the
    57 parent virtual-table or @0p@ (null pointer). The remaining fields are duplicated from the
     51parent virtual-table or @0p@. The remaining fields are duplicated from the
    5852parent tables in this type's inheritance chain, followed by any fields this type
    59 introduces. Parent fields are duplicated so they can be changed, \ie all virtual
    60 members are overridable, while the parent pointer allows access to the original values.
    61 Hence, references to the dispatched type
     53introduces. Parent fields are duplicated so they can be changed (all virtual
     54members are overridable), so that references to the dispatched type
    6255are replaced with the current virtual type.
    6356% These are always taken by pointer or reference.
    6457
    65 \begin{figure}
    6658% Simple ascii diragram:
    67 \begin{cfa}
    68 parent_pointer  // \C{parent pointer to access its fields}
    69 parent_field0   // \C{same layout as parent to allow replacement}
    70 ...
    71 parent_fieldN
    72 child_field0    // \C{new types for this virtual table}
     59\begin{verbatim}
     60parent_pointer  \
     61parent_field0   |
     62...             | Same layout as parent.
     63parent_fieldN   /
     64child_field0
    7365...
    7466child_fieldN
    75 size
    76 alignment
    77 \end{cfa}
    78 %\todo{Refine the diagram}
    79 \caption{Virtual Table Layout}
    80 \label{f:VirtualTableLayout}
    81 \end{figure}
     67\end{verbatim}
     68\todo{Refine the diagram}
    8269
    8370% For each virtual type, a virtual table is constructed. This is both a new type
     
    8673% the type and the instance.
    8774
    88 \begin{comment}
    89 PAB: seems to be said already.
    90 A virtual table is created when a virtual type is created. The name of the
     75A virtual table is created when the virtual type is created. The name of the
    9176type is created by mangling the name of the base type. The name of the instance
    9277is also generated by name mangling. The fields are initialized automatically.
    9378The parent field is initialized by getting the type of the parent field and
    94 using that to calculate the mangled name of the parent's virtual-table type.
    95 \end{comment}
     79using that to calculate the mangled name of the parent's virtual table type.
    9680There are two special fields that are included like normal fields but have
    9781special initialization rules: the @size@ field is the type's size and is
     
    10286
    10387These operations are split up into several groups depending on where they take
    104 place, which varies for monomorphic and polymorphic types. The first devision is
     88place which varies for monomorphic and polymorphic types. The first devision is
    10589between the declarations and the definitions. Declarations, such as a function
    106 signature or an aggregate's name, must always be visible but may be repeated in
     90signature or a aggregate's name, must always be visible but may be repeated in
    10791the form of forward declarations in headers. Definitions, such as function
    10892bodies and a aggregate's layout, can be separately compiled but must occur
    10993exactly once in a source file.
    11094
    111 The declarations include the virtual-type definition and forward declarations
    112 of the virtual-table instance, constructor, message function and
     95\begin{sloppypar}
     96The declarations include the virtual type definition and forward declarations
     97of the virtual table instance, constructor, message function and
    11398@get_exception_vtable@. The definition includes the storage and initialization
    11499of the virtual table instance and the bodies of the three functions.
    115 
    116 Monomorphic instances put all of these two groups in one place.
    117 Polymorphic instances split out the core declarations and definitions from
    118 the per-instance information. The virtual-table type and most of the functions
    119 are polymorphic so they are all part of the core. The virtual-table instance
    120 and the @get_exception_vtable@ function \PAB{ are ...}.
    121 
     100\end{sloppypar}
     101
     102Monomorphic instances put all of these two groups in one place each.
     103Polymorphic instances also split out the core declarations and definitions from
     104the per-instance information. The virtual table type and most of the functions
     105are polymorphic so they are all part of the core. The virtual table instance
     106and the @get_exception_vtable@ function.
     107
     108\begin{sloppypar}
    122109Coroutines and threads need instances of @CoroutineCancelled@ and
    123110@ThreadCancelled@ respectively to use all of their functionality. When a new
    124 data type is declared with @coroutine@ or @thread@, the forward declaration for
     111data type is declared with @coroutine@ or @thread@ the forward declaration for
    125112the instance is created as well. The definition of the virtual table is created
    126113at the definition of the main function.
    127 
    128 \PAB{You need an example here to show what happens for this case.}
    129 
     114\end{sloppypar}
    130115
    131116\subsection{Virtual Cast}
     
    136121The function is
    137122\begin{cfa}
    138 void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent,
     123void * __cfa__virtual_cast(
     124        struct __cfa__parent_vtable const * parent,
    139125        struct __cfa__parent_vtable const * const * child );
    140126\end{cfa}
    141 and it is implemented in the standard library. The structure represents the
    142 head 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@
    144 points at the object of the (possible) child type.
    145 
    146 \PAB{Need a figure to show this relationship.}
    147 
    148 In terms of the virtual-cast expression, @parent@ comes from looking up the
     127and it is implemented in the standard library. The structure reperents the
     128head 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@
     130points at the object of the (possibe) child type.
     131
     132In terms of the virtual cast expression, @parent@ comes from looking up the
    149133type being cast to and @child@ is the result of the expression being cast.
    150 Because the complier outputs C code, some C-type casts are also used.
    151 The last bit of glue is a map that saves every virtual type the compiler
    152 sees. This table is used to check the type used in a virtual cast is a virtual
     134Because the complier outputs C code, some type C type casts are also used.
     135The last bit of glue is an map that saves every virtual type the compiler
     136sees. This is used to check the type used in a virtual cast is a virtual
    153137type and to get its virtual table.
    154138(It also checks for conflicting definitions.)
    155139
    156 \PAB{Can this be rolled into the figure above?}
    157 
    158 Inside the function is a simple conditional. If the type represented by
    159 @parent@ is an ancestor of the type represented by @*child@ (it
    160 requires one more level of dereference to pass through the object) then @child@
     140Inside 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
     142requires one more level of derefence to pass through the object) then @child@
    161143is returned, otherwise the null pointer is returned.
    162144
    163 The check is a simple linear search (like \Cpp RTTI). If the child
    164 virtual table or any of its ancestors (which are retrieved through the first
    165 field of every virtual table) are the same as the parent virtual-table then
     145The check itself is preformed is a simple linear search. If the child
     146virtual table or any of its ancestors (which are retreved through the first
     147field of every virtual table) are the same as the parent virtual table then
    166148the cast succeeds.
    167149
     
    174156% resumption doesn't as well.
    175157
    176 % Many modern languages work with an internal stack that function push and pop
     158% Many modern languages work with an interal stack that function push and pop
    177159% their local data to. Stack unwinding removes large sections of the stack,
    178160% often across functions.
    179161
    180162Stack unwinding is the process of removing stack frames (activations) from the
    181 stack. On function entry and return, unwinding is handled directly by the call/return code
    182 embedded in a function. Usually, the stack-frame size is known statically
     163stack. On function entry and return, unwinding is handled directly by the code
     164embedded in the function. Usually, the stack-frame size is known statically
    183165based on parameter and local variable declarations. For dynamically-sized
    184 local variables.
    185 (Often called a variable-length array or VLA, even when the variable type is an aggregate.)
    186 For VLAs, a runtime computation is necessary to know the frame
     166local variables, a runtime computation is necessary to know the frame
    187167size. Finally, a function's frame-size may change during execution as local
    188 variables (static or dynamic sized) go in and out of scope, which is a form of VLA.
     168variables (static or dynamic sized) go in and out of scope.
    189169Allocating/deallocating stack space is usually an $O(1)$ operation achieved by
    190170bumping the hardware stack-pointer up or down as needed.
    191171
    192 Unwinding across multiple stack frames is more complex because individual stack-management
    193 code associated with each frame can be bypassed. That is, the location
     172Unwinding across multiple stack frames is more complex because individual stack
     173management code associated with each frame is bypassed. That is, the location
    194174of a function's frame-management code is largely unknown and dispersed
    195175throughout the function, hence the current frame size managed by that code is
     
    211191reseting to a snap-shot of an arbitrary but existing function frame on the
    212192stack. It is up to the programmer to ensure the snap-shot is valid when it is
    213 reset and that unwound frames do not have side-effects.
    214 Hence, this unwinding approach is fragile with potential errors that are
     193reset, making this unwinding approach fragile with potential errors that are
    215194difficult to debug because the stack becomes corrupted.
    216195
    217 With respect to stack side-effects, many languages define cleanup actions that must be taken when objects
    218 are deallocated from the stack, when the function of blocks within the function end, such as running a variable's
    219 destructor or a @try@ statement's @finally@ clause.
    220 The purpose of these side-effects is to reestablish the global state of the program, such as dynamic memory-allocation or file access.
    221 Handling these side-effect mechanisms
     196However, many languages define cleanup actions that must be taken when objects
     197are deallocated from the stack or blocks end, such as running a variable's
     198destructor or a @try@ statement's @finally@ clause. Handling these mechanisms
    222199requires walking the stack and checking each stack frame for these potential
    223 actions, where a frame can be any block with declarations.
    224 
    225 In languages like \Cpp and Java, it must be possible to walk the stack frames in search of @try@
     200actions.
     201
     202For exceptions, it must be possible to walk the stack frames in search of @try@
    226203statements to match and execute a handler. For termination exceptions, it must
    227204also be possible to unwind all stack frames from the throw to the matching
    228 catch (including the @try@ block), and each of these frames must be checked for cleanup actions. Stack
     205catch, and each of these frames must be checked for cleanup actions. Stack
    229206walking is where most of the complexity and expense of exception handling
    230207appears.
     
    249226LSDA can contain any information but conventionally it is a table with entries
    250227representing regions of the function and what has to be done there during
    251 unwinding. These regions are bracketed by instruction addresses. If the
     228unwinding. These regions are bracketed by the instruction pointer. If the
    252229instruction pointer is within a region's start/end, then execution is currently
    253230executing in that region. Regions are used to mark out the scopes of objects
     
    261238
    262239The GCC compilation flag @-fexceptions@ causes the generation of an LSDA and
    263 attaches its personality function.
    264 It attaches a series of opaque directives (@.cfi_personality@ directive)
    265 used internally and not part of this work.
    266 However, this
     240attaches its personality function. However, this
    267241flag only handles the cleanup attribute:
     242\todo{Peter: What is attached? Andrew: It uses the .cfi\_personality directive
     243and that's all I know.}
    268244\begin{cfa}
    269245void clean_up( int * var ) { ... }
    270246int avar __attribute__(( cleanup(clean_up) ));
    271247\end{cfa}
    272 that is used on a variable and specifies a function, in this case @clean_up@,
    273 run when the variable goes out of scope, which is used to mimic destructors.
     248which is used on a variable and specifies a function, in this case @clean_up@,
     249run when the variable goes out of scope.
     250The function is passed a pointer to the object being removed from the stack
     251so it can be used to mimic destructors.
    274252However, this feature cannot be used to mimic @try@ statements as it cannot
    275253control the unwinding.
     
    279257section covers some of the important parts of the interface.
    280258
    281 A personality function can perform different actions depending on how it is
     259A personality function can preform different actions depending on how it is
    282260called.
    283261\begin{lstlisting}[language=C,{moredelim=**[is][\color{red}]{@}{@}}]
     
    290268\end{lstlisting}
    291269The @action@ argument is a bitmask of possible actions:
    292 \begin{enumerate}[topsep=5pt]
     270\begin{enumerate}
    293271\item
    294272@_UA_SEARCH_PHASE@ specifies a search phase and tells the personality function
     
    313291@_UA_FORCE_UNWIND@ specifies a forced unwind call. Forced unwind only performs
    314292the cleanup phase and uses a different means to decide when to stop
    315 (see Section~\vref{s:ForcedUnwind}).
     293(see \vref{s:ForcedUnwind}).
    316294\end{enumerate}
    317295
    318296The @exception_class@ argument is a copy of the
    319297\lstinline[language=C]|exception|'s @exception_class@ field.
    320 \PAB{Say more.}
    321298
    322299The \lstinline[language=C]|exception| argument is a pointer to the user
    323300provided storage object. It has two public fields, the exception class, which
    324 is just a number, identifying the exception handling mechanism that
     301is actually just a number, identifying the exception handling mechanism that
    325302created it, and the cleanup function. The cleanup function is called if
    326303required by the exception.
     
    332309that can be passed several places in libunwind. It includes a number of
    333310messages for special cases (some of which should never be used by the
    334 personality function) and error codes. However, unless otherwise noted, the
     311personality function) and error codes but unless otherwise noted the
    335312personality function should always return @_URC_CONTINUE_UNWIND@.
    336313
     
    347324@_URC_END_OF_STACK@.
    348325
    349 Second, when a handler is matched, raise exception walks the stack again performing the cleanup
     326Second, when a handler is matched, raise exception continues onto the cleanup
    350327phase.
    351328Once again, it calls the personality functions of each stack frame from newest
     
    361338Forced Unwind is the other central function in libunwind.
    362339\begin{cfa}
    363 _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *,
     340_Unwind_Reason_Code _Unwind_ForcedUnwind( _Unwind_Exception *,
    364341        _Unwind_Stop_Fn, void *);
    365342\end{cfa}
     
    403380Each stack must have its own exception context. In a sequential \CFA program,
    404381there is only one stack with a single global exception-context. However, when
    405 the library @libcfathread@ is linked, there are multiple stacks, where each
     382the library @libcfathread@ is linked, there are multiple stacks where each
    406383needs its own exception context.
    407384
    408 The function @this_exception_context@ provides general access to the exception context.
    409 For sequential execution, this function is defined as
     385General access to the exception context is provided by function
     386@this_exception_context@. For sequential execution, this function is defined as
    410387a weak symbol in the \CFA system-library, @libcfa@. When a \CFA program is
    411388concurrent, it links with @libcfathread@, where this function is defined with a
     
    413390
    414391The sequential @this_exception_context@ returns a hard-coded pointer to the
    415 global exception context.
     392global execption context.
    416393The concurrent version adds the exception context to the data stored at the
    417 base of each stack. When @this_exception_context@ is called, it retrieves the
     394base of each stack. When @this_exception_context@ is called it retrieves the
    418395active stack and returns the address of the context saved there.
    419396
     
    422399% catches. Talk about GCC nested functions.
    423400
    424 Termination exceptions use libunwind heavily because \CFA termination exceptions match
    425 \Cpp exceptions closely. The main complication for \CFA is that the
     401Termination exceptions use libunwind heavily because it matches the intended
     402use from \Cpp exceptions closely. The main complication for \CFA is that the
    426403compiler generates C code, making it very difficult to generate the assembly to
    427404form the LSDA for try blocks or destructors.
     
    430407The first step of a termination raise is to copy the exception into memory
    431408managed by the exception system. Currently, the system uses @malloc@, rather
    432 than reserved memory or the stack top. The exception-handling mechanism manages
     409than reserved memory or the stack top. The exception handling mechanism manages
    433410memory for the exception as well as memory for libunwind and the system's own
    434411per-exception storage.
    435412
    436 \begin{figure}
     413[Quick ASCII diagram to get started.]
    437414\begin{verbatim}
    438415Fixed Header  | _Unwind_Exception   <- pointer target
     
    443420              V ...
    444421\end{verbatim}
    445 \caption{Exception Layout}
    446 \label{f:ExceptionLayout}
    447 \end{figure}
    448 
    449 Exceptions are stored in variable-sized blocks (see Figure~\vref{f:ExceptionLayout}).
    450 The first component is a fixed-sized data-structure that contains the
     422
     423Exceptions are stored in variable-sized blocks.
     424The first component is a fixed sized data structure that contains the
    451425information for libunwind and the exception system. The second component is an
    452426area of memory big enough to store the exception. Macros with pointer arthritic
     
    454428@_Unwind_Exception@ to the entire node.
    455429
    456 Multiple exceptions can exist because handlers can call functions that raise
    457 exceptions.  Figure~\vref{f:MultipleExceptions} shows a \Cpp program where
    458 exceptions are handled, and then a function is called from the handler that
    459 raises a new exception. The previous exception must persist because it is
    460 unhandled, and hence, control can return to the handler and that exception is
    461 reraised.
    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}]{@}{@}}]
    469 struct E {};
    470 int cnt = 3;
    471 void 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 }
    480 int main() { @f( 2 );@ }
    481 \end{lstlisting}
    482 \end{lrbox}
    483 
    484 \begin{lrbox}{\myboxB}
    485 \begin{lstlisting}
    486 h  $\makebox[0pt][l]{\textbackslash}f$
    487    f
    488    f
    489 h  $\makebox[0pt][l]{\textbackslash}f$  throw E$\(_2\)$
    490    f
    491    f
    492 h  $\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 
    506 In this case, the exception nodes are linked together in a list, one list per stack, with the
     430All of these nodes are linked together in a list, one list per stack, with the
    507431list head stored in the exception context. Within each linked list, the most
    508432recently thrown exception is at the head followed by older thrown
     
    515439exception, the copy function, and the free function, so they are specific to an
    516440exception type. The size and copy function are used immediately to copy an
    517 exception into managed memory. After the exception is handled, the free function
     441exception into managed memory. After the exception is handled the free function
    518442is used to clean up the exception and then the entire node is passed to free
    519443so the memory can be given back to the heap.
     
    521445\subsection{Try Statements and Catch Clauses}
    522446The try statement with termination handlers is complex because it must
    523 compensate for the lack of assembly code generated from \CFA. Libunwind
     447compensate for the lack of assembly-code generated from \CFA. Libunwind
    524448requires an LSDA and personality function for control to unwind across a
    525449function. The LSDA in particular is hard to mimic in generated C code.
     
    530454calls them.
    531455Because this function is known and fixed (and not an arbitrary function that
    532 happens to contain a try statement), this means the LSDA can be generated ahead
     456happens to contain a try statement) this means the LSDA can be generated ahead
    533457of time.
    534458
    535459Both the LSDA and the personality function are set ahead of time using
    536 embedded assembly. This assembly code is handcrafted using C @asm@ statements and contains
    537 enough information for the single try statement the function represents.
     460embedded assembly. This is handcrafted using C @asm@ statements and contains
     461enough information for the single try statement the function repersents.
    538462
    539463The three functions passed to try terminate are:
     
    563487nested functions and all other functions besides @__cfaehm_try_terminate@ in
    564488\CFA use the GCC personality function and the @-fexceptions@ flag to generate
    565 the 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.}
     489the LSDA. This allows destructors to be implemented with the cleanup attribute.
    568490
    569491\section{Resumption}
    570492% The stack-local data, the linked list of nodes.
    571493
    572 Resumption is simpler to implement than termination because there is no stack
    573 unwinding.  \PAB{You need to explain how the \lstinline{catchResume} clauses are
    574 handled. Do you use the personality mechanism in libunwind or do you roll your
    575 own mechanism?}
    576 
    577 The
     494Resumption simple to implement because there is no stack unwinding. The
    578495resumption raise uses a list of nodes for its stack traversal. The head of the
    579496list is stored in the exception context. The nodes in the list have a pointer
    580497to the next node and a pointer to the handler function.
     498
    581499A resumption raise traverses this list. At each node the handler function is
    582500called, passing the exception by pointer. It returns true if the exception is
     
    594512the stack
    595513already examined, is accomplished by updating the front of the list as the
    596 search continues. Before the handler at a node is called, the head of the list
     514search continues. Before the handler at a node is called the head of the list
    597515is updated to the next node of the current node. After the search is complete,
    598516successful or not, the head of the list is reset.
     
    603521the other handler checked up to this point are not checked again.
    604522
    605 This structure also supports new handlers added while the resumption is being
     523This structure also supports new handler added while the resumption is being
    606524handled. These are added to the front of the list, pointing back along the
    607525stack -- the first one points over all the checked handlers -- and the ordering
    608526is maintained.
    609 
    610 \PAB{Again, a figure to show how this works would be helpful.}
    611527
    612528\label{p:zero-cost}
     
    623539% that unwind is required knowledge for that chapter.
    624540
    625 \PAB{This paragraph needs to be moved to the start of this Section, where I have have my other comment.}
    626 
    627541\section{Finally}
    628542% Uses destructors and GCC nested functions.
    629 A finally clause is placed into a GCC nested-function with a unique mangled name, and no
     543Finally clauses is placed into a GCC nested-function with a unique name, and no
    630544arguments or return values. This nested function is then set as the cleanup
    631545function of an empty object that is declared at the beginning of a block placed
    632 around the context of an associated @try@ statement.
    633 
    634 The rest is handled by GCC. The try block and all handlers are inside this
     546around the context of the associated @try@ statement.
     547
     548The rest is handled by GCC. The try block and all handlers are inside the
    635549block. At completion, control exits the block and the empty object is cleaned
    636550up, which runs the function that contains the finally code.
     
    640554
    641555Cancellation also uses libunwind to do its stack traversal and unwinding,
    642 however it uses a different primary function, @_Unwind_ForcedUnwind@. Details
    643 of its interface can be found in Section~\vref{s:ForcedUnwind}.
     556however it uses a different primary function @_Unwind_ForcedUnwind@. Details
     557of its interface can be found in the \vref{s:ForcedUnwind}.
    644558
    645559The first step of cancellation is to find the cancelled stack and its type:
    646 coroutine or thread. Fortunately, the thread library stores the program-main thread
    647 pointer and the current-thread pointer, and every thread stores a pointer to
    648 the current coroutine it is executing.
    649 
    650 \PAB{I don't know if my corrections in the previous paragraph are correct.}
    651 
    652 When the active thread and coroutine are the same, the current stack is the thread stack, otherwise it is a coroutine
    653 stack.
    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.
     560coroutine or thread. Fortunately, the thread library stores the main thread
     561pointer and the current thread pointer, and every thread stores a pointer to
     562its main coroutine and the coroutine it is currently executing.
     563
     564So if the active thread's main and current coroutine are the same. If they
     565are then the current stack is a thread stack, otherwise it is a coroutine
     566stack. If it is a thread stack then an equality check with the stored main
     567thread pointer and current thread pointer is enough to tell if the current
     568thread is the main thread or not.
     569
    658570However, if the threading library is not linked, the sequential execution is on
    659571the main stack. Hence, the entire check is skipped because the weak-symbol
     
    663575Regardless of how the stack is chosen, the stop function and parameter are
    664576passed to the forced-unwind function. The general pattern of all three stop
    665 functions is the same: continue unwinding until the end of stack.
    666 %when they
    667 %do there primary work.
     577functions is the same: they continue unwinding until the end of stack when they
     578do there primary work.
     579
    668580For main stack cancellation, the transfer is just a program abort.
    669581
    670 For coroutine cancellation, the exception is stored in the coroutine's stack,
     582For coroutine cancellation, the exception is stored on the coroutine's stack,
    671583and the coroutine context switches to its last resumer. The rest is handled on
    672584the backside of the resume, which check if the resumed coroutine is
Note: See TracChangeset for help on using the changeset viewer.