Changes in / [5a40e4e:dd1cc02]


Ignore:
Files:
13 added
56 deleted
95 edited

Legend:

Unmodified
Added
Removed
  • benchmark/Makefile.am

    r5a40e4e rdd1cc02  
    197197        $(srcdir)/fixcsv.sh $@
    198198
    199 # use --no-print-directory to generate csv appropriately
    200 mutexStmt.csv:
    201         echo "building $@"
    202         echo "1-lock,2-lock,4-lock,8-lock,1-no-stmt-lock,2-no-stmt-lock,4-no-stmt-lock,8-no-stmt-lock,1-monitor,2-monitor,4-monitor" > $@
    203         +make mutexStmt-lock1.runquiet >> $@ && echo -n ',' >> $@
    204         +make mutexStmt-lock2.runquiet >> $@ && echo -n ',' >> $@
    205         +make mutexStmt-lock4.runquiet >> $@ && echo -n ',' >> $@
    206         +make mutexStmt-lock8.runquiet >> $@ && echo -n ',' >> $@
    207         +make mutexStmt-no-stmt-lock1.runquiet >> $@ && echo -n ',' >> $@
    208         +make mutexStmt-no-stmt-lock2.runquiet >> $@ && echo -n ',' >> $@
    209         +make mutexStmt-no-stmt-lock4.runquiet >> $@ && echo -n ',' >> $@
    210         +make mutexStmt-no-stmt-lock8.runquiet >> $@ && echo -n ',' >> $@
    211         +make mutexStmt-monitor1.runquiet >> $@ && echo -n ',' >> $@
    212         +make mutexStmt-monitor2.runquiet >> $@ && echo -n ',' >> $@
    213         +make mutexStmt-monitor4.runquiet >> $@
    214         $(srcdir)/fixcsv.sh $@
    215 
    216199schedint.csv:
    217200        echo "building $@"
     
    372355        chmod a+x a.out
    373356
    374 mutexStmt$(EXEEXT) :                \
    375         mutexStmt-lock1.run                 \
    376         mutexStmt-lock2.run                 \
    377         mutexStmt-lock4.run                 \
    378         mutexStmt-lock8.run                 \
    379         mutexStmt-no-stmt-lock1.run \
    380         mutexStmt-no-stmt-lock2.run \
    381         mutexStmt-no-stmt-lock4.run \
    382         mutexStmt-no-stmt-lock8.run \
    383         mutexStmt-monitor1.run      \
    384         mutexStmt-monitor2.run      \
    385         mutexStmt-monitor4.run
    386 
    387 mutexStmt-lock1$(EXEEXT):
    388         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/lock1.cfa
    389 
    390 mutexStmt-lock2$(EXEEXT):
    391         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/lock2.cfa
    392 
    393 mutexStmt-lock4$(EXEEXT):
    394         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/lock4.cfa
    395 
    396 mutexStmt-lock8$(EXEEXT):
    397         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/lock8.cfa
    398 
    399 mutexStmt-monitor1$(EXEEXT):
    400         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/monitor1.cfa
    401 
    402 mutexStmt-monitor2$(EXEEXT):
    403         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/monitor2.cfa
    404 
    405 mutexStmt-monitor4$(EXEEXT):
    406         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/monitor4.cfa
    407 
    408 mutexStmt-no-stmt-lock1$(EXEEXT):
    409         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/no_stmt_lock1.cfa
    410 
    411 mutexStmt-no-stmt-lock2$(EXEEXT):
    412         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/no_stmt_lock2.cfa
    413 
    414 mutexStmt-no-stmt-lock4$(EXEEXT):
    415         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/no_stmt_lock4.cfa
    416 
    417 mutexStmt-no-stmt-lock8$(EXEEXT):
    418         $(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/mutexStmt/no_stmt_lock8.cfa
    419 
    420357## =========================================================================================================
    421358
  • doc/theses/andrew_beach_MMath/code/CondCatch.java

    r5a40e4e rdd1cc02  
    66        static boolean should_catch = false;
    77
     8        static void throw_exception() throws EmptyException {
     9                throw new EmptyException();
     10        }
     11
     12        static void cond_catch() throws EmptyException {
     13                try {
     14                        throw_exception();
     15                } catch (EmptyException exc) {
     16                        if (!should_catch) {
     17                                throw exc;
     18                        }
     19                }
     20        }
     21
    822        private static long loop(int times) {
    923                long startTime = System.nanoTime();
    1024                for (int count = 0 ; count < times ; ++count) {
    1125                        try {
    12                                 try {
    13                                         throw new EmptyException();
    14                                 } catch (EmptyException exc) {
    15                                         if (!should_catch) {
    16                                                 throw exc;
    17                                         }
    18                                 }
     26                                cond_catch();
    1927                        } catch (EmptyException exc) {
    2028                                // ...
     
    3846
    3947                long time = loop(times);
    40                 System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
     48                System.out.println("Run-Time (ns): " + time);
    4149        }
    4250}
  • doc/theses/andrew_beach_MMath/code/ThrowEmpty.java

    r5a40e4e rdd1cc02  
    3939
    4040                long time = loop(times, total_frames);
    41                 System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
     41                System.out.println("Run-Time (ns): " + time);
    4242        }
    4343}
  • doc/theses/andrew_beach_MMath/code/ThrowFinally.java

    r5a40e4e rdd1cc02  
    4444
    4545                long time = loop(times, total_frames);
    46                 System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
     46                System.out.println("Run-Time (ns): " + time);
    4747        }
    4848}
  • doc/theses/andrew_beach_MMath/code/ThrowOther.java

    r5a40e4e rdd1cc02  
    5252
    5353                long time = loop(times, total_frames);
    54                 System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
     54                System.out.println("Run-Time (ns): " + time);
    5555        }
    5656}
  • doc/theses/andrew_beach_MMath/code/cond-catch.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.h>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011bool should_catch = false;
     12
     13void throw_exception() {
     14        throw (empty_exception){&empty_vt};
     15}
     16
     17void cond_catch() {
     18        try {
     19                throw_exception();
     20        } catch (empty_exception * exc ; should_catch) {
     21                asm volatile ("# catch block (conditional)");
     22        }
     23}
    1124
    1225int main(int argc, char * argv[]) {
    1326        unsigned int times = 1;
    1427        if (1 < argc) {
    15                 times = strto(argv[1], 0p, 10);
     28                times = strtol(argv[1], 0p, 10);
    1629        }
    1730        if (2 < argc) {
    18                 should_catch = (unsigned int)strto(argv[2], 0p, 2);
     31                should_catch = strtol(argv[2], 0p, 10);
    1932        }
    2033
     
    2235        for (unsigned int count = 0 ; count < times ; ++count) {
    2336                try {
    24                         throw (empty_exception){&empty_vt};
    25                 } catch (empty_exception * exc ; should_catch) {
    26                         asm volatile ("# catch block (conditional)");
     37                        cond_catch();
    2738                } catch (empty_exception * exc) {
    2839                        asm volatile ("# catch block (unconditional)");
     
    3041        }
    3142        Time end_time = timeHiRes();
    32         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     43        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    3344}
  • doc/theses/andrew_beach_MMath/code/cond-catch.cpp

    r5a40e4e rdd1cc02  
    44#include <exception>
    55#include <iostream>
    6 #include <iomanip>
    76
    8 using namespace std;
    97using namespace std::chrono;
    108
     
    1210
    1311bool should_catch = false;
     12
     13void throw_exception() {
     14        throw EmptyException();
     15}
     16
     17void cond_catch() {
     18        try {
     19                throw_exception();
     20        } catch (EmptyException & exc) {
     21                if (!should_catch) {
     22                        throw;
     23                }
     24                asm volatile ("# catch block (conditional)");
     25        }
     26}
    1427
    1528int main(int argc, char * argv[]) {
     
    2538    for (unsigned int count = 0 ; count < times ; ++count) {
    2639        try {
    27                         try {
    28                                 throw EmptyException();
    29                         } catch (EmptyException & exc) {
    30                                 if (!should_catch) {
    31                                         throw;
    32                                 }
    33                                 asm volatile ("# catch block (conditional)");
    34                         }
     40                        cond_catch();
    3541                } catch (EmptyException &) {
    3642                        asm volatile ("# catch block (unconditional)");
     
    3945        time_point<steady_clock> end_time = steady_clock::now();
    4046        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    41         cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
     47        std::cout << "Run-Time (ns): " << duration.count() << std::endl;
    4248}
  • doc/theses/andrew_beach_MMath/code/cond-fixup.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011bool should_catch = false;
     12
     13void throw_exception() {
     14        throwResume (empty_exception){&empty_vt};
     15}
     16
     17void cond_catch() {
     18        try {
     19                throw_exception();
     20        } catchResume (empty_exception * exc ; should_catch) {
     21                asm volatile ("# fixup block (conditional)");
     22        }
     23}
    1124
    1225int main(int argc, char * argv[]) {
    1326        unsigned int times = 1;
    1427        if (1 < argc) {
    15                 times = strto(argv[1], 0p, 10);
     28                times = strtol(argv[1], 0p, 10);
    1629        }
    1730        if (2 < argc) {
    18                 should_catch = (unsigned int)strto(argv[2], 0p, 2);
     31                should_catch = strtol(argv[2], 0p, 10);
    1932        }
    2033
     
    2235        for (unsigned int count = 0 ; count < times ; ++count) {
    2336                try {
    24                         throwResume (empty_exception){&empty_vt};
    25                 } catchResume (empty_exception * exc ; should_catch) {
    26                         asm volatile ("# fixup block (conditional)");
     37                        cond_catch();
    2738                } catchResume (empty_exception * exc) {
    2839                        asm volatile ("# fixup block (unconditional)");
     
    3041        }
    3142        Time end_time = timeHiRes();
    32         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     43        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    3344}
  • doc/theses/andrew_beach_MMath/code/resume-detor.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011struct WithDestructor {};
     
    1617void unwind_destructor(unsigned int frames) {
    1718        if (frames) {
     19
    1820                WithDestructor object;
    1921                unwind_destructor(frames - 1);
     
    2729        unsigned int total_frames = 1;
    2830        if (1 < argc) {
    29                 times = strto(argv[1], 0p, 10);
     31                times = strtol(argv[1], 0p, 10);
    3032        }
    3133        if (2 < argc) {
    32                 total_frames = strto(argv[2], 0p, 10);
     34                total_frames = strtol(argv[2], 0p, 10);
    3335        }
    3436
     
    4244        }
    4345        Time end_time = timeHiRes();
    44         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     46        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4547}
  • doc/theses/andrew_beach_MMath/code/resume-empty.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
    98
    10 void nounwind_empty(unsigned int frames) {
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     10
     11void unwind_empty(unsigned int frames) {
    1112        if (frames) {
    12                 nounwind_empty(frames - 1);
    13                 if ( frames == -1 ) printf( "42" );                             // prevent recursion optimizations
     13                unwind_empty(frames - 1);
    1414        } else {
    1515                throwResume (empty_exception){&empty_vt};
     
    2121        unsigned int total_frames = 1;
    2222        if (1 < argc) {
    23                 times = strto(argv[1], 0p, 10);
     23                times = strtol(argv[1], 0p, 10);
    2424        }
    2525        if (2 < argc) {
    26                 total_frames = strto(argv[2], 0p, 10);
     26                total_frames = strtol(argv[2], 0p, 10);
    2727        }
    2828
    2929        Time start_time = timeHiRes();
    30         for (unsigned int count = 0 ; count < times ; ++count) {
     30        for (int count = 0 ; count < times ; ++count) {
    3131                try {
    32                         nounwind_empty(total_frames);
     32                        unwind_empty(total_frames);
    3333                } catchResume (empty_exception *) {
    3434                        asm volatile ("# fixup block");
     
    3636        }
    3737        Time end_time = timeHiRes();
    38         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     38        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    3939}
  • doc/theses/andrew_beach_MMath/code/resume-finally.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011void unwind_finally(unsigned int frames) {
     
    2425        unsigned int total_frames = 1;
    2526        if (1 < argc) {
    26                 times = strto(argv[1], 0p, 10);
     27                times = strtol(argv[1], 0p, 10);
    2728        }
    2829        if (2 < argc) {
    29                 total_frames = strto(argv[2], 0p, 10);
     30                total_frames = strtol(argv[2], 0p, 10);
    3031        }
    3132
     
    3940        }
    4041        Time end_time = timeHiRes();
    41         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     42        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4243}
  • doc/theses/andrew_beach_MMath/code/resume-other.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
    9 exception not_raised_exception;
     7EHM_EXCEPTION(empty_exception)();
    108
    11 void nounwind_other(unsigned int frames) {
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     10
     11EHM_EXCEPTION(not_raised_exception)();
     12
     13void unwind_other(unsigned int frames) {
    1214        if (frames) {
    1315                try {
    14                         nounwind_other(frames - 1);
     16                        unwind_other(frames - 1);
    1517                } catchResume (not_raised_exception *) {
    1618                        asm volatile ("# fixup block (stack)");
     
    2527        unsigned int total_frames = 1;
    2628        if (1 < argc) {
    27                 times = strto(argv[1], 0p, 10);
     29                times = strtol(argv[1], 0p, 10);
    2830        }
    2931        if (2 < argc) {
    30                 total_frames = strto(argv[2], 0p, 10);
     32                total_frames = strtol(argv[2], 0p, 10);
    3133        }
    3234
     
    3436        for (int count = 0 ; count < times ; ++count) {
    3537                try {
    36                         nounwind_other(total_frames);
     38                        unwind_other(total_frames);
    3739                } catchResume (empty_exception *) {
    3840                        asm volatile ("# fixup block (base)");
     
    4042        }
    4143        Time end_time = timeHiRes();
    42         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     44        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4345}
  • doc/theses/andrew_beach_MMath/code/run.sh

    r5a40e4e rdd1cc02  
    11#!/usr/bin/env bash
    22
    3 readonly ALL_TESTS=(raise-{empty,detor,finally,other} try-{catch,finally} \
    4                         cond-match-{all,none} fixup-{empty,other})
     3readonly ALL_TESTS=(cond-match-{all,none} cross-{catch,finally} \
     4                raise-{detor,empty,finally,other})
    55
    66gen-file-name() (
     
    1818)
    1919
    20 readonly N=${1:-1}
     20readonly N=${1:-5}
    2121readonly OUT_FILE=$(gen-file-name ${2:-run-%-$N})
    2222
  • doc/theses/andrew_beach_MMath/code/test.sh

    r5a40e4e rdd1cc02  
    44# test.sh LANGUAGE TEST
    55#   Run the TEST in LANGUAGE.
    6 # test.sh -a
    7 #   Build all tests.
    86# test.sh -b SOURCE_FILE...
    97#   Build a test from SOURCE_FILE(s).
    10 # test.sh -c
    11 #   Clean all executables.
    128# test.sh -v LANGUAGE TEST FILE
    139#   View the result from TEST in LANGUAGE stored in FILE.
    1410
    15 readonly DIR=$(dirname "$(readlink -f "$0")")
    16 cd $DIR
    17 
    18 readonly MIL=000000
    19 # Various preset values used as arguments.
    20 readonly ITERS_1M=1$MIL
    21 readonly ITERS_10M=10$MIL
    22 readonly ITERS_100M=100$MIL
    23 readonly ITERS_1000M=1000$MIL
     11readonly ITERATIONS=1000000 # 1 000 000, one million
    2412readonly STACK_HEIGHT=100
    2513
     
    3523        case "$1" in
    3624        *.cfa)
    37                 # A symbolic link/local copy can be used as an override.
    38                 cmd=./cfa
    39                 if [ ! -x $cmd ]; then
    40                         cmd=cfa
    41                 fi
    42                 mmake "${1%.cfa}" "$1" $cmd -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
     25                # Requires a symbolic link.
     26                mmake "${1%.cfa}" "$1" ./cfa -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
    4327                ;;
    4428        *.cpp)
    45                 mmake "${1%.cpp}-cpp" "$1" g++-10 -DNDEBUG -O3 "$1" -o "${1%.cpp}-cpp"
     29                mmake "${1%.cpp}-cpp" "$1" g++ -DNDEBUG -O3 "$1" -o "${1%.cpp}-cpp"
    4630                ;;
    4731        *.java)
     
    5539)
    5640
    57 if [ "-a" = "$1" ]; then
    58         for file in *.cfa *.cpp *.java; do
    59                 build $file
    60         done
    61         exit 0
    62 elif [ "-b" = "$1" ]; then
     41if [ "-b" = "$1" ]; then
    6342        for file in "${@:2}"; do
    6443                build $file
    6544        done
    6645        exit 0
    67 elif [ "-c" = "$1" ]; then
    68         rm $(basename -s ".cfa" -a *.cfa)
    69         rm $(basename -s ".cpp" -a *.cpp)
    70         rm *-cpp
    71         rm *.class
    72         exit 0
    7346elif [ "-v" = "$1" -a 4 = "$#" ]; then
    74         TEST_LANG="$2"
    75         TEST_CASE="$3"
    76         VIEW_FILE="$4"
     47    TEST_LANG="$2"
     48    TEST_CASE="$3"
     49    VIEW_FILE="$4"
    7750elif [ 2 -eq "$#" ]; then
    7851        TEST_LANG="$1"
     
    9063
    9164case "$TEST_CASE" in
    92 raise-empty)
    93         CFAT="./throw-empty $ITERS_1M $STACK_HEIGHT"
    94         CFAR="./resume-empty $ITERS_10M $STACK_HEIGHT"
    95         CPP="./throw-empty-cpp $ITERS_1M $STACK_HEIGHT"
    96         JAVA="java ThrowEmpty $ITERS_1M $STACK_HEIGHT"
    97         PYTHON="./throw-empty.py $ITERS_1M $STACK_HEIGHT"
     65cond-match-all)
     66        CFAT="./cond-catch $ITERATIONS 1"
     67        CFAR="./cond-fixup $ITERATIONS 1"
     68        CPP="./cond-catch-cpp $ITERATIONS 1"
     69        JAVA="java CondCatch $ITERATIONS 1"
     70        PYTHON="./cond_catch.py $ITERATIONS 1"
     71        ;;
     72cond-match-none)
     73        CFAT="./cond-catch $ITERATIONS 0"
     74        CFAR="./cond-fixup $ITERATIONS 0"
     75        CPP="./cond-catch-cpp $ITERATIONS 0"
     76        JAVA="java CondCatch $ITERATIONS 0"
     77        PYTHON="./cond_catch.py $ITERATIONS 0"
     78        ;;
     79cross-catch)
     80        CFAT="./cross-catch $ITERATIONS"
     81        CFAR="./cross-resume $ITERATIONS"
     82        CPP="./cross-catch-cpp $ITERATIONS"
     83        JAVA="java CrossCatch $ITERATIONS"
     84        PYTHON="./cross_catch.py $ITERATIONS"
     85        ;;
     86cross-finally)
     87        CFAT="./cross-finally $ITERATIONS"
     88        CFAR=unsupported
     89        CPP=unsupported
     90        JAVA="java CrossFinally $ITERATIONS"
     91        PYTHON="./cross_finally.py $ITERATIONS"
    9892        ;;
    9993raise-detor)
    100         CFAT="./throw-detor $ITERS_1M $STACK_HEIGHT"
    101         CFAR="./resume-detor $ITERS_10M $STACK_HEIGHT"
    102         CPP="./throw-detor-cpp $ITERS_1M $STACK_HEIGHT"
     94        CFAT="./throw-detor $ITERATIONS $STACK_HEIGHT"
     95        CFAR="./resume-detor $ITERATIONS $STACK_HEIGHT"
     96        CPP="./throw-detor-cpp $ITERATIONS $STACK_HEIGHT"
    10397        JAVA=unsupported
    10498        PYTHON=unsupported
    10599        ;;
     100raise-empty)
     101        CFAT="./throw-empty $ITERATIONS $STACK_HEIGHT"
     102        CFAR="./resume-empty $ITERATIONS $STACK_HEIGHT"
     103        CPP="./throw-empty-cpp $ITERATIONS $STACK_HEIGHT"
     104        JAVA="java ThrowEmpty $ITERATIONS $STACK_HEIGHT"
     105        PYTHON="./throw_empty.py $ITERATIONS $STACK_HEIGHT"
     106        ;;
    106107raise-finally)
    107         CFAT="./throw-finally $ITERS_1M $STACK_HEIGHT"
    108         CFAR="./resume-finally $ITERS_10M $STACK_HEIGHT"
     108        CFAT="./throw-finally $ITERATIONS $STACK_HEIGHT"
     109        CFAR="./resume-finally $ITERATIONS $STACK_HEIGHT"
    109110        CPP=unsupported
    110         JAVA="java ThrowFinally $ITERS_1M $STACK_HEIGHT"
    111         PYTHON="./throw-finally.py $ITERS_1M $STACK_HEIGHT"
     111        JAVA="java ThrowFinally $ITERATIONS $STACK_HEIGHT"
     112        PYTHON="./throw_finally.py $ITERATIONS $STACK_HEIGHT"
    112113        ;;
    113114raise-other)
    114         CFAT="./throw-other $ITERS_1M $STACK_HEIGHT"
    115         CFAR="./resume-other $ITERS_10M $STACK_HEIGHT"
    116         CPP="./throw-other-cpp $ITERS_1M $STACK_HEIGHT"
    117         JAVA="java ThrowOther $ITERS_1M $STACK_HEIGHT"
    118         PYTHON="./throw-other.py $ITERS_1M $STACK_HEIGHT"
    119         ;;
    120 try-catch)
    121         CFAT="./try-catch $ITERS_1000M"
    122         CFAR="./try-resume $ITERS_1000M"
    123         CPP="./try-catch-cpp $ITERS_1000M"
    124         JAVA="java TryCatch $ITERS_1000M"
    125         PYTHON="./try-catch.py $ITERS_1000M"
    126         ;;
    127 try-finally)
    128         CFAT="./try-finally $ITERS_1000M"
    129         CFAR=unsupported
    130         CPP=unsupported
    131         JAVA="java TryFinally $ITERS_1000M"
    132         PYTHON="./try-finally.py $ITERS_1000M"
    133         ;;
    134 cond-match-all)
    135         CFAT="./cond-catch $ITERS_10M 1"
    136         CFAR="./cond-fixup $ITERS_100M 1"
    137         CPP="./cond-catch-cpp $ITERS_10M 1"
    138         JAVA="java CondCatch $ITERS_10M 1"
    139         PYTHON="./cond-catch.py $ITERS_10M 1"
    140         ;;
    141 cond-match-none)
    142         CFAT="./cond-catch $ITERS_10M 0"
    143         CFAR="./cond-fixup $ITERS_100M 0"
    144         CPP="./cond-catch-cpp $ITERS_10M 0"
    145         JAVA="java CondCatch $ITERS_10M 0"
    146         PYTHON="./cond-catch.py $ITERS_10M 0"
    147         ;;
    148 fixup-empty)
    149         CFAT="./fixup-empty-f $ITERS_10M $STACK_HEIGHT"
    150         CFAR="./fixup-empty-r $ITERS_10M $STACK_HEIGHT"
    151         CPP="./fixup-empty-cpp $ITERS_10M $STACK_HEIGHT"
    152         JAVA="java FixupEmpty $ITERS_10M $STACK_HEIGHT"
    153         PYTHON="./fixup-empty.py $ITERS_10M $STACK_HEIGHT"
    154         ;;
    155 fixup-other)
    156         CFAT="./fixup-other-f $ITERS_10M $STACK_HEIGHT"
    157         CFAR="./fixup-other-r $ITERS_10M $STACK_HEIGHT"
    158         CPP="./fixup-other-cpp $ITERS_10M $STACK_HEIGHT"
    159         JAVA="java FixupOther $ITERS_10M $STACK_HEIGHT"
    160         PYTHON="./fixup-other.py $ITERS_10M $STACK_HEIGHT"
     115        CFAT="./throw-other $ITERATIONS $STACK_HEIGHT"
     116        CFAR="./resume-other $ITERATIONS $STACK_HEIGHT"
     117        CPP="./throw-other-cpp $ITERATIONS $STACK_HEIGHT"
     118        JAVA="java ThrowOther $ITERATIONS $STACK_HEIGHT"
     119        PYTHON="./throw_other.py $ITERATIONS $STACK_HEIGHT"
    161120        ;;
    162121*)
     
    181140
    182141if [ -n "$VIEW_FILE" ]; then
    183         grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
    184         exit
     142    grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
     143    exit
    185144fi
    186145
  • doc/theses/andrew_beach_MMath/code/throw-detor.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011struct WithDestructor {};
     
    2728        unsigned int total_frames = 1;
    2829        if (1 < argc) {
    29                 times = strto(argv[1], 0p, 10);
     30                times = strtol(argv[1], 0p, 10);
    3031        }
    3132        if (2 < argc) {
    32                 total_frames = strto(argv[2], 0p, 10);
     33                total_frames = strtol(argv[2], 0p, 10);
    3334        }
    3435
     
    4243        }
    4344        Time end_time = timeHiRes();
    44         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     45        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4546}
  • doc/theses/andrew_beach_MMath/code/throw-detor.cpp

    r5a40e4e rdd1cc02  
    44#include <exception>
    55#include <iostream>
    6 #include <iomanip>
    76
    8 using namespace std;
    97using namespace std::chrono;
    108
     
    4644        time_point<steady_clock> end_time = steady_clock::now();
    4745        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    48         cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
     46        std::cout << "Run-Time (ns): " << duration.count() << std::endl;
    4947}
  • doc/theses/andrew_beach_MMath/code/throw-empty.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
     8
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    910
    1011void unwind_empty(unsigned int frames) {
     
    2021        unsigned int total_frames = 1;
    2122        if (1 < argc) {
    22                 times = strto(argv[1], 0p, 10);
     23                times = strtol(argv[1], 0p, 10);
    2324        }
    2425        if (2 < argc) {
    25                 total_frames = strto(argv[2], 0p, 10);
     26                total_frames = strtol(argv[2], 0p, 10);
    2627        }
    2728
     
    3536        }
    3637        Time end_time = timeHiRes();
    37         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     38        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    3839}
  • doc/theses/andrew_beach_MMath/code/throw-empty.cpp

    r5a40e4e rdd1cc02  
    11// Throw Across Empty Function
    22#include <chrono>
    3 #include <cstdio>
    43#include <cstdlib>
    54#include <exception>
    65#include <iostream>
    7 #include <iomanip>
    86
    9 using namespace std;
    107using namespace std::chrono;
    118
     
    1512        if (frames) {
    1613                unwind_empty(frames - 1);
    17                 if (-1 == frames) printf("~");
    1814        } else {
    1915                throw (EmptyException){};
     
    4137        time_point<steady_clock> end_time = steady_clock::now();
    4238        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    43         cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
     39        std::cout << "Run-Time (ns): " << duration.count() << std::endl;
    4440}
  • doc/theses/andrew_beach_MMath/code/throw-finally.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
     7EHM_EXCEPTION(empty_exception)();
    98
    10 unsigned int frames;                                                                    // use global because of gcc thunk problem
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    1110
    12 void unwind_finally(unsigned int dummy) {
     11void unwind_finally(unsigned int frames) {
    1312        if (frames) {
    14                 frames -= 1;
    1513                try {
    16                         unwind_finally(42);
     14                        unwind_finally(frames - 1);
    1715                } finally {
    1816                        asm volatile ("# finally block");
    1917                }
    2018        } else {
    21                 dummy = 42;
    2219                throw (empty_exception){&empty_vt};
    2320        }
     
    2825        unsigned int total_frames = 1;
    2926        if (1 < argc) {
    30                 times = strto(argv[1], 0p, 10);
     27                times = strtol(argv[1], 0p, 10);
    3128        }
    3229        if (2 < argc) {
    33                 total_frames = strto(argv[2], 0p, 10);
     30                total_frames = strtol(argv[2], 0p, 10);
    3431        }
    35         frames = total_frames;
    3632
    3733        Time start_time = timeHiRes();
    3834        for (int count = 0 ; count < times ; ++count) {
    3935                try {
    40                         unwind_finally(42);
     36                        unwind_finally(total_frames);
    4137                } catch (empty_exception *) {
    4238                        asm volatile ("# catch block");
     
    4440        }
    4541        Time end_time = timeHiRes();
    46         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     42        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4743}
  • doc/theses/andrew_beach_MMath/code/throw-other.cfa

    r5a40e4e rdd1cc02  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    7 exception empty_exception;
    8 vtable(empty_exception) empty_vt;
    9 exception not_raised_exception;
     7EHM_EXCEPTION(empty_exception)();
    108
    11 unsigned int frames;                                                                    // use global because of gcc thunk problem
     9EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    1210
    13 void unwind_other(unsigned int dummy) {
     11EHM_EXCEPTION(not_raised_exception)();
     12
     13void unwind_other(unsigned int frames) {
    1414        if (frames) {
    15                 frames -= 1;
    1615                try {
    17                         unwind_other(42);
     16                        unwind_other(frames - 1);
    1817                } catch (not_raised_exception *) {
    1918                        asm volatile ("# catch block (stack)");
    2019                }
    2120        } else {
    22                 dummy = 42;
    2321                throw (empty_exception){&empty_vt};
    2422        }
     
    2927        unsigned int total_frames = 1;
    3028        if (1 < argc) {
    31                 times = strto(argv[1], 0p, 10);
     29                times = strtol(argv[1], 0p, 10);
    3230        }
    3331        if (2 < argc) {
    34                 total_frames = strto(argv[2], 0p, 10);
     32                total_frames = strtol(argv[2], 0p, 10);
    3533        }
    36         frames = total_frames;
    3734
    3835        Time start_time = timeHiRes();
    3936        for (int count = 0 ; count < times ; ++count) {
    4037                try {
    41                         unwind_other(42);
     38                        unwind_other(total_frames);
    4239                } catch (empty_exception *) {
    4340                        asm volatile ("# catch block (base)");
     
    4542        }
    4643        Time end_time = timeHiRes();
    47         sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
     44        sout | "Run-Time (ns): " | (end_time - start_time)`ns;
    4845}
  • doc/theses/andrew_beach_MMath/code/throw-other.cpp

    r5a40e4e rdd1cc02  
    44#include <exception>
    55#include <iostream>
    6 #include <iomanip>
    76
    8 using namespace std;
    97using namespace std::chrono;
    108
     
    4543        time_point<steady_clock> end_time = steady_clock::now();
    4644        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    47         cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
     45        std::cout << "Run-Time (ns): " << duration.count() << std::endl;
    4846}
  • doc/theses/andrew_beach_MMath/conclusion.tex

    r5a40e4e rdd1cc02  
    11\chapter{Conclusion}
    2 \label{c:conclusion}
    32% Just a little knot to tie the paper together.
    43
    54In the previous chapters this thesis presents the design and implementation
    65of \CFA's exception handling mechanism (EHM).
    7 Both the design and implementation are based off of tools and
    8 techniques developed for other programming languages but they were adapted to
    9 better fit \CFA's feature set and add a few features that do not exist in
    10 other EHMs;
    11 including conditional matching, default handlers for unhandled exceptions
    12 and cancellation though coroutines and threads back to the program main stack.
     6Both the design and implementation are based off of tools and techniques
     7developed for other programming languages but they were adapted to better fit
     8\CFA's feature set.
    139
    1410The resulting features cover all of the major use cases of the most popular
    1511termination EHMs of today, along with reintroducing resumption exceptions and
    16 creating some new features that fit with \CFA's larger programming patterns,
    17 such as virtuals independent of traditional objects.
     12creating some new features that fix with \CFA's larger programming patterns.
    1813
    19 The \CFA project's test suite has been expanded to test the EHM.
    20 The implementation's performance has also been
    21 compared to other implementations with a small set of targeted
    22 micro-benchmarks.
     14The implementation has been tested and compared to other implementations.
    2315The results, while not cutting edge, are good enough for prototyping, which
    24 is \CFA's current stage of development.
     16is \CFA's stage of development.
    2517
    26 This initial EHM will bring valuable new features to \CFA in its own right
    27 but also serves as a tool and motivation for other developments in the
    28 language.
     18This is a valuable new feature for \CFA in its own right but also serves
     19as a tool (and motivation) for other developments in the language.
  • doc/theses/andrew_beach_MMath/exception-layout.fig

    r5a40e4e rdd1cc02  
    2828        0 0 1.00 240.00 240.00
    2929         360 405 360 2070
    30 4 0 0 50 -1 0 12 0.0000 0 135 1080 2700 585 Fixed Header\001
    31 4 0 0 50 -1 0 12 0.0000 0 135 1575 540 990 Cforall Information\001
    32 4 0 0 50 -1 0 12 0.0000 0 180 1695 540 585 _Unwind_Exception\001
    33 4 0 0 50 -1 0 12 0.0000 0 180 1245 540 1530 User Exception\001
    34 4 0 0 50 -1 0 12 0.0000 0 180 1185 2655 1530 Variable Body\001
    35 4 0 0 50 -1 0 12 0.0000 0 165 1110 2655 1215 (Fixed Offset)\001
     304 0 0 50 -1 0 12 0.0000 4 135 1080 2700 585 Fixed Header\001
     314 0 0 50 -1 0 12 0.0000 4 135 1710 540 990 Cforall Information\001
     324 0 0 50 -1 0 12 0.0000 4 165 1530 540 585 _Unwind_Exception\001
     334 0 0 50 -1 0 12 0.0000 4 165 1260 540 1530 User Exception\001
     344 0 0 50 -1 0 12 0.0000 4 165 1170 2655 1530 Variable Body\001
     354 0 0 50 -1 0 12 0.0000 4 165 1260 2655 1215 (Fixed Offset)\001
  • doc/theses/andrew_beach_MMath/existing.tex

    r5a40e4e rdd1cc02  
    1010
    1111Only those \CFA features pertaining to this thesis are discussed.
     12% Also, only new features of \CFA will be discussed,
    1213A familiarity with
    1314C or C-like languages is assumed.
     
    1617\CFA has extensive overloading, allowing multiple definitions of the same name
    1718to be defined~\cite{Moss18}.
    18 \begin{cfa}
    19 char i; int i; double i;
    20 int f(); double f();
    21 void g( int ); void g( double );
    22 \end{cfa}
     19\begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
     20char @i@; int @i@; double @i@;
     21int @f@(); double @f@();
     22void @g@( int ); void @g@( double );
     23\end{lstlisting}
    2324This feature requires name mangling so the assembly symbols are unique for
    2425different overloads. For compatibility with names in C, there is also a syntax
     
    6263int && rri = ri;
    6364rri = 3;
    64 &ri = &j;
     65&ri = &j; // rebindable
    6566ri = 5;
    6667\end{cfa}
     
    7879\end{minipage}
    7980
    80 References are intended to be used when the indirection of a pointer is
    81 required, but the address is not as important as the value and dereferencing
    82 is the common usage.
     81References are intended for pointer situations where dereferencing is the common usage,
     82\ie the value is more important than the pointer.
    8383Mutable references may be assigned to by converting them to a pointer
    84 with a @&@ and then assigning a pointer to them, as in @&ri = &j;@ above.
    85 % ???
     84with a @&@ and then assigning a pointer to them, as in @&ri = &j;@ above
    8685
    8786\section{Operators}
    8887
    8988\CFA implements operator overloading by providing special names, where
    90 operator expressions are translated into function calls using these names.
     89operator usages are translated into function calls using these names.
    9190An operator name is created by taking the operator symbols and joining them with
    9291@?@s to show where the arguments go.
     
    9594This syntax make it easy to tell the difference between prefix operations
    9695(such as @++?@) and post-fix operations (@?++@).
    97 
    98 As an example, here are the addition and equality operators for a point type.
     96For example, plus and equality operators are defined for a point type.
    9997\begin{cfa}
    10098point ?+?(point a, point b) { return point{a.x + b.x, a.y + b.y}; }
     
    104102}
    105103\end{cfa}
    106 Note that this syntax works effectively but a textual transformation,
    107 the compiler converts all operators into functions and then resolves them
    108 normally. This means any combination of types may be used,
    109 although nonsensical ones (like @double ?==?(point, int);@) are discouraged.
    110 This feature is also used for all builtin operators as well,
    111 although those are implicitly provided by the language.
     104Note these special names are not limited to builtin
     105operators, and hence, may be used with arbitrary types.
     106\begin{cfa}
     107double ?+?( int x, point y ); // arbitrary types
     108\end{cfa}
     109% Some ``near misses", that are that do not match an operator form but looks like
     110% it may have been supposed to, will generate warning but otherwise they are
     111% left alone.
     112Because operators are never part of the type definition they may be added
     113at any time, including on built-in types.
    112114
    113115%\subsection{Constructors and Destructors}
    114 In \CFA, constructors and destructors are operators, which means they are
    115 functions with special operator names rather than type names in \Cpp.
    116 Both constructors and destructors can be implicity called by the compiler,
    117 however the operator names allow explicit calls.
    118 % Placement new means that this is actually equivant to C++.
     116
     117\CFA also provides constructors and destructors as operators, which means they
     118are functions with special operator names rather than type names in \Cpp.
     119While constructors and destructions are normally called implicitly by the compiler,
     120the special operator names, allow explicit calls.
     121
     122% Placement new means that this is actually equivalent to C++.
    119123
    120124The special name for a constructor is @?{}@, which comes from the
     
    125129struct Example { ... };
    126130void ?{}(Example & this) { ... }
    127 {
    128         Example a;
    129         Example b = {};
    130 }
    131131void ?{}(Example & this, char first, int num) { ... }
    132 {
    133         Example c = {'a', 2};
    134 }
    135 \end{cfa}
    136 Both @a@ and @b@ will be initalized with the first constructor,
    137 @b@ because of the explicit call and @a@ implicitly.
    138 @c@ will be initalized with the second constructor.
    139 Currently, there is no general way to skip initialation.
    140 % I don't use @= anywhere in the thesis.
    141 
     132Example a;              // implicit constructor calls
     133Example b = {};
     134Example c = {'a', 2};
     135\end{cfa}
     136Both @a@ and @b@ are initialized with the first constructor,
     137while @c@ is initialized with the second.
     138Constructor calls can be replaced with C initialization using special operator \lstinline{@=}.
     139\begin{cfa}
     140Example d @= {42};
     141\end{cfa}
    142142% I don't like the \^{} symbol but $^\wedge$ isn't better.
    143143Similarly, destructors use the special name @^?{}@ (the @^@ has no special
    144144meaning).
     145% These are a normally called implicitly called on a variable when it goes out
     146% of scope. They can be called explicitly as well.
    145147\begin{cfa}
    146148void ^?{}(Example & this) { ... }
    147149{
    148         Example d;
    149         ^?{}(d);
    150 
    151         Example e;
    152 } // Implicit call of ^?{}(e);
     150        Example e;      // implicit constructor call
     151        ^?{}(e);                // explicit destructor call
     152        ?{}(e);         // explicit constructor call
     153} // implicit destructor call
    153154\end{cfa}
    154155
     
    224225The global definition of @do_once@ is ignored, however if quadruple took a
    225226@double@ argument, then the global definition would be used instead as it
    226 would then be a better match.\cite{Moss19}
    227 
    228 To avoid typing long lists of assertions, constraints can be collected into
    229 convenient a package called a @trait@, which can then be used in an assertion
     227is a better match.
     228% Aaron's thesis might be a good reference here.
     229
     230To avoid typing long lists of assertions, constraints can be collect into
     231convenient package called a @trait@, which can then be used in an assertion
    230232instead of the individual constraints.
    231233\begin{cfa}
     
    251253        node(T) * next;
    252254        T * data;
    253 };
     255}
    254256node(int) inode;
    255257\end{cfa}
     
    291293};
    292294CountUp countup;
     295for (10) sout | resume(countup).next; // print 10 values
    293296\end{cfa}
    294297Each coroutine has a @main@ function, which takes a reference to a coroutine
    295298object and returns @void@.
    296299%[numbers=left] Why numbers on this one?
    297 \begin{cfa}
     300\begin{cfa}[numbers=left,numberstyle=\scriptsize\sf]
    298301void main(CountUp & this) {
    299         for (unsigned int next = 0 ; true ; ++next) {
    300                 this.next = next;
     302        for (unsigned int up = 0;; ++up) {
     303                this.next = up;
    301304                suspend;$\label{suspend}$
    302305        }
     
    304307\end{cfa}
    305308In this function, or functions called by this function (helper functions), the
    306 @suspend@ statement is used to return execution to the coroutine's caller
    307 without terminating the coroutine's function.
     309@suspend@ statement is used to return execution to the coroutine's resumer
     310without terminating the coroutine's function(s).
    308311
    309312A coroutine is resumed by calling the @resume@ function, \eg @resume(countup)@.
    310313The first resume calls the @main@ function at the top. Thereafter, resume calls
    311314continue a coroutine in the last suspended function after the @suspend@
    312 statement. In this case there is only one and, hence, the difference between
    313 subsequent calls is the state of variables inside the function and the
    314 coroutine object.
    315 The return value of @resume@ is a reference to the coroutine, to make it
    316 convent to access fields of the coroutine in the same expression.
    317 Here is a simple example in a helper function:
    318 \begin{cfa}
    319 unsigned int get_next(CountUp & this) {
    320         return resume(this).next;
    321 }
    322 \end{cfa}
    323 
    324 When the main function returns the coroutine halts and can no longer be
    325 resumed.
     315statement, in this case @main@ line~\ref{suspend}.  The @resume@ function takes
     316a reference to the coroutine structure and returns the same reference. The
     317return value allows easy access to communication variables defined in the
     318coroutine object. For example, the @next@ value for coroutine object @countup@
     319is both generated and collected in the single expression:
     320@resume(countup).next@.
    326321
    327322\subsection{Monitor and Mutex Parameter}
     
    335330exclusion on a monitor object by qualifying an object reference parameter with
    336331@mutex@.
    337 \begin{cfa}
    338 void example(MonitorA & mutex argA, MonitorB & mutex argB);
    339 \end{cfa}
     332\begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
     333void example(MonitorA & @mutex@ argA, MonitorB & @mutex@ argB);
     334\end{lstlisting}
    340335When the function is called, it implicitly acquires the monitor lock for all of
    341336the mutex parameters without deadlock.  This semantics means all functions with
     
    367362{
    368363        StringWorker stringworker; // fork thread running in "main"
    369 } // Implicit call to join(stringworker), waits for completion.
     364} // implicitly join with thread / wait for completion
    370365\end{cfa}
    371366The thread main is where a new thread starts execution after a fork operation
  • doc/theses/andrew_beach_MMath/features.tex

    r5a40e4e rdd1cc02  
    1919
    2020\paragraph{Raise}
    21 The raise is the starting point for exception handling,
     21The raise is the starting point for exception handling
    2222by raising an exception, which passes it to
    2323the EHM.
     
    3030\paragraph{Handle}
    3131The primary purpose of an EHM is to run some user code to handle a raised
    32 exception. This code is given, along with some other information,
    33 in a handler.
     32exception. This code is given, with some other information, in a handler.
    3433
    3534A handler has three common features: the previously mentioned user code, a
    36 region of code it guards and an exception label/condition that matches
    37 against the raised exception.
     35region of code it guards, and an exception label/condition that matches
     36the raised exception.
    3837Only raises inside the guarded region and raising exceptions that match the
    3938label can be handled by a given handler.
     
    4241
    4342The @try@ statements of \Cpp, Java and Python are common examples. All three
    44 also show another common feature of handlers, they are grouped by the guarded
    45 region.
     43show the common features of guarded region, raise, matching and handler.
     44\begin{cfa}
     45try {                           // guarded region
     46        ...     
     47        throw exception;        // raise
     48        ...     
     49} catch( exception ) {  // matching condition, with exception label
     50        ...                             // handler code
     51}
     52\end{cfa}
    4653
    4754\subsection{Propagation}
    4855After an exception is raised comes what is usually the biggest step for the
    49 EHM: finding and setting up the handler for execution.
    50 The propagation from raise to
     56EHM: finding and setting up the handler for execution. The propagation from raise to
    5157handler can be broken up into three different tasks: searching for a handler,
    5258matching against the handler and installing the handler.
     
    5460\paragraph{Searching}
    5561The EHM begins by searching for handlers that might be used to handle
    56 the exception.
    57 The search will find handlers that have the raise site in their guarded
     62the exception. The search is restricted to
     63handlers that have the raise site in their guarded
    5864region.
    5965The search includes handlers in the current function, as well as any in
     
    6167
    6268\paragraph{Matching}
    63 Each handler found is with the raised exception. The exception
     69Each handler found is matched with the raised exception. The exception
    6470label defines a condition that is used with the exception and decides if
    6571there is a match or not.
    66 %
    6772In languages where the first match is used, this step is intertwined with
    6873searching; a match check is performed immediately after the search finds
     
    7984different course of action for this case.
    8085This situation only occurs with unchecked exceptions as checked exceptions
    81 (such as in Java) can make the guarantee.
     86(such as in Java) are guaranteed to find a matching handler.
    8287The unhandled action is usually very general, such as aborting the program.
    8388
     
    9398A handler labeled with any given exception can handle exceptions of that
    9499type or any child type of that exception. The root of the exception hierarchy
    95 (here \code{C}{exception}) acts as a catch-all, leaf types catch single types
     100(here \code{C}{exception}) acts as a catch-all, leaf types catch single types,
    96101and the exceptions in the middle can be used to catch different groups of
    97102related exceptions.
    98103
    99104This system has some notable advantages, such as multiple levels of grouping,
    100 the ability for libraries to add new exception types and the isolation
     105the ability for libraries to add new exception types, and the isolation
    101106between different sub-hierarchies.
    102107This design is used in \CFA even though it is not a object-orientated
     
    118123For effective exception handling, additional information is often passed
    119124from the raise to the handler and back again.
    120 So far, only communication of the exceptions' identity is covered.
    121 A common communication method for adding information to an exception
    122 is putting fields into the exception instance
     125So far, only communication of the exception's identity is covered.
     126A common communication method for passing more information is putting fields into the exception instance
    123127and giving the handler access to them.
    124 % You can either have pointers/references in the exception, or have p/rs to
    125 % the exception when it doesn't have to be copied.
    126 Passing references or pointers allows data at the raise location to be
    127 updated, passing information in both directions.
     128Using reference fields pointing to data at the raise location allows data to be
     129passed in both directions.
    128130
    129131\section{Virtuals}
    130 \label{s:virtuals}
    131132Virtual types and casts are not part of \CFA's EHM nor are they required for
    132133an EHM.
    133134However, one of the best ways to support an exception hierarchy
    134135is via a virtual hierarchy and dispatch system.
    135 Ideally, the virtual system would have been part of \CFA before the work
     136
     137Ideally, the virtual system should have been part of \CFA before the work
    136138on exception handling began, but unfortunately it was not.
    137139Hence, only the features and framework needed for the EHM were
    138 designed and implemented for this thesis.
    139 Other features were considered to ensure that
     140designed and implemented for this thesis. Other features were considered to ensure that
    140141the structure could accommodate other desirable features in the future
    141142but are not implemented.
    142143The rest of this section only discusses the implemented subset of the
    143 virtual system design.
     144virtual-system design.
    144145
    145146The virtual system supports multiple ``trees" of types. Each tree is
     
    148149number of children.
    149150Any type that belongs to any of these trees is called a virtual type.
     151
    150152% A type's ancestors are its parent and its parent's ancestors.
    151153% The root type has no ancestors.
    152154% A type's descendants are its children and its children's descendants.
    153155
    154 For the purposes of illustration, a proposed -- but unimplemented syntax --
    155 will be used. Each virtual type is represented by a trait with an annotation
    156 that makes it a virtual type. This annotation is empty for a root type, which
    157 creates a new tree:
    158 \begin{cfa}
    159 trait root_type(T) virtual() {}
    160 \end{cfa}
    161 The annotation may also refer to any existing virtual type to make this new
    162 type a child of that type and part of the same tree. The parent may itself
    163 be a child or a root type and may have any number of existing children.
    164 
    165 % OK, for some reason the b and t positioning options are reversed here.
    166 \begin{minipage}[b]{0.6\textwidth}
    167 \begin{cfa}
    168 trait child_a(T) virtual(root_type) {}
    169 trait grandchild(T) virtual(child_a) {}
    170 trait child_b(T) virtual(root_type) {}
    171 \end{cfa}
    172 \end{minipage}
    173 \begin{minipage}{0.4\textwidth}
    174 \begin{center}
    175 \input{virtual-tree}
    176 \end{center}
    177 \end{minipage}
    178 
    179 Every virtual type also has a list of virtual members and a unique id,
    180 both are stored in a virtual table.
    181 Every instance of a virtual type also has a pointer to a virtual table stored
    182 in it, although there is no per-type virtual table as in many other languages.
    183 
    184 The list of virtual members is built up down the tree. Every virtual type
    185 inherits the list of virtual members from its parent and may add more
    186 virtual members to the end of the list which are passed on to its children.
    187 Again, using the unimplemented syntax this might look like:
    188 \begin{cfa}
    189 trait root_type(T) virtual() {
    190         const char * to_string(T const & this);
    191         unsigned int size;
    192 }
    193 
    194 trait child_type(T) virtual(root_type) {
    195         char * irrelevant_function(int, char);
    196 }
    197 \end{cfa}
    198 % Consider adding a diagram, but we might be good with the explanation.
    199 
    200 As @child_type@ is a child of @root_type@ it has the virtual members of
    201 @root_type@ (@to_string@ and @size@) as well as the one it declared
    202 (@irrelevant_function@).
    203 
    204 It is important to note that these are virtual members, and may contain   
    205 arbitrary fields, functions or otherwise.
    206 The names ``size" and ``align" are reserved for the size and alignment of the
    207 virtual type, and are always automatically initialized as such.
    208 The other special case are uses of the trait's polymorphic argument
    209 (@T@ in the example), which are always updated to refer to the current
    210 virtual type. This allows functions that refer to to polymorphic argument
    211 to act as traditional virtual methods (@to_string@ in the example), as the
    212 object can always be passed to a virtual method in its virtual table.
     156Every virtual type also has a list of virtual members. Children inherit
     157their parent's list of virtual members but may add new members to it.
     158It is important to note that these are virtual members, not virtual methods
     159of object-orientated programming, and can be of any type.
     160
     161\PAB{Need to look at these when done.
     162
     163\CFA still supports virtual methods as a special case of virtual members.
     164Function pointers that take a pointer to the virtual type are modified
     165with each level of inheritance so that refers to the new type.
     166This means an object can always be passed to a function in its virtual table
     167as if it were a method.
     168\todo{Clarify (with an example) virtual methods.}
     169
     170Each virtual type has a unique id.
     171This id and all the virtual members are combined
     172into a virtual table type. Each virtual type has a pointer to a virtual table
     173as a hidden field.
     174\todo{Might need a diagram for virtual structure.}
     175}%
    213176
    214177Up until this point the virtual system is similar to ones found in
    215 object-oriented languages but this is where \CFA diverges.
    216 Objects encapsulate a single set of methods in each type,
    217 universally across the entire program,
    218 and indeed all programs that use that type definition.
    219 The only way to change any method is to inherit and define a new type with
    220 its own universal implementation. In this sense,
    221 these object-oriented types are ``closed" and cannot be altered.
    222 % Because really they are class oriented.
    223 
    224 In \CFA, types do not encapsulate any code.
    225 Whether or not satisfies any given assertion, and hence any trait, is
    226 context sensitive. Types can begin to satisfy a trait, stop satisfying it or
    227 satisfy the same trait at any lexical location in the program.
    228 In this sense, an type's implementation in the set of functions and variables
    229 that allow it to satisfy a trait is ``open" and can change
    230 throughout the program.
     178object-orientated languages but this is where \CFA diverges. Objects encapsulate a
     179single set of methods in each type, universally across the entire program,
     180and indeed all programs that use that type definition. Even if a type inherits and adds methods, it still encapsulate a
     181single set of methods. In this sense,
     182object-oriented types are ``closed" and cannot be altered.
     183
     184In \CFA, types do not encapsulate any code. Traits are local for each function and
     185types can satisfy a local trait, stop satisfying it or, satisfy the same
     186trait in a different way at any lexical location in the program where a function is call.
     187In this sense, the set of functions/variables that satisfy a trait for a type is ``open" as the set can change at every call site.
    231188This capability means it is impossible to pick a single set of functions
    232189that represent a type's implementation across a program.
     
    235192type. A user can define virtual tables that are filled in at their
    236193declaration and given a name. Anywhere that name is visible, even if it is
    237 defined locally inside a function (although in this case the user must ensure
    238 it outlives any objects that use it), it can be used.
     194defined locally inside a function \PAB{What does this mean? (although that means it does not have a
     195static lifetime)}, it can be used.
    239196Specifically, a virtual type is ``bound" to a virtual table that
    240197sets the virtual members for that object. The virtual members can be accessed
    241198through the object.
    242 
    243 This means virtual tables are declared and named in \CFA.
    244 They are declared as variables, using the type
    245 @vtable(VIRTUAL_TYPE)@ and any valid name. For example:
    246 \begin{cfa}
    247 vtable(virtual_type_name) table_name;
    248 \end{cfa}
    249 
    250 Like any variable they may be forward declared with the @extern@ keyword.
    251 Forward declaring virtual tables is relatively common.
    252 Many virtual types have an ``obvious" implementation that works in most
    253 cases.
    254 A pattern that has appeared in the early work using virtuals is to
    255 implement a virtual table with the the obvious definition and place a forward
    256 declaration of it in the header beside the definition of the virtual type.
    257 
    258 Even on the full declaration, no initializer should be used.
    259 Initialization is automatic.
    260 The type id and special virtual members ``size" and ``align" only depend on
    261 the virtual type, which is fixed given the type of the virtual table and
    262 so the compiler fills in a fixed value.
    263 The other virtual members are resolved, using the best match to the member's
    264 name and type, in the same context as the virtual table is declared using
    265 \CFA's normal resolution rules.
    266199
    267200While much of the virtual infrastructure is created, it is currently only used
     
    279212@EXPRESSION@ object, otherwise it returns @0p@ (null pointer).
    280213
    281 \section{Exceptions}
    282 
    283 The syntax for declaring an exception is the same as declaring a structure
    284 except the keyword that is swapped out:
    285 \begin{cfa}
    286 exception TYPE_NAME {
    287         FIELDS
    288 };
    289 \end{cfa}
    290 
    291 Fields are filled in the same way as a structure as well. However an extra
    292 field is added that contains the pointer to the virtual table.
    293 It must be explicitly initialized by the user when the exception is
    294 constructed.
    295 
    296 Here is an example of declaring an exception type along with a virtual table,
    297 assuming the exception has an ``obvious" implementation and a default
    298 virtual table makes sense.
    299 
    300 \begin{minipage}[t]{0.4\textwidth}
    301 Header:
    302 \begin{cfa}
    303 exception Example {
    304         int data;
    305 };
    306 
    307 extern vtable(Example)
    308         example_base_vtable;
    309 \end{cfa}
    310 \end{minipage}
    311 \begin{minipage}[t]{0.6\textwidth}
    312 Source:
    313 \begin{cfa}
    314 vtable(Example) example_base_vtable
    315 \end{cfa}
    316 \vfil
    317 \end{minipage}
    318 
    319 %\subsection{Exception Details}
    320 This is the only interface needed when raising and handling exceptions.
    321 However it is actually a short hand for a more complex
    322 trait based interface.
    323 
    324 The language views exceptions through a series of traits.
    325 If a type satisfies them, then it can be used as an exception. The following
     214\section{Exception}
     215% Leaving until later, hopefully it can talk about actual syntax instead
     216% of my many strange macros. Syntax aside I will also have to talk about the
     217% features all exceptions support.
     218
     219Exceptions are defined by the trait system; there are a series of traits, and
     220if a type satisfies them, then it can be used as an exception. The following
    326221is the base trait all exceptions need to match.
    327222\begin{cfa}
     
    330225};
    331226\end{cfa}
    332 The trait is defined over two types: the exception type and the virtual table
     227The trait is defined over two types, the exception type and the virtual table
    333228type. Each exception type should have a single virtual table type.
    334229There are no actual assertions in this trait because the trait system
     
    336231completing the virtual system). The imaginary assertions would probably come
    337232from a trait defined by the virtual system, and state that the exception type
    338 is a virtual type, is a descendant of @exception_t@ (the base exception type)
    339 and allow the user to find the virtual table type.
     233is a virtual type, is a descendant of @exception_t@ (the base exception type),
     234and note its virtual table type.
    340235
    341236% I did have a note about how it is the programmer's responsibility to make
     
    355250};
    356251\end{cfa}
    357 Both traits ensure a pair of types is an exception type, its virtual table
    358 type
     252Both traits ensure a pair of types are an exception type, its virtual table
     253type,
    359254and defines one of the two default handlers. The default handlers are used
    360255as fallbacks and are discussed in detail in \vref{s:ExceptionHandling}.
     
    365260facing way. So these three macros are provided to wrap these traits to
    366261simplify referring to the names:
    367 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@.
     262@IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@, and @IS_RESUMPTION_EXCEPTION@.
    368263
    369264All three take one or two arguments. The first argument is the name of the
     
    388283These twin operations are the core of \CFA's exception handling mechanism.
    389284This section covers the general patterns shared by the two operations and
    390 then goes on to cover the details each individual operation.
     285then goes on to cover the details of each individual operation.
    391286
    392287Both operations follow the same set of steps.
    393288First, a user raises an exception.
    394 Second, the exception propagates up the stack, searching for a handler.
     289Second, the exception propagates up the stack.
    395290Third, if a handler is found, the exception is caught and the handler is run.
    396291After that control continues at a raise-dependent location.
    397 As an alternate to the third step,
    398 if a handler is not found, a default handler is run and, if it returns,
    399 then control
     292Fourth, if a handler is not found, a default handler is run and, if it returns, then control
    400293continues after the raise.
    401294
    402 The differences between the two operations include how propagation is
    403 performed, where execution continues after an exception is handled
    404 and which default handler is run.
     295%This general description covers what the two kinds have in common.
     296The differences in the two operations include how propagation is performed, where execution continues
     297after an exception is caught and handled, and which default handler is run.
    405298
    406299\subsection{Termination}
    407300\label{s:Termination}
    408 Termination handling is the familiar kind of handling
    409 and used in most programming
     301Termination handling is the familiar EHM and used in most programming
    410302languages with exception handling.
    411303It is a dynamic, non-local goto. If the raised exception is matched and
     
    439331Then propagation starts with the search. \CFA uses a ``first match" rule so
    440332matching is performed with the copied exception as the search key.
    441 It starts from the raise site and proceeds towards base of the stack,
     333It starts from the raise in the throwing function and proceeds towards the base of the stack,
    442334from callee to caller.
    443335At each stack frame, a check is made for termination handlers defined by the
     
    453345\end{cfa}
    454346When viewed on its own, a try statement simply executes the statements
    455 in the \snake{GUARDED_BLOCK} and when those are finished,
     347in the \snake{GUARDED_BLOCK}, and when those are finished,
    456348the try statement finishes.
    457349
     
    479371termination exception types.
    480372The global default termination handler performs a cancellation
    481 (as described in \vref{s:Cancellation})
    482 on the current stack with the copied exception.
    483 Since it is so general, a more specific handler can be defined,
    484 overriding the default behaviour for the specific exception types.
     373(see \vref{s:Cancellation} for the justification) on the current stack with the copied exception.
     374Since it is so general, a more specific handler is usually
     375defined, possibly with a detailed message, and used for specific exception type, effectively overriding the default handler.
    485376
    486377\subsection{Resumption}
    487378\label{s:Resumption}
    488379
    489 Resumption exception handling is less familar form of exception handling,
    490 but is
     380Resumption exception handling is the less familar EHM, but is
    491381just as old~\cite{Goodenough75} and is simpler in many ways.
    492382It is a dynamic, non-local function call. If the raised exception is
     
    497387function once the error is corrected, and
    498388ignorable events, such as logging where nothing needs to happen and control
    499 should always continue from the raise site.
    500 
    501 Except for the changes to fit into that pattern, resumption exception
    502 handling is symmetric with termination exception handling, by design
    503 (see \autoref{s:Termination}).
     389should always continue from the raise point.
    504390
    505391A resumption raise is started with the @throwResume@ statement:
     
    507393throwResume EXPRESSION;
    508394\end{cfa}
    509 % The new keywords are currently ``experimental" and not used in this work.
    510 It works much the same way as the termination raise, except the
    511 type must satisfy the \snake{is_resumption_exception} that uses the
    512 default handler: \defaultResumptionHandler.
    513 This can be specialized for particular exception types.
    514 
    515 At run-time, no exception copy is made. Since
     395\todo{Decide on a final set of keywords and use them everywhere.}
     396It works much the same way as the termination throw.
     397The expression must return a reference to a resumption exception,
     398where the resumption exception is any type that satisfies the trait
     399@is_resumption_exception@ at the call site.
     400The assertions from this trait are available to
     401the exception system while handling the exception.
     402
     403At run-time, no exception copy is made, since
    516404resumption does not unwind the stack nor otherwise remove values from the
    517 current scope, there is no need to manage memory to keep the exception
    518 allocated.
    519 
    520 Then propagation starts with the search,
    521 following the same search path as termination,
    522 from the raise site to the base of stack and top of try statement to bottom.
    523 However, the handlers on try statements are defined by @catchResume@ clauses.
     405current scope, so there is no need to manage memory to keep the exception in scope.
     406
     407Then propagation starts with the search. It starts from the raise in the
     408resuming function and proceeds towards the base of the stack,
     409from callee to caller.
     410At each stack frame, a check is made for resumption handlers defined by the
     411@catchResume@ clauses of a @try@ statement.
    524412\begin{cfa}
    525413try {
     
    531419}
    532420\end{cfa}
    533 Note that termination handlers and resumption handlers may be used together
     421% PAB, you say this above.
     422% When a try statement is executed, it simply executes the statements in the
     423% @GUARDED_BLOCK@ and then finishes.
     424%
     425% However, while the guarded statements are being executed, including any
     426% invoked functions, all the handlers in these statements are included in the
     427% search path.
     428% Hence, if a resumption exception is raised, these handlers may be matched
     429% against the exception and may handle it.
     430%
     431% Exception matching checks the handler in each catch clause in the order
     432% they appear, top to bottom. If the representation of the raised exception type
     433% is the same or a descendant of @EXCEPTION_TYPE@$_i$, then @NAME@$_i$
     434% (if provided) is bound to a pointer to the exception and the statements in
     435% @HANDLER_BLOCK@$_i$ are executed.
     436% If control reaches the end of the handler, execution continues after the
     437% the raise statement that raised the handled exception.
     438%
     439% Like termination, if no resumption handler is found during the search,
     440% then the default handler (\defaultResumptionHandler) visible at the raise
     441% statement is called. It will use the best match at the raise sight according
     442% to \CFA's overloading rules. The default handler is
     443% passed the exception given to the raise. When the default handler finishes
     444% execution continues after the raise statement.
     445%
     446% There is a global @defaultResumptionHandler{} is polymorphic over all
     447% resumption exceptions and performs a termination throw on the exception.
     448% The \defaultTerminationHandler{} can be overridden by providing a new
     449% function that is a better match.
     450
     451The @GUARDED_BLOCK@ and its associated nested guarded statements work the same
     452for resumption as for termination, as does exception matching at each
     453@catchResume@. Similarly, if no resumption handler is found during the search,
     454then the currently visible default handler (\defaultResumptionHandler) is
     455called and control continues after the raise statement if it returns. Finally,
     456there is also a global @defaultResumptionHandler@, which can be overridden,
     457that is polymorphic over all resumption exceptions but performs a termination
     458throw on the exception rather than a cancellation.
     459
     460Throwing the exception in @defaultResumptionHandler@ has the positive effect of
     461walking the stack a second time for a recovery handler. Hence, a programmer has
     462two chances for help with a problem, fixup or recovery, should either kind of
     463handler appear on the stack. However, this dual stack walk leads to following
     464apparent anomaly:
     465\begin{cfa}
     466try {
     467        throwResume E;
     468} catch (E) {
     469        // this handler runs
     470}
     471\end{cfa}
     472because the @catch@ appears to handle a @throwResume@, but a @throwResume@ only
     473matches with @catchResume@. The anomaly results because the unmatched
     474@catchResuem@, calls @defaultResumptionHandler@, which in turn throws @E@.
     475
     476% I wonder if there would be some good central place for this.
     477Note, termination and resumption handlers may be used together
    534478in a single try statement, intermixing @catch@ and @catchResume@ freely.
    535479Each type of handler only interacts with exceptions from the matching
    536480kind of raise.
    537 Like @catch@ clauses, @catchResume@ clauses have no effect if an exception
    538 is not raised.
    539 
    540 The matching rules are exactly the same as well.
    541 The first major difference here is that after
    542 @EXCEPTION_TYPE@$_i$ is matched and @NAME@$_i$ is bound to the exception,
    543 @HANDLER_BLOCK@$_i$ is executed right away without first unwinding the stack.
    544 After the block has finished running control jumps to the raise site, where
    545 the just handled exception came from, and continues executing after it,
    546 not after the try statement.
    547481
    548482\subsubsection{Resumption Marking}
     
    552486and run, its try block (the guarded statements) and every try statement
    553487searched before it are still on the stack. There presence can lead to
    554 the recursive resumption problem.\cite{Buhr00a}
    555 % Other possible citation is MacLaren77, but the form is different.
     488the \emph{recursive resumption problem}.
    556489
    557490The recursive resumption problem is any situation where a resumption handler
     
    567500When this code is executed, the guarded @throwResume@ starts a
    568501search and matches the handler in the @catchResume@ clause. This
    569 call is placed on the stack above the try-block.
    570 Now the second raise in the handler searches the same try block,
    571 matches again and then puts another instance of the
     502call is placed on the stack above the try-block. Now the second raise in the handler
     503searches the same try block, matches, and puts another instance of the
    572504same handler on the stack leading to infinite recursion.
    573505
    574 While this situation is trivial and easy to avoid, much more complex cycles
    575 can form with multiple handlers and different exception types.
     506While this situation is trivial and easy to avoid, much more complex cycles can
     507form with multiple handlers and different exception types.  The key point is
     508that the programmer's intuition expects every raise in a handler to start
     509searching \emph{below} the @try@ statement, making it difficult to understand
     510and fix the problem.
     511
    576512To prevent all of these cases, each try statement is ``marked" from the
    577 time the exception search reaches it to either when a handler completes
    578 handling that exception or when the search reaches the base
     513time the exception search reaches it to either when a matching handler
     514completes or when the search reaches the base
    579515of the stack.
    580516While a try statement is marked, its handlers are never matched, effectively
     
    588524for instance, marking just the handlers that caught the exception,
    589525would also prevent recursive resumption.
    590 However, the rules selected mirrors what happens with termination,
    591 so this reduces the amount of rules and patterns a programmer has to know.
    592 
    593 The marked try statements are the ones that would be removed from
     526However, the rule selected mirrors what happens with termination,
     527and hence, matches programmer intuition that a raise searches below a try.
     528
     529In detail, the marked try statements are the ones that would be removed from
    594530the stack for a termination exception, \ie those on the stack
    595531between the handler and the raise statement.
     
    657593
    658594\subsection{Comparison with Reraising}
    659 In languages without conditional catch, that is no ability to match an
    660 exception based on something other than its type, it can be mimicked
    661 by matching all exceptions of the right type, checking any additional
    662 conditions inside the handler and re-raising the exception if it does not
    663 match those.
    664 
    665 Here is a minimal example comparing both patterns, using @throw;@
    666 (no argument) to start a re-raise.
     595Without conditional catch, the only approach to match in more detail is to reraise
     596the exception after it has been caught, if it could not be handled.
    667597\begin{center}
    668 \begin{tabular}{l r}
    669 \begin{cfa}
    670 try {
    671     do_work_may_throw();
    672 } catch(exception_t * exc ;
    673                 can_handle(exc)) {
    674     handle(exc);
    675 }
    676 
    677 
    678 
     598\begin{tabular}{l|l}
     599\begin{cfa}
     600try {
     601        do_work_may_throw();
     602} catch(excep_t * ex; can_handle(ex)) {
     603
     604        handle(ex);
     605
     606
     607
     608}
    679609\end{cfa}
    680610&
    681611\begin{cfa}
    682612try {
    683     do_work_may_throw();
    684 } catch(exception_t * exc) {
    685     if (can_handle(exc)) {
    686         handle(exc);
    687     } else {
    688         throw;
    689     }
    690 }
    691 \end{cfa}
    692 \end{tabular}
    693 \end{center}
    694 At first glance catch-and-reraise may appear to just be a quality of life
    695 feature, but there are some significant differences between the two
    696 stratagies.
    697 
    698 A simple difference that is more important for \CFA than many other languages
    699 is that the raise site changes, with a re-raise but does not with a
    700 conditional catch.
    701 This is important in \CFA because control returns to the raise site to run
    702 the per-site default handler. Because of this only a conditional catch can
    703 allow the original raise to continue.
    704 
    705 The more complex issue comes from the difference in how conditional
    706 catches and re-raises handle multiple handlers attached to a single try
    707 statement. A conditional catch will continue checking later handlers while
    708 a re-raise will skip them.
    709 If the different handlers could handle some of the same exceptions,
    710 translating a try statement that uses one to use the other can quickly
    711 become non-trivial:
    712 
    713 \noindent
    714 Original, with conditional catch:
    715 \begin{cfa}
    716 ...
    717 } catch (an_exception * e ; check_a(e)) {
    718         handle_a(e);
    719 } catch (exception_t * e ; check_b(e)) {
    720         handle_b(e);
    721 }
    722 \end{cfa}
    723 Translated, with re-raise:
    724 \begin{cfa}
    725 ...
    726 } catch (exception_t * e) {
    727         an_exception * an_e = (virtual an_exception *)e;
    728         if (an_e && check_a(an_e)) {
    729                 handle_a(an_e);
    730         } else if (check_b(e)) {
    731                 handle_b(e);
     613        do_work_may_throw();
     614} catch(excep_t * ex) {
     615        if (can_handle(ex)) {
     616                handle(ex);
    732617        } else {
    733618                throw;
     
    735620}
    736621\end{cfa}
    737 (There is a simpler solution if @handle_a@ never raises exceptions,
    738 using nested try statements.)
    739 
    740 % } catch (an_exception * e ; check_a(e)) {
    741 %     handle_a(e);
    742 % } catch (exception_t * e ; !(virtual an_exception *)e && check_b(e)) {
    743 %     handle_b(e);
    744 % }
     622\end{tabular}
     623\end{center}
     624Notice catch-and-reraise increases complexity by adding additional data and
     625code to the exception process. Nevertheless, catch-and-reraise can simulate
     626conditional catch straightforwardly, when exceptions are disjoint, \ie no
     627inheritance.
     628
     629However, catch-and-reraise simulation becomes unusable for exception inheritance.
     630\begin{flushleft}
     631\begin{cfa}[xleftmargin=6pt]
     632exception E1;
     633exception E2(E1); // inheritance
     634\end{cfa}
     635\begin{tabular}{l|l}
     636\begin{cfa}
     637try {
     638        ... foo(); ... // raise E1/E2
     639        ... bar(); ... // raise E1/E2
     640} catch( E2 e; e.rtn == foo ) {
     641        ...
     642} catch( E1 e; e.rtn == foo ) {
     643        ...
     644} catch( E1 e; e.rtn == bar ) {
     645        ...
     646}
     647
     648\end{cfa}
     649&
     650\begin{cfa}
     651try {
     652        ... foo(); ...
     653        ... bar(); ...
     654} catch( E2 e ) {
     655        if ( e.rtn == foo ) { ...
     656        } else throw; // reraise
     657} catch( E1 e ) {
     658        if (e.rtn == foo) { ...
     659        } else if (e.rtn == bar) { ...
     660        else throw; // reraise
     661}
     662\end{cfa}
     663\end{tabular}
     664\end{flushleft}
     665The derived exception @E2@ must be ordered first in the catch list, otherwise
     666the base exception @E1@ catches both exceptions. In the catch-and-reraise code
     667(right), the @E2@ handler catches exceptions from both @foo@ and
     668@bar@. However, the reraise misses the following catch clause. To fix this
     669problem, an enclosing @try@ statement is need to catch @E2@ for @bar@ from the
     670reraise, and its handler must duplicate the inner handler code for @bar@. To
     671generalize, this fix for any amount of inheritance and complexity of try
     672statement requires a technique called \emph{try-block
     673splitting}~\cite{Krischer02}, which is not discussed in this thesis. It is
     674sufficient to state that conditional catch is more expressive than
     675catch-and-reraise in terms of complexity.
     676
     677\begin{comment}
     678That is, they have the same behaviour in isolation.
     679Two things can expose differences between these cases.
     680
     681One is the existence of multiple handlers on a single try statement.
     682A reraise skips all later handlers for a try statement but a conditional
     683catch does not.
     684% Hence, if an earlier handler contains a reraise later handlers are
     685% implicitly skipped, with a conditional catch they are not.
     686Still, they are equivalently powerful,
     687both can be used two mimic the behaviour of the other,
     688as reraise can pack arbitrary code in the handler and conditional catches
     689can put arbitrary code in the predicate.
     690% I was struggling with a long explanation about some simple solutions,
     691% like repeating a condition on later handlers, and the general solution of
     692% merging everything together. I don't think it is useful though unless its
     693% for a proof.
     694% https://en.cppreference.com/w/cpp/language/throw
     695
     696The question then becomes ``Which is a better default?"
     697We believe that not skipping possibly useful handlers is a better default.
     698If a handler can handle an exception it should and if the handler can not
     699handle the exception then it is probably safer to have that explicitly
     700described in the handler itself instead of implicitly described by its
     701ordering with other handlers.
     702% Or you could just alter the semantics of the throw statement. The handler
     703% index is in the exception so you could use it to know where to start
     704% searching from in the current try statement.
     705% No place for the `goto else;` metaphor.
     706
     707The other issue is all of the discussion above assumes that the only
     708way to tell apart two raises is the exception being raised and the remaining
     709search path.
     710This is not true generally, the current state of the stack can matter in
     711a number of cases, even only for a stack trace after an program abort.
     712But \CFA has a much more significant need of the rest of the stack, the
     713default handlers for both termination and resumption.
     714
     715% For resumption it turns out it is possible continue a raise after the
     716% exception has been caught, as if it hadn't been caught in the first place.
     717This becomes a problem combined with the stack unwinding used in termination
     718exception handling.
     719The stack is unwound before the handler is installed, and hence before any
     720reraises can run. So if a reraise happens the previous stack is gone,
     721the place on the stack where the default handler was supposed to run is gone,
     722if the default handler was a local function it may have been unwound too.
     723There is no reasonable way to restore that information, so the reraise has
     724to be considered as a new raise.
     725This is the strongest advantage conditional catches have over reraising,
     726they happen before stack unwinding and avoid this problem.
     727
     728% The one possible disadvantage of conditional catch is that it runs user
     729% code during the exception search. While this is a new place that user code
     730% can be run destructors and finally clauses are already run during the stack
     731% unwinding.
    745732%
    746 % } catch (an_exception * e)
    747 %   if (check_a(e)) {
    748 %     handle_a(e);
    749 %   } else throw;
    750 % } catch (exception_t * e)
    751 %   if (check_b(e)) {
    752 %     handle_b(e);
    753 %   } else throw;
    754 % }
    755 In similar simple examples translating from re-raise to conditional catch
    756 takes less code but it does not have a general trivial solution either.
    757 
    758 So, given that the two patterns do not trivially translate into each other,
    759 it becomes a matter of which on should be encouraged and made the default.
    760 From the premise that if a handler that could handle an exception then it
    761 should, it follows that checking as many handlers as possible is preferred.
    762 So conditional catch and checking later handlers is a good default.
     733% https://www.cplusplus.com/reference/exception/current_exception/
     734%   `exception_ptr current_exception() noexcept;`
     735% https://www.python.org/dev/peps/pep-0343/
     736\end{comment}
    763737
    764738\section{Finally Clauses}
     
    776750The @FINALLY_BLOCK@ is executed when the try statement is removed from the
    777751stack, including when the @GUARDED_BLOCK@ finishes, any termination handler
    778 finishes or during an unwind.
     752finishes, or during an unwind.
    779753The only time the block is not executed is if the program is exited before
    780754the stack is unwound.
     
    796770they have their own strengths, similar to top-level function and lambda
    797771functions with closures.
    798 Destructors take more work to create, but if there is clean-up code
     772Destructors take more work for their creation, but if there is clean-up code
    799773that needs to be run every time a type is used, they are much easier
    800 to set-up for each use. % It's automatic.
     774to set-up.
    801775On the other hand finally clauses capture the local context, so is easy to
    802776use when the clean-up is not dependent on the type of a variable or requires
     
    814788raise, this exception is not used in matching only to pass information about
    815789the cause of the cancellation.
    816 Finally, as no handler is provided, there is no default handler.
     790Finaly, since a cancellation only unwinds and forwards, there is no default handler.
    817791
    818792After @cancel_stack@ is called the exception is copied into the EHM's memory
     
    825799After the main stack is unwound there is a program-level abort.
    826800
    827 The first reason for this behaviour is for sequential programs where there
    828 is only one stack, and hence to stack to pass information to.
    829 Second, even in concurrent programs, the main stack has no dependency
    830 on another stack and no reliable way to find another living stack.
    831 Finally, keeping the same behaviour in both sequential and concurrent
    832 programs is simple and easy to understand.
     801The reasons for this semantics in a sequential program is that there is no more code to execute.
     802This semantics also applies to concurrent programs, too, even if threads are running.
     803That is, if any threads starts a cancellation, it implies all threads terminate.
     804Keeping the same behaviour in sequential and concurrent programs is simple.
     805Also, even in concurrent programs there may not currently be any other stacks
     806and even if other stacks do exist, main has no way to know where they are.
    833807
    834808\paragraph{Thread Stack}
     
    860834
    861835With explicit join and a default handler that triggers a cancellation, it is
    862 possible to cascade an error across any number of threads,
    863 alternating between the resumption (possibly termination) and cancellation,
    864 cleaning up each
     836possible to cascade an error across any number of threads, cleaning up each
    865837in turn, until the error is handled or the main thread is reached.
    866838
     
    875847caller's context and passes it to the internal report.
    876848
    877 A coroutine only knows of two other coroutines,
    878 its starter and its last resumer.
     849A coroutine only knows of two other coroutines, its starter and its last resumer.
    879850The starter has a much more distant connection, while the last resumer just
    880851(in terms of coroutine state) called resume on this coroutine, so the message
     
    882853
    883854With a default handler that triggers a cancellation, it is possible to
    884 cascade an error across any number of coroutines,
    885 alternating between the resumption (possibly termination) and cancellation,
    886 cleaning up each in turn,
     855cascade an error across any number of coroutines, cleaning up each in turn,
    887856until the error is handled or a thread stack is reached.
     857
     858\PAB{Part of this I do not understand. A cancellation cannot be caught. But you
     859talk about handling a cancellation in the last sentence. Which is correct?}
  • doc/theses/andrew_beach_MMath/future.tex

    r5a40e4e rdd1cc02  
    22\label{c:future}
    33
    4 The following discussion covers both possible interesting research
    5 that could follow from this work as long as simple implementation
    6 improvements.
    7 
    84\section{Language Improvements}
    9 
     5\todo{Future/Language Improvements seems to have gotten mixed up. It is
     6presented as ``waiting on language improvements" but really its more
     7non-research based impovements.}
    108\CFA is a developing programming language. As such, there are partially or
    11 unimplemented features (including several broken components)
    12 that I had to workaround while building the EHM largely in
    13 the \CFA language (some C components). Below are a few of these issues
    14 and how implementing/fixing them would affect the EHM.
    15 In addition there are some simple improvements that had no interesting
    16 research attached to them but would make using the language easier.
     9unimplemented features of the language (including several broken components)
     10that I had to workaround while building an exception handling system largely in
     11the \CFA language (some C components).  The following are a few of these
     12issues, and once implemented/fixed, how they would affect the exception system.
    1713\begin{itemize}
     14\item
     15The implementation of termination is not portable because it includes
     16hand-crafted assembly statements.
     17The existing compilers cannot translate that for other platforms and those
     18sections must be ported by hand to
     19support more hardware architectures, such as the ARM processor.
    1820\item
    1921Due to a type-system problem, the catch clause cannot bind the exception to a
     
    2224result in little or no change in the exception system but simplify usage.
    2325\item
    24 The @copy@ function in the exception virtual table is an adapter to address
    25 some limitations in the \CFA copy constructor. If the copy constructor is
    26 improved it can be used directly without the adapter.
    27 \item
    2826Termination handlers cannot use local control-flow transfers, \eg by @break@,
    2927@return@, \etc. The reason is that current code generation hoists a handler
    3028into a nested function for convenience (versus assemble-code generation at the
    31 try statement). Hence, when the handler runs, it can still access local
    32 variables in the lexical scope of the try statement. Still, it does mean
    33 that seemingly local control flow is not in fact local and crosses a function
    34 boundary.
    35 Making the termination handlers code within the surrounding
    36 function would remove this limitation.
    37 % Try blocks are much more difficult to do practically (requires our own
    38 % assembly) and resumption handlers have some theoretical complexity.
     29@try@ statement). Hence, when the handler runs, its code is not in the lexical
     30scope of the @try@ statement, where the local control-flow transfers are
     31meaningful.
    3932\item
    4033There is no detection of colliding unwinds. It is possible for clean-up code
    4134run during an unwind to trigger another unwind that escapes the clean-up code
    4235itself; such as a termination exception caught further down the stack or a
    43 cancellation. There do exist ways to handle this case, but currently there is
    44 no detection and the first unwind will simply be forgotten, often leaving
     36cancellation. There do exist ways to handle this but currently they are not
     37even detected and the first unwind will simply be forgotten, often leaving
    4538it in a bad state.
    4639\item
    47 Finally, the exception system has not had a lot of programmer testing.
    48 More time with encouraged usage will reveal new
    49 quality of life upgrades that can be made.
     40Also the exception system did not have a lot of time to be tried and tested.
     41So just letting people use the exception system more will reveal new
     42quality of life upgrades that can be made with time.
    5043\end{itemize}
    5144
     
    5447project, but was thrust upon it to do exception inheritance; hence, only
    5548minimal work is done. A draft for a complete virtual system is available but
    56 not finalized. A future \CFA project is to complete that work and then
     49it is not finalized. A future \CFA project is to complete that work and then
    5750update the exception system that uses the current version.
    5851
     
    6053exception traits. The most important one is an assertion to check one virtual
    6154type is a child of another. This check precisely captures many of the
    62 current ad-hoc correctness requirements.
    63 
    64 Other features of the virtual system could also remove some of the
    65 special cases around exception virtual tables, such as the generation
    66 of the @msg@ function, could be removed.
     55correctness requirements.
    6756
    6857The full virtual system might also include other improvement like associated
    6958types to allow traits to refer to types not listed in their header. This
    7059feature allows exception traits to not refer to the virtual-table type
    71 explicitly, removing the need for the current interface macros,
    72 such as @EHM_IS_EXCEPTION@.
     60explicitly, removing the need for the current interface macros.
    7361
    7462\section{Additional Raises}
     
    8674Non-local/concurrent raise requires more
    8775coordination between the concurrency system
    88 and the exception system. Many of the interesting design decisions center
     76and the exception system. Many of the interesting design decisions centre
    8977around masking, \ie controlling which exceptions may be thrown at a stack. It
    9078would likely require more of the virtual system and would also effect how
     
    10593Checked exceptions make exceptions part of a function's type by adding an
    10694exception signature. An exception signature must declare all checked
    107 exceptions that could propagate from the function, either because they were
    108 raised inside the function or came from a sub-function. This improves safety
     95exceptions that could propagate from the function (either because they were
     96raised inside the function or came from a sub-function). This improves safety
    10997by making sure every checked exception is either handled or consciously
    11098passed on.
    11199
    112100However checked exceptions were never seriously considered for this project
    113 because they have significant trade-offs in usability and code reuse in
     101because they have significant trade-offs in usablity and code reuse in
    114102exchange for the increased safety.
    115103These trade-offs are most problematic when trying to pass exceptions through
     
    141129not support a successful-exiting stack-search without doing an unwind.
    142130Workarounds are possible but awkward. Ideally an extension to libunwind could
    143 be made, but that would either require separate maintenance or gaining enough
    144 support to have it folded into the official library itself.
     131be made, but that would either require separate maintenance or gain enough
     132support to have it folded into the standard.
    145133
    146134Also new techniques to skip previously searched parts of the stack need to be
     
    170158to leave the handler.
    171159Currently, mimicking this behaviour in \CFA is possible by throwing a
    172 termination exception inside a resumption handler.
     160termination inside a resumption handler.
    173161
    174162% Maybe talk about the escape; and escape CONTROL_STMT; statements or how
  • doc/theses/andrew_beach_MMath/implement.tex

    r5a40e4e rdd1cc02  
    1414\label{s:VirtualSystem}
    1515% Virtual table rules. Virtual tables, the pointer to them and the cast.
    16 While the \CFA virtual system currently has only one public features, virtual
    17 cast and virtual tables,
    18 % ??? refs (see the virtual cast feature \vpageref{p:VirtualCast}),
    19 substantial structure is required to support them,
     16While the \CFA virtual system currently has only one public feature, virtual
     17cast (see the virtual cast feature \vpageref{p:VirtualCast}),
     18substantial structure is required to support it,
    2019and provide features for exception handling and the standard library.
    2120
    2221\subsection{Virtual Type}
    23 A virtual type~(see \autoref{s:virtuals}) has a pointer to a virtual table,
    24 called the \emph{virtual-table pointer},
    25 which binds each instance of a virtual type to a virtual table.
    26 Internally, the field is called \snake{virtual_table}
    27 and is fixed after construction.
    28 This pointer is also the table's id and how the system accesses the
     22Virtual types only have one change to their structure: the addition of a
     23pointer to the virtual table, which is called the \emph{virtual-table pointer}.
     24Internally, the field is called \snake{virtual_table}.
     25The field is fixed after construction. It is always the first field in the
     26structure so that its location is always known.
     27\todo{Talk about constructors for virtual types (after they are working).}
     28
     29The virtual table pointer binds an instance of a virtual type
     30to a virtual table.
     31The pointer is also the table's id and how the system accesses the
    2932virtual table and the virtual members there.
    30 It is always the first field in the
    31 structure so that its location is always known.
    32 
    33 % We have no special rules for these constructors.
    34 Virtual table pointers are passed to the constructors of virtual types
    35 as part of field-by-field construction.
    3633
    3734\subsection{Type Id}
    3835Every virtual type has a unique id.
    39 These are used in type equality, to check if the representation of two values
    40 are the same, and to access the type's type information.
    41 This uniqueness means across a program composed of multiple translation
    42 units (TU), not uniqueness across all programs or even across multiple
    43 processes on the same machine.
    44 
    45 Our approach for program uniqueness is using a static declaration for each
    46 type id, where the run-time storage address of that variable is guaranteed to
    47 be unique during program execution.
    48 The type id storage can also be used for other purposes,
    49 and is used for type information.
    50 
    51 The problem is that a type id may appear in multiple TUs that compose a
    52 program (see \autoref{ss:VirtualTable}); so the initial solution would seem
    53 to be make it external in each translation unit. Hovever, the type id must
    54 have a declaration in (exactly) one of the TUs to create the storage.
    55 No other declaration related to the virtual type has this property, so doing
    56 this through standard C declarations would require the user to do it manually.
    57 
    58 Instead the linker is used to handle this problem.
    59 % I did not base anything off of C++17; they are solving the same problem.
    60 A new feature has been added to \CFA for this purpose, the special attribute
    61 \snake{cfa_linkonce}, which uses the special section @.gnu.linkonce@.
    62 When used as a prefix (\eg @.gnu.linkonce.example@) the linker does
    63 not combine these sections, but instead discards all but one with the same
    64 full name.
    65 
    66 So each type id must be given a unique section name with the linkonce
    67 prefix. Luckily \CFA already has a way to get unique names, the name mangler.
    68 For example, this could be written directly in \CFA:
    69 \begin{cfa}
    70 __attribute__((cfa_linkonce)) void f() {}
    71 \end{cfa}
    72 This is translated to:
    73 \begin{cfa}
    74 __attribute__((section(".gnu.linkonce._X1fFv___1"))) void _X1fFv___1() {}
    75 \end{cfa}
    76 This is done internally to access the name manglers.
    77 This attribute is useful for other purposes, any other place a unique
    78 instance required, and should eventually be made part of a public and
    79 stable feature in \CFA.
    80 
    81 \subsection{Type Information}
    82 
    83 There is data stored at the type id's declaration, the type information.
     36Type ids can be compared for equality,
     37which checks if the types reperented are the same,
     38or used to access the type's type information.
    8439The type information currently is only the parent's type id or, if the
    8540type has no parent, the null pointer.
     41
     42The id's are implemented as pointers to the type's type information instance.
     43Dereferencing the pointer gets the type information.
    8644The ancestors of a virtual type are found by traversing type ids through
    8745the type information.
    88 An example using helper macros looks like:
     46The information pushes the issue of creating a unique value (for
     47the type id) to the problem of creating a unique instance (for type
     48information), which the linker can solve.
     49
     50The advanced linker support is used here to avoid having to create
     51a new declaration to attach this data to.
     52With C/\CFA's header/implementation file divide for something to appear
     53exactly once it must come from a declaration that appears in exactly one
     54implementation file; the declarations in header files may exist only once
     55they can be included in many different translation units.
     56Therefore, structure's declaration will not work.
     57Neither will attaching the type information to the virtual table -- although
     58a vtable declarations are in implemention files they are not unique, see
     59\autoref{ss:VirtualTable}.
     60Instead the same type information is generated multiple times and then
     61the new attribute \snake{cfa_linkone} is used to removed duplicates.
     62
     63Type information is constructed as follows:
     64\begin{enumerate}
     65\item
     66Use the type's name to generate a name for the type information structure.
     67This is saved so it may be reused.
     68\item
     69Generate a new structure definition to store the type
     70information. The layout is the same in each case, just the parent's type id,
     71but the types used change from instance to instance.
     72The generated name is used for both this structure and, if relivant, the
     73parent pointer.
     74If the virtual type is polymorphic then the type information structure is
     75polymorphic as well, with the same polymorphic arguments.
     76\item
     77A seperate name for instances is generated from the type's name.
     78\item
     79The definition is generated and initialised.
     80The parent id is set to the null pointer or to the address of the parent's
     81type information instance. Name resolution handles the rest.
     82\item
     83\CFA's name mangler does its regular name mangling encoding the type of
     84the declaration into the instance name. This gives a completely unique name
     85including different instances of the same polymorphic type.
     86\end{enumerate}
     87\todo{The list is making me realise, some of this isn't ordered.}
     88
     89Writing that code manually, with helper macros for the early name mangling,
     90would look like this:
    8991\begin{cfa}
    9092struct INFO_TYPE(TYPE) {
     
    98100\end{cfa}
    99101
    100 Type information is constructed as follows:
    101 \begin{enumerate}[nosep]
    102 \item
    103 Use the type's name to generate a name for the type information structure,
    104 which is saved so it can be reused.
    105 \item
    106 Generate a new structure definition to store the type
    107 information. The layout is the same in each case, just the parent's type id,
    108 but the types used change from instance to instance.
    109 The generated name is used for both this structure and, if relevant, the
    110 parent pointer.
    111 If the virtual type is polymorphic then the type information structure is
    112 polymorphic as well, with the same polymorphic arguments.
    113 \item
    114 A separate name for instances is generated from the type's name.
    115 \item
    116 The definition is generated and initialized.
    117 The parent id is set to the null pointer or to the address of the parent's
    118 type information instance. Name resolution handles the rest.
    119 \item
    120 \CFA's name mangler does its regular name mangling encoding the type of
    121 the declaration into the instance name.
    122 This process gives a completely unique name
    123 including different instances of the same polymorphic type.
    124 \end{enumerate}
    125 
    126 Writing that code manually, with helper macros for the early name mangling,
    127 would look like this:
    128 \begin{cfa}
    129 struct INFO_TYPE(TYPE) {
    130         INFO_TYPE(PARENT) const * parent;
    131 };
    132 
    133 __attribute__((cfa_linkonce))
    134 INFO_TYPE(TYPE) const INFO_NAME(TYPE) = {
    135         &INFO_NAME(PARENT),
    136 };
    137 \end{cfa}
    138 
    139 \begin{comment}
    140102\subsubsection{\lstinline{cfa\_linkonce} Attribute}
    141 % I just realized: This is an extension of the inline keyword.
     103% I just realised: This is an extension of the inline keyword.
    142104% An extension of C's at least, it is very similar to C++'s.
    143105Another feature added to \CFA is a new attribute: \texttt{cfa\_linkonce}.
     
    164126everything that comes after the special prefix, then only one is used
    165127and the other is discarded.
    166 \end{comment}
    167128
    168129\subsection{Virtual Table}
     
    175136below.
    176137
    177 The layout always comes in three parts (see \autoref{f:VirtualTableLayout}).
     138The layout always comes in three parts.
     139\todo{Add labels to the virtual table layout figure.}
    178140The first section is just the type id at the head of the table. It is always
    179141there to ensure that it can be found even when the accessing code does not
     
    181143The second section are all the virtual members of the parent, in the same
    182144order as they appear in the parent's virtual table. Note that the type may
    183 change slightly as references to the ``this" change. This is limited to
     145change slightly as references to the ``this" will change. This is limited to
    184146inside pointers/references and via function pointers so that the size (and
    185147hence the offsets) are the same.
     
    188150
    189151\begin{figure}
    190 \begin{center}
    191152\input{vtable-layout}
    192 \end{center}
    193153\caption{Virtual Table Layout}
    194154\label{f:VirtualTableLayout}
     155\todo*{Improve the Virtual Table Layout diagram.}
    195156\end{figure}
    196157
     
    215176type's alignment, is set using an @alignof@ expression.
    216177
    217 Most of these tools are already inside the compiler. Using simple
    218 code transformations early on in compilation, allows most of that work to be
    219 handed off to the existing tools. \autoref{f:VirtualTableTransformation}
    220 shows an example transformation, this example shows an exception virtual table.
    221 It also shows the transformation on the full declaration.
    222 For a forward declaration, the @extern@ keyword is preserved and the
    223 initializer is not added.
    224 
    225 \begin{figure}[htb]
    226 \begin{cfa}
    227 vtable(example_type) example_name;
    228 \end{cfa}
    229 \transformline
    230 % Check mangling.
    231 \begin{cfa}
    232 const struct example_type_vtable example_name = {
    233         .__cfavir_typeid : &__cfatid_example_type,
    234         .size : sizeof(example_type),
    235         .copy : copy,
    236         .^?{} : ^?{},
    237         .msg : msg,
    238 };
    239 \end{cfa}
    240 \caption{Virtual Table Transformation}
    241 \label{f:VirtualTableTransformation}
    242 \end{figure}
    243 
    244 \subsection{Concurrency Integration}
     178\subsubsection{Concurrency Integration}
    245179Coroutines and threads need instances of @CoroutineCancelled@ and
    246180@ThreadCancelled@ respectively to use all of their functionality. When a new
     
    249183at the definition of the main function.
    250184
    251 These transformations are shown through code re-writing in
    252 \autoref{f:CoroutineTypeTransformation} and
    253 \autoref{f:CoroutineMainTransformation}.
    254 Threads use the same pattern, with some names and types changed.
    255 In both cases, the original declaration is not modified,
     185This is showned through code re-writing in
     186\autoref{f:ConcurrencyTypeTransformation} and
     187\autoref{f:ConcurrencyMainTransformation}.
     188In both cases the original declaration is not modified,
    256189only new ones are added.
    257190
    258 \begin{figure}[htb]
     191\begin{figure}
    259192\begin{cfa}
    260193coroutine Example {
     
    274207extern CoroutineCancelled_vtable & _default_vtable;
    275208\end{cfa}
    276 \caption{Coroutine Type Transformation}
    277 \label{f:CoroutineTypeTransformation}
     209\caption{Concurrency Type Transformation}
     210\label{f:ConcurrencyTypeTransformation}
    278211\end{figure}
    279212
    280 \begin{figure}[htb]
     213\begin{figure}
    281214\begin{cfa}
    282215void main(Example & this) {
     
    296229        &_default_vtable_object_declaration;
    297230\end{cfa}
    298 \caption{Coroutine Main Transformation}
    299 \label{f:CoroutineMainTransformation}
     231\caption{Concurrency Main Transformation}
     232\label{f:ConcurrencyMainTransformation}
    300233\end{figure}
    301234
     
    309242\begin{cfa}
    310243void * __cfa__virtual_cast(
    311         struct __cfavir_type_id * parent,
    312         struct __cfavir_type_id * const * child );
    313 \end{cfa}
    314 The type id for the target type of the virtual cast is passed in as
    315 @parent@ and
     244        struct __cfavir_type_td parent,
     245        struct __cfavir_type_id const * child );
     246\end{cfa}
     247The type id of target type of the virtual cast is passed in as @parent@ and
    316248the cast target is passed in as @child@.
    317 The generated C code wraps both arguments and the result with type casts.
     249
     250For generated C code wraps both arguments and the result with type casts.
    318251There is also an internal check inside the compiler to make sure that the
    319252target type is a virtual type.
     
    327260
    328261\section{Exceptions}
    329 % The implementation of exception types.
    330 
    331 Creating exceptions can roughly divided into two parts,
    332 the exceptions themselves and the virtual system interactions.
    333 
    334 Creating an exception type is just a matter of prepending the field 
    335 with the virtual table pointer to the list of the fields
    336 (see \autoref{f:ExceptionTypeTransformation}).
    337 
    338 \begin{figure}[htb]
    339 \begin{cfa}
    340 exception new_exception {
    341         // EXISTING FIELDS
    342 };
    343 \end{cfa}
    344 \transformline
    345 \begin{cfa}
    346 struct new_exception {
    347         struct new_exception_vtable const * virtual_table;
    348         // EXISTING FIELDS
    349 };
    350 \end{cfa}
    351 \caption{Exception Type Transformation}
    352 \label{f:ExceptionTypeTransformation}
    353 \end{figure}
    354 
    355 The integration between exceptions and the virtual system is a bit more
    356 complex simply because of the nature of the virtual system prototype.
    357 The primary issue is that the virtual system has no way to detect when it
    358 should generate any of its internal types and data. This is handled by
    359 the exception code, which tells the virtual system when to generate
    360 its components.
    361 
    362 All types associated with a virtual type,
    363 the types of the virtual table and the type id,
    364 are generated when the virtual type (the exception) is first found.
    365 The type id (the instance) is generated with the exception, if it is
    366 a monomorphic type.
    367 However, if the exception is polymorphic, then a different type id has to
    368 be generated for every instance. In this case, generation is delayed
    369 until a virtual table is created.
    370 % There are actually some problems with this, which is why it is not used
    371 % for monomorphic types.
    372 When a virtual table is created and initialized, two functions are created
    373 to fill in the list of virtual members.
    374 The first is a copy function that adapts the exception's copy constructor
    375 to work with pointers, avoiding some issues with the current copy constructor
    376 interface.
    377 Second is the msg function that returns a C-string with the type's name,
    378 including any polymorphic parameters.
     262% Anything about exception construction.
    379263
    380264\section{Unwinding}
     
    390274stack. On function entry and return, unwinding is handled directly by the
    391275call/return code embedded in the function.
    392 
    393 % Discussing normal stack unwinding:
     276In many cases, the position of the instruction pointer (relative to parameter
     277and local declarations) is enough to know the current size of the stack
     278frame.
     279
    394280Usually, the stack-frame size is known statically based on parameter and
    395 local variable declarations. Even for a dynamic stack-size, the information
     281local variable declarations. Even with dynamic stack-size, the information
    396282to determine how much of the stack has to be removed is still contained
    397283within the function.
     
    399285bumping the hardware stack-pointer up or down as needed.
    400286Constructing/destructing values within a stack frame has
    401 a similar complexity but larger constants.
    402 
    403 % Discussing multiple frame stack unwinding:
     287a similar complexity but can add additional work and take longer.
     288
    404289Unwinding across multiple stack frames is more complex because that
    405290information is no longer contained within the current function.
    406 With separate compilation,
    407 a function does not know its callers nor their frame layout.
    408 Even using the return address, that information is encoded in terms of
    409 actions in code, intermixed with the actions required finish the function.
    410 Without changing the main code path it is impossible to select one of those
    411 two groups of actions at the return site.
     291With seperate compilation a function has no way of knowing what its callers
     292are so it can't know how large those frames are.
     293Without altering the main code path it is also hard to pass that work off
     294to the caller.
    412295
    413296The traditional unwinding mechanism for C is implemented by saving a snap-shot
     
    419302This approach is fragile and requires extra work in the surrounding code.
    420303
    421 With respect to the extra work in the surrounding code,
     304With respect to the extra work in the surounding code,
    422305many languages define clean-up actions that must be taken when certain
    423306sections of the stack are removed. Such as when the storage for a variable
    424 is removed from the stack, possibly requiring a destructor call,
    425 or when a try statement with a finally clause is
     307is removed from the stack or when a try statement with a finally clause is
    426308(conceptually) popped from the stack.
    427 None of these cases should be handled by the user --- that would contradict the
     309None of these should be handled by the user --- that would contradict the
    428310intention of these features --- so they need to be handled automatically.
    429311
     
    466348In plain C (which \CFA currently compiles down to) this
    467349flag only handles the cleanup attribute:
    468 %\label{code:cleanup}
    469350\begin{cfa}
    470351void clean_up( int * var ) { ... }
     
    474355in this case @clean_up@, run when the variable goes out of scope.
    475356This feature is enough to mimic destructors,
    476 but not try statements that affect
     357but not try statements which can effect
    477358the unwinding.
    478359
    479360To get full unwinding support, all of these features must be handled directly
    480 in assembly and assembler directives; particularly the cfi directives
     361in assembly and assembler directives; partiularly the cfi directives
    481362\snake{.cfi_lsda} and \snake{.cfi_personality}.
    482363
     
    518399@_UA_FORCE_UNWIND@ specifies a forced unwind call. Forced unwind only performs
    519400the cleanup phase and uses a different means to decide when to stop
    520 (see \autoref{s:ForcedUnwind}).
     401(see \vref{s:ForcedUnwind}).
    521402\end{enumerate}
    522403
    523404The @exception_class@ argument is a copy of the
    524405\code{C}{exception}'s @exception_class@ field,
    525 which is a number that identifies the EHM
     406which is a number that identifies the exception handling mechanism
    526407that created the exception.
    527408
     
    613494needs its own exception context.
    614495
    615 The current exception context should be retrieved by calling the function
     496The exception context should be retrieved by calling the function
    616497\snake{this_exception_context}.
    617498For sequential execution, this function is defined as
     
    638519The first step of a termination raise is to copy the exception into memory
    639520managed by the exception system. Currently, the system uses @malloc@, rather
    640 than reserved memory or the stack top. The EHM manages
     521than reserved memory or the stack top. The exception handling mechanism manages
    641522memory for the exception as well as memory for libunwind and the system's own
    642523per-exception storage.
     
    673554\newsavebox{\stackBox}
    674555\begin{lrbox}{\codeBox}
    675 \begin{cfa}
     556\begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
    676557unsigned num_exceptions = 0;
    677558void throws() {
     
    692573    throws();
    693574}
    694 \end{cfa}
     575\end{lstlisting}
    695576\end{lrbox}
    696577
    697578\begin{lrbox}{\stackBox}
    698579\begin{lstlisting}
    699 | finally block (Example)
    700 | try block
     580| try-finally
     581| try-catch (Example)
    701582throws()
    702 | finally block (Example)
    703 | try block
     583| try-finally
     584| try-catch (Example)
    704585throws()
    705 | finally block (Example)
    706 | try block
     586| try-finally
     587| try-catch (Example)
    707588throws()
    708589main()
     
    717598\label{f:MultipleExceptions}
    718599\end{figure}
     600\todo*{Work on multiple exceptions code sample.}
    719601
    720602All exceptions are stored in nodes, which are then linked together in lists
     
    736618\subsection{Try Statements and Catch Clauses}
    737619The try statement with termination handlers is complex because it must
    738 compensate for the C code-generation versus proper
     620compensate for the C code-generation versus
    739621assembly-code generated from \CFA. Libunwind
    740622requires an LSDA and personality function for control to unwind across a
    741623function. The LSDA in particular is hard to mimic in generated C code.
    742624
    743 The workaround is a function called \snake{__cfaehm_try_terminate} in the
    744 standard \CFA library. The contents of a try block and the termination
    745 handlers are converted into nested functions. These are then passed to the
    746 try terminate function and it calls them, appropriately.
     625The workaround is a function called @__cfaehm_try_terminate@ in the standard
     626library. The contents of a try block and the termination handlers are converted
     627into functions. These are then passed to the try terminate function and it
     628calls them.
    747629Because this function is known and fixed (and not an arbitrary function that
    748 happens to contain a try statement), its LSDA can be generated ahead
     630happens to contain a try statement), the LSDA can be generated ahead
    749631of time.
    750632
    751 Both the LSDA and the personality function for \snake{__cfaehm_try_terminate}
    752 are set ahead of time using
     633Both the LSDA and the personality function are set ahead of time using
    753634embedded assembly. This assembly code is handcrafted using C @asm@ statements
    754635and contains
    755 enough information for the single try statement the function represents.
     636enough information for a single try statement the function repersents.
    756637
    757638The three functions passed to try terminate are:
     
    765646decides if a catch clause matches the termination exception. It is constructed
    766647from the conditional part of each handler and runs each check, top to bottom,
    767 in turn, to see if the exception matches this handler.
    768 The match is performed in two steps, first a virtual cast is used to check
    769 if the raised exception is an instance of the declared exception type or
    770 one of its descendant types, and then the condition is evaluated, if
    771 present.
    772 The match function takes a pointer to the exception and returns 0 if the
     648in turn, first checking to see if the exception type matches and then if the
     649condition is true. It takes a pointer to the exception and returns 0 if the
    773650exception is not handled here. Otherwise the return value is the id of the
    774651handler that matches the exception.
     
    783660All three functions are created with GCC nested functions. GCC nested functions
    784661can be used to create closures,
    785 in other words,
    786 functions that can refer to variables in their lexical scope even
    787 those variables are part of a different function.
    788 This approach allows the functions to refer to all the
     662in other words functions that can refer to the state of other
     663functions on the stack. This approach allows the functions to refer to all the
    789664variables in scope for the function containing the @try@ statement. These
    790665nested functions and all other functions besides @__cfaehm_try_terminate@ in
     
    794669
    795670\autoref{f:TerminationTransformation} shows the pattern used to transform
    796 a \CFA try statement with catch clauses into the appropriate C functions.
     671a \CFA try statement with catch clauses into the approprate C functions.
     672\todo{Explain the Termination Transformation figure.}
    797673
    798674\begin{figure}
     
    852728\caption{Termination Transformation}
    853729\label{f:TerminationTransformation}
     730\todo*{Improve (compress?) Termination Transformations.}
    854731\end{figure}
    855732
     
    861738Instead of storing the data in a special area using assembly,
    862739there is just a linked list of possible handlers for each stack,
    863 with each node on the list representing a try statement on the stack.
     740with each node on the list reperenting a try statement on the stack.
    864741
    865742The head of the list is stored in the exception context.
     
    867744to the head of the list.
    868745Instead of traversing the stack, resumption handling traverses the list.
    869 At each node, the EHM checks to see if the try statement the node represents
     746At each node, the EHM checks to see if the try statement the node repersents
    870747can handle the exception. If it can, then the exception is handled and
    871748the operation finishes, otherwise the search continues to the next node.
    872749If the search reaches the end of the list without finding a try statement
    873 with a handler clause
    874 that can handle the exception, the default handler is executed.
    875 If the default handler returns, control continues after the raise statement.
     750that can handle the exception, the default handler is executed and the
     751operation finishes.
    876752
    877753Each node has a handler function that does most of the work.
    878754The handler function is passed the raised exception and returns true
    879755if the exception is handled and false otherwise.
     756
    880757The handler function checks each of its internal handlers in order,
    881758top-to-bottom, until it funds a match. If a match is found that handler is
     
    883760If no match is found the function returns false.
    884761The match is performed in two steps, first a virtual cast is used to see
    885 if the raised exception is an instance of the declared exception type or one
    886 of its descendant types, if so then it is passed to the custom predicate
    887 if one is defined.
    888 % You need to make sure the type is correct before running the predicate
    889 % because the predicate can depend on that.
     762if the thrown exception is an instance of the declared exception or one of
     763its descendant type, then check to see if passes the custom predicate if one
     764is defined. This ordering gives the type guarantee used in the predicate.
    890765
    891766\autoref{f:ResumptionTransformation} shows the pattern used to transform
    892 a \CFA try statement with catchResume clauses into the appropriate
    893 C functions.
     767a \CFA try statement with catch clauses into the approprate C functions.
     768\todo{Explain the Resumption Transformation figure.}
    894769
    895770\begin{figure}
     
    932807\caption{Resumption Transformation}
    933808\label{f:ResumptionTransformation}
     809\todo*{Improve (compress?) Resumption Transformations.}
    934810\end{figure}
    935811
     
    938814(see \vpageref{s:ResumptionMarking}), which ignores parts of
    939815the stack
    940 already examined, and is accomplished by updating the front of the list as
    941 the search continues.
    942 Before the handler is called at a matching node, the head of the list
     816already examined, is accomplished by updating the front of the list as the
     817search continues. Before the handler at a node is called, the head of the list
    943818is updated to the next node of the current node. After the search is complete,
    944819successful or not, the head of the list is reset.
     
    947822been checked are not on the list while a handler is run. If a resumption is
    948823thrown during the handling of another resumption, the active handlers and all
    949 the other handlers checked up to this point are not checked again.
     824the other handler checked up to this point are not checked again.
    950825% No paragraph?
    951826This structure also supports new handlers added while the resumption is being
     
    955830
    956831\begin{figure}
    957 \centering
    958832\input{resumption-marking}
    959833\caption{Resumption Marking}
    960834\label{f:ResumptionMarking}
     835\todo*{Label Resumption Marking to aid clarity.}
    961836\end{figure}
    962837
     
    976851\section{Finally}
    977852% Uses destructors and GCC nested functions.
    978 
    979 %\autoref{code:cleanup}
    980 A finally clause is handled by converting it into a once-off destructor.
    981 The code inside the clause is placed into GCC nested-function
    982 with a unique name, and no arguments or return values.
    983 This nested function is
    984 then set as the cleanup function of an empty object that is declared at the
    985 beginning of a block placed around the context of the associated try
    986 statement (see \autoref{f:FinallyTransformation}).
    987 
    988 \begin{figure}
    989 \begin{cfa}
    990 try {
    991         // TRY BLOCK
    992 } finally {
    993         // FINALLY BLOCK
    994 }
    995 \end{cfa}
    996 
    997 \transformline
    998 
    999 \begin{cfa}
    1000 {
    1001         void finally(void *__hook){
    1002                 // FINALLY BLOCK
    1003         }
    1004         __attribute__ ((cleanup(finally)))
    1005         struct __cfaehm_cleanup_hook __finally_hook;
    1006         {
    1007                 // TRY BLOCK
    1008         }
    1009 }
    1010 \end{cfa}
    1011 
    1012 \caption{Finally Transformation}
    1013 \label{f:FinallyTransformation}
    1014 \end{figure}
    1015 
    1016 The rest is handled by GCC.
    1017 The TRY BLOCK
    1018 contains the try block itself as well as all code generated for handlers.
    1019 Once that code has completed,
    1020 control exits the block and the empty object is cleaned
     853A finally clause is placed into a GCC nested-function with a unique name,
     854and no arguments or return values.
     855This nested function is then set as the cleanup
     856function of an empty object that is declared at the beginning of a block placed
     857around the context of the associated @try@ statement.
     858
     859The rest is handled by GCC. The try block and all handlers are inside this
     860block. At completion, control exits the block and the empty object is cleaned
    1021861up, which runs the function that contains the finally code.
    1022862
     
    1047887passed to the forced-unwind function. The general pattern of all three stop
    1048888functions is the same: continue unwinding until the end of stack and
    1049 then perform the appropriate transfer.
     889then preform the appropriate transfer.
    1050890
    1051891For main stack cancellation, the transfer is just a program abort.
  • doc/theses/andrew_beach_MMath/intro.tex

    r5a40e4e rdd1cc02  
    1111
    1212% Now take a step back and explain what exceptions are generally.
     13A language's EHM is a combination of language syntax and run-time
     14components that are used to construct, raise, and handle exceptions,
     15including all control flow.
     16Exceptions are an active mechanism for replacing passive error/return codes and return unions (Go and Rust).
    1317Exception handling provides dynamic inter-function control flow.
    14 A language's EHM is a combination of language syntax and run-time
    15 components that construct, raise, propagate and handle exceptions,
    16 to provide all of that control flow.
    1718There are two forms of exception handling covered in this thesis:
    1819termination, which acts as a multi-level return,
    1920and resumption, which is a dynamic function call.
    20 % About other works:
    21 Often, when this separation is not made, termination exceptions are assumed
    22 as they are more common and may be the only form of handling provided in
    23 a language.
    24 
    25 All types of exception handling link a raise with a handler.
    26 Both operations are usually language primitives, although raises can be
    27 treated as a primitive function that takes an exception argument.
    28 Handlers are more complex as they are added to and removed from the stack
    29 during execution, must specify what they can handle and give the code to
    30 handle the exception.
    31 
    32 Exceptions work with different execution models but for the descriptions
    33 that follow a simple call stack, with functions added and removed in a
    34 first-in-last-out order, is assumed.
    35 
    36 Termination exception handling searches the stack for the handler, then
    37 unwinds the stack to where the handler was found before calling it.
    38 The handler is run inside the function that defined it and when it finishes
    39 it returns control to that function.
     21% PAB: Maybe this sentence was suppose to be deleted?
     22Termination handling is much more common,
     23to the extent that it is often seen as the only form of handling.
     24% PAB: I like this sentence better than the next sentence.
     25% This separation is uncommon because termination exception handling is so
     26% much more common that it is often assumed.
     27% WHY: Mention other forms of continuation and \cite{CommonLisp} here?
     28
     29Exception handling relies on the concept of nested functions to create handlers that deal with exceptions.
     30\begin{center}
     31\begin{tabular}[t]{ll}
     32\begin{lstlisting}[aboveskip=0pt,belowskip=0pt,language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
     33void f( void (*hp)() ) {
     34        hp();
     35}
     36void g( void (*hp)() ) {
     37        f( hp );
     38}
     39void h( int @i@, void (*hp)() ) {
     40        void @handler@() { // nested
     41                printf( "%d\n", @i@ );
     42        }
     43        if ( i == 1 ) hp = handler;
     44        if ( i > 0 ) h( i - 1, hp );
     45        else g( hp );
     46}
     47h( 2, 0 );
     48\end{lstlisting}
     49&
     50\raisebox{-0.5\totalheight}{\input{handler}}
     51\end{tabular}
     52\end{center}
     53The nested function @handler@ in the second stack frame is explicitly passed to function @f@.
     54When this handler is called in @f@, it uses the parameter @i@ in the second stack frame, which is accessible by an implicit lexical-link pointer.
     55Setting @hp@ in @h@ at different points in the recursion, results in invoking a different handler.
     56Exception handling extends this idea by eliminating explicit handler passing, and instead, performing a stack search for a handler that matches some criteria (conditional dynamic call), and calls the handler at the top of the stack.
     57It is the runtime search $O(N)$ that differentiates an EHM call (raise) from normal dynamic call $O(1)$ via a function or virtual-member pointer.
     58
     59Termination exception handling searches the stack for a handler, unwinds the stack to the frame containing the matching handler, and calling the handler at the top of the stack.
    4060\begin{center}
    4161\input{termination}
    4262\end{center}
    43 
    44 Resumption exception handling searches the stack for a handler and then calls
    45 it without removing any other stack frames.
    46 The handler is run on top of the existing stack, often as a new function or
    47 closure capturing the context in which the handler was defined.
    48 After the handler has finished running it returns control to the function
    49 that preformed the raise, usually starting after the raise.
     63Note, since the handler can reference variables in @h@, @h@ must remain on the stack for the handler call.
     64After the handler returns, control continues after the lexical location of the handler in @h@ (static return)~\cite[p.~108]{Tennent77}.
     65Unwinding allows recover to any previous
     66function on the stack, skipping any functions between it and the
     67function containing the matching handler.
     68
     69Resumption exception handling searches the stack for a handler, does \emph{not} unwind the stack to the frame containing the matching handler, and calls the handler at the top of the stack.
    5070\begin{center}
    5171\input{resumption}
    5272\end{center}
     73After the handler returns, control continues after the resume in @f@ (dynamic return).
     74Not unwinding allows fix up of the problem in @f@ by any previous function on the stack, without disrupting the current set of stack frames.
    5375
    5476Although a powerful feature, exception handling tends to be complex to set up
    5577and expensive to use
    5678so it is often limited to unusual or ``exceptional" cases.
    57 The classic example is error handling, exceptions can be used to
    58 remove error handling logic from the main execution path, and pay
     79The classic example is error handling, where exceptions are used to
     80remove error handling logic from the main execution path, while paying
    5981most of the cost only when the error actually occurs.
    6082
     
    6688some of the underlying tools used to implement and express exception handling
    6789in other languages are absent in \CFA.
    68 Still the resulting syntax resembles that of other languages:
    69 \begin{cfa}
    70 try {
     90Still the resulting basic syntax resembles that of other languages:
     91\begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
     92@try@ {
    7193        ...
    7294        T * object = malloc(request_size);
    7395        if (!object) {
    74                 throw OutOfMemory{fixed_allocation, request_size};
     96                @throw@ OutOfMemory{fixed_allocation, request_size};
    7597        }
    7698        ...
    77 } catch (OutOfMemory * error) {
     99} @catch@ (OutOfMemory * error) {
    78100        ...
    79101}
    80 \end{cfa}
     102\end{lstlisting}
    81103% A note that yes, that was a very fast overview.
    82104The design and implementation of all of \CFA's EHM's features are
     
    85107
    86108% The current state of the project and what it contributes.
    87 All of these features have been implemented in \CFA,
    88 covering both changes to the compiler and the run-time.
    89 In addition, a suite of test cases and performance benchmarks were created
    90 along side the implementation.
    91 The implementation techniques are generally applicable in other programming
     109The majority of the \CFA EHM is implemented in \CFA, except for a small amount of assembler code.
     110In addition,
     111a suite of tests and performance benchmarks were created as part of this project.
     112The \CFA implementation techniques are generally applicable in other programming
    92113languages and much of the design is as well.
    93 Some parts of the EHM use other features unique to \CFA and would be
    94 harder to replicate in other programming languages.
     114Some parts of the EHM use features unique to \CFA, and hence,
     115are harder to replicate in other programming languages.
     116% Talk about other programming languages.
     117Three well known programming languages with EHMs, %/exception handling
     118C++, Java and Python are examined in the performance work. However, these languages focus on termination
     119exceptions, so there is no comparison with resumption.
    95120
    96121The contributions of this work are:
    97122\begin{enumerate}
    98123\item Designing \CFA's exception handling mechanism, adapting designs from
    99 other programming languages and creating new features.
    100 \item Implementing stack unwinding and the \CFA EHM, including updating
    101 the \CFA compiler and the run-time environment.
    102 \item Designed and implemented a prototype virtual system.
     124other programming languages, and creating new features.
     125\item Implementing stack unwinding for the \CFA EHM, including updating
     126the \CFA compiler and run-time environment to generate and execute the EHM code.
     127\item Designing and implementing a prototype virtual system.
    103128% I think the virtual system and per-call site default handlers are the only
    104129% "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,
    107 as compared to other languages.
     130\item Creating tests and performance benchmarks to compare with EHM's in other languages.
    108131\end{enumerate}
    109132
    110 The rest of this thesis is organized as follows.
    111 The current state of exceptions is covered in \autoref{s:background}.
    112 The existing state of \CFA is also covered in \autoref{c:existing}.
    113 New EHM features are introduced in \autoref{c:features},
     133%\todo{I can't figure out a good lead-in to the roadmap.}
     134The thesis is organization as follows.
     135The next section and parts of \autoref{c:existing} cover existing EHMs.
     136New \CFA EHM features are introduced in \autoref{c:features},
    114137covering their usage and design.
    115138That is followed by the implementation of these features in
    116139\autoref{c:implement}.
    117 Performance results are examined in \autoref{c:performance}.
    118 Possibilities to extend this project are discussed in \autoref{c:future}.
    119 Finally, the project is summarized in \autoref{c:conclusion}.
     140Performance results are presented in \autoref{c:performance}.
     141Summing up and possibilities for extending this project are discussed in \autoref{c:future}.
    120142
    121143\section{Background}
    122144\label{s:background}
    123145
    124 Exception handling has been examined before in programming languages,
    125 with papers on the subject dating back 70s.\cite{Goodenough75}
     146Exception handling is a well examined area in programming languages,
     147with papers on the subject dating back the 70s~\cite{Goodenough75}.
    126148Early exceptions were often treated as signals, which carried no information
    127 except their identity.
    128 Ada originally used this system\cite{Ada}, but now allows for a string
    129 message as a payload\cite{Ada12}.
     149except their identity. Ada~\cite{Ada} still uses this system.
    130150
    131151The modern flag-ship for termination exceptions is \Cpp,
    132152which added them in its first major wave of non-object-orientated features
    133 in 1990.\cite{CppHistory}
    134 Many EHMs have special exception types,
    135 however \Cpp has the ability to use any type as an exception.
    136 These were found to be not very useful and have been pushed aside for classes
    137 inheriting from
     153in 1990.
     154% https://en.cppreference.com/w/cpp/language/history
     155While many EHMs have special exception types,
     156\Cpp has the ability to use any type as an exception.
     157However, this generality is not particularly useful, and has been pushed aside for classes, with a convention of inheriting from
    138158\code{C++}{std::exception}.
    139 Although there is a special catch-all syntax (@catch(...)@) there are no
    140 operations that can be performed on the caught value, not even type inspection.
    141 Instead the base exception-type \code{C++}{std::exception} defines common
    142 functionality (such as
    143 the ability to describe the reason the exception was raised) and all
     159While \Cpp has a special catch-all syntax @catch(...)@, there is no way to discriminate its exception type, so nothing can
     160be done with the caught value because nothing is known about it.
     161Instead the base exception-type \code{C++}{std::exception} is defined with common functionality (such as
     162the ability to print a message when the exception is raised but not caught) and all
    144163exceptions have this functionality.
    145 That trade-off, restricting usable types to gain guaranteed functionality,
    146 is almost universal now, as without some common functionality it is almost
    147 impossible to actually handle any errors.
    148 
    149 Java was the next popular language to use exceptions.\cite{Java8}
    150 Its exception system largely reflects that of \Cpp, except that requires
    151 you throw a child type of \code{Java}{java.lang.Throwable}
     164Having a root exception-type seems to be the standard now, as the guaranteed functionality is worth
     165any lost in flexibility from limiting exceptions types to classes.
     166
     167Java~\cite{Java} was the next popular language to use exceptions.
     168Its exception system largely reflects that of \Cpp, except it requires
     169exceptions to be a subtype of \code{Java}{java.lang.Throwable}
    152170and it uses checked exceptions.
    153 Checked exceptions are part of a function's interface,
    154 the exception signature of the function.
    155 Every function that could be raised from a function, either directly or
    156 because it is not handled from a called function, is given.
    157 Using this information, it is possible to statically verify if any given
    158 exception is handled and guarantee that no exception will go unhandled.
    159 Making exception information explicit improves clarity and safety,
    160 but can slow down or restrict programming.
    161 For example, programming high-order functions becomes much more complex
    162 if the argument functions could raise exceptions.
    163 However, as odd it may seem, the worst problems are rooted in the simple
    164 inconvenience of writing and updating exception signatures.
    165 This has caused Java programmers to develop multiple programming ``hacks''
    166 to circumvent checked exceptions, negating their advantages.
    167 One particularly problematic example is the ``catch-and-ignore'' pattern,
    168 where an empty handler is used to handle an exception without doing any
    169 recovery or repair. In theory that could be good enough to properly handle
    170 the exception, but more often is used to ignore an exception that the       
    171 programmer does not feel is worth the effort of handling it, for instance if
    172 they do not believe it will ever be raised.
    173 If they are incorrect the exception will be silenced, while in a similar
    174 situation with unchecked exceptions the exception would at least activate   
    175 the language's unhandled exception code (usually program abort with an 
    176 error message).
     171Checked exceptions are part of a function's interface defining all exceptions it or its called functions raise.
     172Using this information, it is possible to statically verify if a handler exists for all raised exception, \ie no uncaught exceptions.
     173Making exception information explicit, improves clarity and
     174safety, but can slow down programming.
     175For example, programming complexity increases when dealing with high-order methods or an overly specified
     176throws clause. However some of the issues are more
     177programming annoyances, such as writing/updating many exception signatures after adding or remove calls.
     178Java programmers have developed multiple programming ``hacks'' to circumvent checked exceptions negating the robustness it is suppose to provide.
     179For example, the ``catch-and-ignore" pattern, where the handler is empty because the exception does not appear relevant to the programmer versus
     180repairing or recovering from the exception.
    177181
    178182%\subsection
    179183Resumption exceptions are less popular,
    180 although resumption is as old as termination; hence, few
     184although resumption is as old as termination;
     185hence, few
    181186programming languages have implemented them.
    182187% http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/parc/techReports/
    183188%   CSL-79-3_Mesa_Language_Manual_Version_5.0.pdf
    184 Mesa is one programming language that did.\cite{Mesa} Experience with Mesa
    185 is quoted as being one of the reasons resumptions were not
     189Mesa~\cite{Mesa} is one programming languages that did. Experience with Mesa
     190is quoted as being one of the reasons resumptions are not
    186191included in the \Cpp standard.
    187192% https://en.wikipedia.org/wiki/Exception_handling
    188 Since then resumptions have been ignored in main-stream programming languages.
    189 However, resumption is being revisited in the context of decades of other
    190 developments in programming languages.
    191 While rejecting resumption may have been the right decision in the past,
    192 the situation has changed since then.
    193 Some developments, such as the function programming equivalent to resumptions,
    194 algebraic effects\cite{Zhang19}, are enjoying success.
    195 A complete reexamination of resumptions is beyond this thesis,
    196 but there reemergence is enough to try them in \CFA.
     193As a result, resumption has ignored in main-stream programming languages.
     194However, ``what goes around comes around'' and resumption is being revisited now (like user-level threading).
     195While rejecting resumption might have been the right decision in the past, there are decades
     196of developments in computer science that have changed the situation.
     197Some of these developments, such as functional programming's resumption
     198equivalent, algebraic effects\cite{Zhang19}, are enjoying significant success.
     199A complete reexamination of resumptions is beyond this thesis, but their re-emergence is
     200enough to try them in \CFA.
    197201% Especially considering how much easier they are to implement than
    198 % termination exceptions and how much Peter likes them.
    199 
    200 %\subsection
    201 Functional languages tend to use other solutions for their primary error
    202 handling mechanism, but exception-like constructs still appear.
    203 Termination appears in the error construct, which marks the result of an
    204 expression as an error; then the result of any expression that tries to use
    205 it also results in an error, and so on until an appropriate handler is reached.
     202% termination exceptions.
     203
     204%\subsection
     205Functional languages tend to use other solutions for their primary EHM,
     206but exception-like constructs still appear.
     207Termination appears in error construct, which marks the result of an
     208expression as an error; thereafter, the result of any expression that tries to use it is also an
     209error, and so on until an appropriate handler is reached.
    206210Resumption appears in algebraic effects, where a function dispatches its
    207211side-effects to its caller for handling.
    208212
    209213%\subsection
    210 More recently exceptions seem to be vanishing from newer programming
    211 languages, replaced by ``panic".
    212 In Rust, a panic is just a program level abort that may be implemented by
    213 unwinding the stack like in termination exception
    214 handling.\cite{RustPanicMacro}\cite{RustPanicModule}
    215 Go's panic through is very similar to a termination, except it only supports
     214Some programming languages have moved to a restricted kind of EHM
     215called ``panic".
     216In Rust~\cite{Rust}, a panic is just a program level abort that may be implemented by
     217unwinding the stack like in termination exception handling.
     218% https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
     219In Go~\cite{Go}, a panic is very similar to a termination, except it only supports
    216220a catch-all by calling \code{Go}{recover()}, simplifying the interface at
    217 the cost of flexibility.\cite{Go:2021}
     221the cost of flexibility.
    218222
    219223%\subsection
    220224While exception handling's most common use cases are in error handling,
    221 here are some other ways to handle errors with comparisons with exceptions.
     225here are other ways to handle errors with comparisons to exceptions.
    222226\begin{itemize}
    223227\item\emph{Error Codes}:
    224 This pattern has a function return an enumeration (or just a set of fixed
    225 values) to indicate if an error has occurred and possibly which error it was.
    226 
    227 Error codes mix exceptional/error and normal values, enlarging the range of
    228 possible return values. This can be addressed with multiple return values
    229 (or a tuple) or a tagged union.
    230 However, the main issue with error codes is forgetting to check them,
     228This pattern has a function return an enumeration (or just a set of fixed values) to indicate
     229if an error occurred and possibly which error it was.
     230
     231Error codes mix exceptional and normal values, artificially enlarging the type and/or value range.
     232Some languages address this issue by returning multiple values or a tuple, separating the error code from the function result.
     233However, the main issue with error codes is forgetting to checking them,
    231234which leads to an error being quietly and implicitly ignored.
    232 Some new languages and tools will try to issue warnings when an error code
    233 is discarded to avoid this problem.
    234 Checking error codes also bloats the main execution path,
    235 especially if the error is not handled immediately hand has to be passed
    236 through multiple functions before it is addressed.
     235Some new languages have tools that issue warnings, if the error code is
     236discarded to avoid this problem.
     237Checking error codes also results in bloating the main execution path, especially if an error is not dealt with locally and has to be cascaded down the call stack to a higher-level function..
    237238
    238239\item\emph{Special Return with Global Store}:
    239 Similar to the error codes pattern but the function itself only returns
    240 that there was an error
    241 and store the reason for the error in a fixed global location.
    242 For example many routines in the C standard library will only return some
    243 error value (such as -1 or a null pointer) and the error code is written into
    244 the standard variable @errno@.
    245 
    246 This approach avoids the multiple results issue encountered with straight
    247 error codes but otherwise has the same disadvantages and more.
    248 Every function that reads or writes to the global store must agree on all
    249 possible errors and managing it becomes more complex with concurrency.
     240Some functions only return a boolean indicating success or failure
     241and store the exact reason for the error in a fixed global location.
     242For example, many C routines return non-zero or -1, indicating success or failure,
     243and write error details into the C standard variable @errno@.
     244
     245This approach avoids the multiple results issue encountered with straight error codes
     246but otherwise has many (if not more) of the disadvantages.
     247For example, everything that uses the global location must agree on all possible errors and global variable are unsafe with concurrency.
    250248
    251249\item\emph{Return Union}:
     
    256254so that one type can be used everywhere in error handling code.
    257255
    258 This pattern is very popular in any functional or semi-functional language
    259 with primitive support for tagged unions (or algebraic data types).
    260 % We need listing Rust/rust to format code snippets from it.
     256This pattern is very popular in functional or any semi-functional language with
     257primitive support for tagged unions (or algebraic data types).
     258% We need listing Rust/rust to format code snipits from it.
    261259% Rust's \code{rust}{Result<T, E>}
    262 The main advantage is that an arbitrary object can be used to represent an
    263 error so it can include a lot more information than a simple error code.
    264 The disadvantages include that the it does have to be checked along the main
    265 execution and if there aren't primitive tagged unions proper usage can be
    266 hard to enforce.
     260The main advantage is providing for more information about an
     261error, other than one of a fix-set of ids.
     262While some languages use checked union access to force error-code checking,
     263it is still possible to bypass the checking.
     264The main disadvantage is again significant error code on the main execution path and cascading through called functions.
    267265
    268266\item\emph{Handler Functions}:
    269 This pattern associates errors with functions.
    270 On error, the function that produced the error calls another function to
     267This pattern implicitly associates functions with errors.
     268On error, the function that produced the error implicitly calls another function to
    271269handle it.
    272270The handler function can be provided locally (passed in as an argument,
    273271either directly as as a field of a structure/object) or globally (a global
    274272variable).
    275 C++ uses this approach as its fallback system if exception handling fails,
    276 such as \snake{std::terminate_handler} and, for a time,
    277 \snake{std::unexpected_handler}.
    278 
    279 Handler functions work a lot like resumption exceptions,
    280 but without the dynamic search for a handler.
    281 Since setting up the handler can be more complex/expensive,
    282 especially when the handler has to be passed through multiple layers of
    283 function calls, but cheaper (constant time) to call,
    284 they are more suited to more frequent (less exceptional) situations.
     273C++ uses this approach as its fallback system if exception handling fails, \eg
     274\snake{std::terminate_handler} and for a time \snake{std::unexpected_handler}
     275
     276Handler functions work a lot like resumption exceptions, without the dynamic handler search.
     277Therefore, setting setting up the handler can be more complex/expensive, especially if the handle must be passed through multiple function calls, but cheaper to call $O(1)$, and hence,
     278are more suited to frequent exceptional situations.
     279% The exception being global handlers if they are rarely change as the time
     280% in both cases shrinks towards zero.
    285281\end{itemize}
    286282
    287283%\subsection
    288284Because of their cost, exceptions are rarely used for hot paths of execution.
    289 Hence, there is an element of self-fulfilling prophecy as implementation
    290 techniques have been focused on making them cheap to set-up,
    291 happily making them expensive to use in exchange.
    292 This difference is less important in higher-level scripting languages,
    293 where using exception for other tasks is more common.
    294 An iconic example is Python's
    295 \code{Python}{StopIteration}\cite{PythonExceptions} exception that
    296 is thrown by an iterator to indicate that it is exhausted.
    297 When paired with Python's iterator-based for-loop this will be thrown every
    298 time the end of the loop is reached.\cite{PythonForLoop}
     285Therefore, there is an element of self-fulfilling prophecy for implementation
     286techniques to make exceptions cheap to set-up at the cost
     287of expensive usage.
     288This cost differential is less important in higher-level scripting languages, where use of exceptions for other tasks is more common.
     289An iconic example is Python's @StopIteration@ exception that is thrown by
     290an iterator to indicate that it is exhausted, especially when combined with Python's heavy
     291use of the iterator-based for-loop.
     292% https://docs.python.org/3/library/exceptions.html#StopIteration
  • doc/theses/andrew_beach_MMath/performance.tex

    r5a40e4e rdd1cc02  
    22\label{c:performance}
    33
    4 Performance is of secondary importance for most of this project.
    5 Instead, the focus was to get the features working. The only performance
    6 requirement is to ensure the tests for correctness run in a reasonable
    7 amount of time. Hence, a few basic performance tests were performed to
    8 check this requirement.
     4Performance has been of secondary importance for most of this project.
     5Instead, the focus has been to get the features working. The only performance
     6requirements is to ensure the tests for correctness run in a reasonable
     7amount of time.
    98
    109\section{Test Set-Up}
    11 Tests were run in \CFA, C++, Java and Python.
     10Tests will be run in \CFA, C++, Java and Python.
    1211In addition there are two sets of tests for \CFA,
    13 one with termination and one with resumption.
     12one for termination exceptions and once with resumption exceptions.
    1413
    1514C++ is the most comparable language because both it and \CFA use the same
    1615framework, libunwind.
    17 In fact, the comparison is almost entirely in quality of implementation.
    18 Specifically, \CFA's EHM has had significantly less time to be optimized and
     16In fact, the comparison is almost entirely a quality of implementation
     17comparison. \CFA's EHM has had significantly less time to be optimized and
    1918does not generate its own assembly. It does have a slight advantage in that
    20 \Cpp has to do some extra bookkeeping to support its utility functions,
    21 but otherwise \Cpp should have a significant advantage.
    22 
    23 Java, a popular language with similar termination semantics,
    24 is implemented in a very different environment, a virtual machine with
     19there are some features it does not handle, through utility functions,
     20but otherwise \Cpp has a significant advantage.
     21
     22Java is another very popular language with similar termination semantics.
     23It is implemented in a very different environment, a virtual machine with
    2524garbage collection.
    2625It also implements the finally clause on try blocks allowing for a direct
    2726feature-to-feature comparison.
    28 As with \Cpp, Java's implementation is mature, has more optimizations
    29 and extra features as compared to \CFA.
    30 
    31 Python is used as an alternative comparison because of the \CFA EHM's
    32 current performance goals, which is to not be prohibitively slow while the
     27As with \Cpp, Java's implementation is more mature, has more optimizations
     28and more extra features.
     29
     30Python was used as a point of comparison because of the \CFA EHM's
     31current performance goals, which is not be prohibitively slow while the
    3332features are designed and examined. Python has similar performance goals for
    3433creating quick scripts and its wide use suggests it has achieved those goals.
    3534
    36 Unfortunately, there are no notable modern programming languages with
    37 resumption exceptions. Even the older programming languages with resumption
    38 seem to be notable only for having resumption.
    39 Instead, resumption is compared to its simulation in other programming
    40 languages: fixup functions that are explicitly passed into a function.
    41 
    42 All tests are run inside a main loop that repeatedly performs a test.
    43 This approach avoids start-up or tear-down time from
     35Unfortunately there are no notable modern programming languages with
     36resumption exceptions. Even the older programming languages with resumptions
     37seem to be notable only for having resumptions.
     38So instead resumptions are compared to a less similar but much more familiar
     39feature, termination exceptions.
     40
     41All tests are run inside a main loop which will perform the test
     42repeatedly. This is to avoids start-up or tear-down time from
    4443affecting the timing results.
    45 The number of times the loop is run is configurable from the command line;
    46 the number used in the timing runs is given with the results per test.
    47 The Java tests run the main loop 1000 times before
    48 beginning the actual test to ``warm-up" the JVM.
    49 % All other languages are precompiled or interpreted.
     44Tests ran their main loop a million times.
     45The Java versions of the test also run this loop an extra 1000 times before
     46beginning to time the results to ``warm-up" the JVM.
    5047
    5148Timing is done internally, with time measured immediately before and
    52 after the test loop. The difference is calculated and printed.
     49immediately after the test loop. The difference is calculated and printed.
     50
    5351The loop structure and internal timing means it is impossible to test
    5452unhandled exceptions in \Cpp and Java as that would cause the process to
     
    5755critical.
    5856
    59 The exceptions used in these tests are always based off of
    60 the base exception for the language.
    61 This requirement minimizes performance differences based
    62 on the object model used to represent the exception.
    63 
    64 All tests are designed to be as minimal as possible, while still preventing
    65 excessive optimizations.
     57The exceptions used in these tests will always be a exception based off of
     58the base exception. This requirement minimizes performance differences based
     59on the object model used to repersent the exception.
     60
     61All tests were designed to be as minimal as possible while still preventing
     62exessive optimizations.
    6663For example, empty inline assembly blocks are used in \CFA and \Cpp to
    6764prevent excessive optimizations while adding no actual work.
     
    7168% \code{C++}{catch(...)}).
    7269
    73 When collecting data, each test is run eleven times. The top three and bottom
    74 three results are discarded and the remaining five values are averaged.
    75 The test are run with the latest (still pre-release) \CFA compiler,
    76 using gcc-10 10.3.0 as a backend.
    77 g++-10 10.3.0 is used for \Cpp.
    78 Java tests are complied and run with version 11.0.11.
    79 Python used version 3.8.10.
    80 The machines used to run the tests are:
    81 \begin{itemize}[nosep]
    82 \item ARM 2280 Kunpeng 920 48-core 2$\times$socket
    83       \lstinline{@} 2.6 GHz running Linux v5.11.0-25
    84 \item AMD 6380 Abu Dhabi 16-core 4$\times$socket
    85       \lstinline{@} 2.5 GHz running Linux v5.11.0-25
    86 \end{itemize}
    87 Representing the two major families of hardware architecture.
    88 
    8970\section{Tests}
    9071The following tests were selected to test the performance of different
    9172components of the exception system.
    92 They should provide a guide as to where the EHM's costs are found.
    93 
    94 \paragraph{Stack Traversal}
    95 This group measures the cost of traversing the stack,
    96 (and in termination, unwinding it).
    97 Inside the main loop is a call to a recursive function.
    98 This function calls itself F times before raising an exception.
    99 F is configurable from the command line, but is usually 100.
    100 This builds up many stack frames, and any contents they may have,
    101 before the raise.
    102 The exception is always handled at the base of the stack.
    103 For example the Empty test for \CFA resumption looks like:
    104 \begin{cfa}
    105 void unwind_empty(unsigned int frames) {
    106         if (frames) {
    107                 unwind_empty(frames - 1);
    108         } else {
    109                 throwResume (empty_exception){&empty_vt};
    110         }
    111 }
    112 \end{cfa}
    113 Other test cases have additional code around the recursive call adding
    114 something besides simple stack frames to the stack.
    115 Note that both termination and resumption have to traverse over
    116 the stack but only termination has to unwind it.
    117 \begin{itemize}[nosep]
    118 % \item None:
    119 % Reuses the empty test code (see below) except that the number of frames
    120 % is set to 0 (this is the only test for which the number of frames is not
    121 % 100). This isolates the start-up and shut-down time of a throw.
    122 \item Empty:
     73The should provide a guide as to where the EHM's costs can be found.
     74
     75\paragraph{Raise and Handle}
     76The first group of tests involve setting up
     77So there is three layers to the test. The first is set up and a loop, which
     78configures the test and then runs it repeatedly to reduce the impact of
     79start-up and shutdown on the results.
     80Each iteration of the main loop
     81\begin{itemize}[nosep]
     82\item Empty Function:
    12383The repeating function is empty except for the necessary control code.
    124 As other traversal tests add to this, it is the baseline for the group
    125 as the cost comes from traversing over and unwinding a stack frame
    126 that has no other interactions with the exception system.
    12784\item Destructor:
    12885The repeating function creates an object with a destructor before calling
    12986itself.
    130 Comparing this to the empty test gives the time to traverse over and
    131 unwind a destructor.
    13287\item Finally:
    13388The repeating function calls itself inside a try block with a finally clause
    13489attached.
    135 Comparing this to the empty test gives the time to traverse over and
    136 unwind a finally clause.
    13790\item Other Handler:
    13891The repeating function calls itself inside a try block with a handler that
    139 does not match the raised exception, but is of the same kind of handler.
    140 This means that the EHM has to check each handler, and continue
    141 over all of them until it reaches the base of the stack.
    142 Comparing this to the empty test gives the time to traverse over and
    143 unwind a handler.
     92will not match the raised exception. (But is of the same kind of handler.)
    14493\end{itemize}
    14594
    14695\paragraph{Cross Try Statement}
    147 This group of tests measures the cost for setting up exception handling,
    148 if it is
    149 not used (because the exceptional case did not occur).
    150 Tests repeatedly cross (enter, execute and leave) a try statement but never
    151 perform a raise.
     96The next group measures the cost of a try statement when no exceptions are
     97raised. The test is set-up, then there is a loop to reduce the impact of
     98start-up and shutdown on the results.
     99In each iteration, a try statement is executed. Entering and leaving a loop
     100is all the test wants to do.
    152101\begin{itemize}[nosep]
    153102\item Handler:
    154 The try statement has a handler (of the appropriate kind).
     103The try statement has a handler (of the matching kind).
    155104\item Finally:
    156105The try statement has a finally clause.
     
    158107
    159108\paragraph{Conditional Matching}
    160 This group measures the cost of conditional matching.
     109This group of tests checks the cost of conditional matching.
    161110Only \CFA implements the language level conditional match,
    162 the other languages mimic it with an ``unconditional" match (it still
    163 checks the exception's type) and conditional re-raise if it is not supposed
     111the other languages must mimic with an ``unconditional" match (it still
     112checks the exception's type) and conditional re-raise if it was not supposed
    164113to handle that exception.
    165 
    166 Here is the pattern shown in \CFA and \Cpp. Java and Python use the same
    167 pattern as \Cpp, but with their own syntax.
    168 
    169 \begin{minipage}{0.45\textwidth}
    170 \begin{cfa}
    171 try {
    172         ...
    173 } catch (exception_t * e ;
    174                 should_catch(e)) {
    175         ...
    176 }
    177 \end{cfa}
    178 \end{minipage}
    179 \begin{minipage}{0.55\textwidth}
    180 \begin{lstlisting}[language=C++]
    181 try {
    182         ...
    183 } catch (std::exception & e) {
    184         if (!should_catch(e)) throw;
    185         ...
    186 }
    187 \end{lstlisting}
    188 \end{minipage}
    189114\begin{itemize}[nosep]
    190115\item Match All:
     
    194119\end{itemize}
    195120
    196 \paragraph{Resumption Simulation}
    197 A slightly altered version of the Empty Traversal test is used when comparing
    198 resumption to fix-up routines.
    199 The handler, the actual resumption handler or the fix-up routine,
    200 always captures a variable at the base of the loop,
    201 and receives a reference to a variable at the raise site, either as a
    202 field on the exception or an argument to the fix-up routine.
    203 % I don't actually know why that is here but not anywhere else.
    204 
    205121%\section{Cost in Size}
    206122%Using exceptions also has a cost in the size of the executable.
     
    214130
    215131\section{Results}
    216 % First, introduce the tables.
    217 \autoref{t:PerformanceTermination},
    218 \autoref{t:PerformanceResumption}
    219 and~\autoref{t:PerformanceFixupRoutines}
    220 show the test results.
    221 In cases where a feature is not supported by a language, the test is skipped
    222 for that language and the result is marked N/A.
    223 There are also cases where the feature is supported but measuring its
    224 cost is impossible. This happened with Java, which uses a JIT that optimize
    225 away the tests and it cannot be stopped.\cite{Dice21}
    226 These tests are marked N/C.
    227 To get results in a consistent range (1 second to 1 minute is ideal,
    228 going higher is better than going low) N, the number of iterations of the
    229 main loop in each test, is varied between tests. It is also given in the
    230 results and has a value in the millions.
    231 
    232 An anomaly in some results came from \CFA's use of gcc nested functions.
    233 These nested functions are used to create closures that can access stack
    234 variables in their lexical scope.
    235 However, if they do so, then they can cause the benchmark's run-time to
    236 increase by an order of magnitude.
    237 The simplest solution is to make those values global variables instead
    238 of function local variables.
    239 % Do we know if editing a global inside nested function is a problem?
    240 Tests that had to be modified to avoid this problem have been marked
    241 with a ``*'' in the results.
    242 
    243 % Now come the tables themselves:
    244 % You might need a wider window for this.
    245 
    246 \begin{table}[htb]
    247 \centering
    248 \caption{Termination Performance Results (sec)}
    249 \label{t:PerformanceTermination}
    250 \begin{tabular}{|r|*{2}{|r r r r|}}
    251 \hline
    252                        & \multicolumn{4}{c||}{AMD}         & \multicolumn{4}{c|}{ARM}  \\
    253 \cline{2-9}
    254 N\hspace{8pt}          & \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c||}{Python} &
    255                          \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
    256 \hline
    257 Empty Traversal (1M)   & 3.4   & 2.8   & 18.3  & 23.4      & 3.7   & 3.2   & 15.5  & 14.8  \\
    258 D'tor Traversal (1M)   & 48.4  & 23.6  & N/A   & N/A       & 64.2  & 29.0  & N/A   & N/A   \\
    259 Finally Traversal (1M) & 3.4*  & N/A   & 17.9  & 29.0      & 4.1*  & N/A   & 15.6  & 19.0  \\
    260 Other Traversal (1M)   & 3.6*  & 23.2  & 18.2  & 32.7      & 4.0*  & 24.5  & 15.5  & 21.4  \\
    261 Cross Handler (1B)     & 6.0   & 0.9   & N/C   & 37.4      & 10.0  & 0.8   & N/C   & 32.2  \\
    262 Cross Finally (1B)     & 0.9   & N/A   & N/C   & 44.1      & 0.8   & N/A   & N/C   & 37.3  \\
    263 Match All (10M)        & 32.9  & 20.7  & 13.4  & 4.9       & 36.2  & 24.5  & 12.0  & 3.1   \\
    264 Match None (10M)       & 32.7  & 50.3  & 11.0  & 5.1       & 36.3  & 71.9  & 12.3  & 4.2   \\
     132Each test was run eleven times. The top three and bottom three results were
     133discarded and the remaining five values are averaged.
     134
     135In cases where a feature is not supported by a language the test is skipped
     136for that language. Similarly, if a test is does not change between resumption
     137and termination in \CFA, then only one test is written and the result
     138was put into the termination column.
     139
     140% Raw Data:
     141% run-algol-a.sat
     142% ---------------
     143% Raise Empty   &  82687046678 &  291616256 &   3252824847 & 15422937623 & 14736271114 \\
     144% Raise D'tor   & 219933199603 &  297897792 & 223602799362 &         N/A &         N/A \\
     145% Raise Finally & 219703078448 &  298391745 &          N/A &         ... & 18923060958 \\
     146% Raise Other   & 296744104920 & 2854342084 & 112981255103 & 15475924808 & 21293137454 \\
     147% Cross Handler &      9256648 &   13518430 &       769328 &     3486252 &    31790804 \\
     148% Cross Finally &       769319 &        N/A &          N/A &     2272831 &    37491962 \\
     149% Match All     &   3654278402 &   47518560 &   3218907794 &  1296748192 &   624071886 \\
     150% Match None    &   4788861754 &   58418952 &   9458936430 &  1318065020 &   625200906 \\
     151%
     152% run-algol-thr-c
     153% ---------------
     154% Raise Empty   &   3757606400 &   36472972 &   3257803337 & 15439375452 & 14717808642 \\
     155% Raise D'tor   &  64546302019 &  102148375 & 223648121635 &         N/A &         N/A \\
     156% Raise Finally &  64671359172 &  103285005 &          N/A & 15442729458 & 18927008844 \\
     157% Raise Other   & 294143497130 & 2630130385 & 112969055576 & 15448220154 & 21279953424 \\
     158% Cross Handler &      9646462 &   11955668 &       769328 &     3453707 &    31864074 \\
     159% Cross Finally &       773412 &        N/A &          N/A &     2253825 &    37266476 \\
     160% Match All     &   3719462155 &   43294042 &   3223004977 &  1286054154 &   623887874 \\
     161% Match None    &   4971630929 &   55311709 &   9481225467 &  1310251289 &   623752624 \\
     162\begin{tabular}{|l|c c c c c|}
     163\hline
     164              & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\
     165\hline
     166Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     167Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
     168Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
     169Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     170Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     171Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
     172Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     173Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    265174\hline
    266175\end{tabular}
    267 \end{table}
    268 
    269 \begin{table}[htb]
    270 \centering
    271 \caption{Resumption Performance Results (sec)}
    272 \label{t:PerformanceResumption}
    273 \begin{tabular}{|r||r||r|}
    274 \hline
    275 N\hspace{8pt}
    276                         & AMD     & ARM  \\
    277 \hline
    278 Empty Traversal (10M)   & 0.2     & 0.3  \\
    279 D'tor Traversal (10M)   & 1.8     & 1.0  \\
    280 Finally Traversal (10M) & 1.7     & 1.0  \\
    281 Other Traversal (10M)   & 22.6    & 25.9 \\
    282 Cross Handler (1B)      & 8.4     & 11.9 \\
    283 Match All (100M)        & 2.3     & 3.2  \\
    284 Match None (100M)       & 2.9     & 3.9  \\
     176
     177% run-plg7a-a.sat
     178% ---------------
     179% Raise Empty   &  57169011329 &  296612564 &   2788557155 & 17511466039 & 23324548496 \\
     180% Raise D'tor   & 150599858014 &  318443709 & 149651693682 &         N/A &         N/A \\
     181% Raise Finally & 148223145000 &  373325807 &          N/A &         ... & 29074552998 \\
     182% Raise Other   & 189463708732 & 3017109322 &  85819281694 & 17584295487 & 32602686679 \\
     183% Cross Handler &      8001654 &   13584858 &      1555995 &     6626775 &    41927358 \\
     184% Cross Finally &      1002473 &        N/A &          N/A &     4554344 &    51114381 \\
     185% Match All     &   3162460860 &   37315018 &   2649464591 &  1523205769 &   742374509 \\
     186% Match None    &   4054773797 &   47052659 &   7759229131 &  1555373654 &   744656403 \\
     187%
     188% run-plg7a-thr-a
     189% ---------------
     190% Raise Empty   &   3604235388 &   29829965 &   2786931833 & 17576506385 & 23352975105 \\
     191% Raise D'tor   &  46552380948 &  178709605 & 149834207219 &         N/A &         N/A \\
     192% Raise Finally &  46265157775 &  177906320 &          N/A & 17493045092 & 29170962959 \\
     193% Raise Other   & 195659245764 & 2376968982 &  86070431924 & 17552979675 & 32501882918 \\
     194% Cross Handler &    397031776 &   12503552 &      1451225 &     6658628 &    42304965 \\
     195% Cross Finally &      1136746 &        N/A &          N/A &     4468799 &    46155817 \\
     196% Match All     &   3189512499 &   39124453 &   2667795989 &  1525889031 &   733785613 \\
     197% Match None    &   4094675477 &   48749857 &   7850618572 &  1566713577 &   733478963 \\
     198
     199% PLG7A (in seconds)
     200\begin{tabular}{|l|c c c c c|}
     201\hline
     202              & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\
     203\hline
     204% Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     205% Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
     206% Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
     207% Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     208% Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     209% Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
     210% Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     211% Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     212Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     213Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
     214Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
     215Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     216Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     217Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
     218Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     219Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    285220\hline
    286221\end{tabular}
    287 \end{table}
    288 
    289 \begin{table}[htb]
    290 \centering
    291 \small
    292 \caption{Resumption/Fixup Routine Comparison (sec)}
    293 \label{t:PerformanceFixupRoutines}
    294 \setlength{\tabcolsep}{5pt}
    295 \begin{tabular}{|r|*{2}{|r r r r r|}}
    296 \hline
    297             & \multicolumn{5}{c||}{AMD}     & \multicolumn{5}{c|}{ARM}  \\
    298 \cline{2-11}
    299 N\hspace{8pt}       & \multicolumn{1}{c}{Raise} & \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c||}{Python} &
    300               \multicolumn{1}{c}{Raise} & \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
    301 \hline
    302 Resume Empty (10M)  & 1.5 & 1.5 & 14.7 & 2.3 & 176.1  & 1.0 & 1.4 & 8.9 & 1.2 & 119.9 \\
    303 \hline
    304 \end{tabular}
    305 \end{table}
    306 
    307 % Now discuss the results in the tables.
    308 One result not directly related to \CFA but important to keep in mind is that,
    309 for exceptions, the standard intuition about which languages should go
    310 faster often does not hold.
    311 For example, there are a few cases where Python out-performs
    312 \CFA, \Cpp and Java.
    313 % To be exact, the Match All and Match None cases.
    314 The most likely explanation is that, since exceptions
    315 are rarely considered to be the common case, the more optimized languages
    316 make that case expensive to improve other cases.
    317 In addition, languages with high-level representations have a much
    318 easier time scanning the stack as there is less to decode.
    319 
    320 As stated,
    321 the performance tests are not attempting to show \CFA has a new competitive
    322 way of implementing exception handling.
    323 The only performance requirement is to insure the \CFA EHM has reasonable
    324 performance for prototyping.
    325 Although that may be hard to exactly quantify, I believe it has succeeded
    326 in that regard.
    327 Details on the different test cases follow.
    328 
    329 \subsection{Termination \texorpdfstring{(\autoref{t:PerformanceTermination})}{}}
    330 
    331 \begin{description}
    332 \item[Empty Traversal]
    333 \CFA is slower than \Cpp, but is still faster than the other languages
    334 and closer to \Cpp than other languages.
    335 This result is to be expected,
    336 as \CFA is closer to \Cpp than the other languages.
    337 
    338 \item[D'tor Traversal]
    339 Running destructors causes a huge slowdown in the two languages that support
    340 them. \CFA has a higher proportionate slowdown but it is similar to \Cpp's.
    341 Considering the amount of work done in destructors is effectively zero
    342 (an assembly comment), the cost
    343 must come from the change of context required to run the destructor.
    344 
    345 \item[Finally Traversal]
    346 Performance is similar to Empty Traversal in all languages that support finally
    347 clauses. Only Python seems to have a larger than random noise change in
    348 its run-time and it is still not large.
    349 Despite the similarity between finally clauses and destructors,
    350 finally clauses seem to avoid the spike that run-time destructors have.
    351 Possibly some optimization removes the cost of changing contexts.
    352 
    353 \item[Other Traversal]
    354 For \Cpp, stopping to check if a handler applies seems to be about as
    355 expensive as stopping to run a destructor.
    356 This results in a significant jump.
    357 
    358 Other languages experience a small increase in run-time.
    359 The small increase likely comes from running the checks,
    360 but they could avoid the spike by not having the same kind of overhead for
    361 switching to the check's context.
    362 
    363 \item[Cross Handler]
    364 Here \CFA falls behind \Cpp by a much more significant margin.
    365 This is likely due to the fact \CFA has to insert two extra function
    366 calls, while \Cpp does not have to do execute any other instructions.
    367 Python is much further behind.
    368 
    369 \item[Cross Finally]
    370 \CFA's performance now matches \Cpp's from Cross Handler.
    371 If the code from the finally clause is being inlined,
    372 which is just an asm comment, than there are no additional instructions
    373 to execute again when exiting the try statement normally.
    374 
    375 \item[Conditional Match]
    376 Both of the conditional matching tests can be considered on their own.
    377 However for evaluating the value of conditional matching itself, the
    378 comparison of the two sets of results is useful.
    379 Consider the massive jump in run-time for \Cpp going from match all to match
    380 none, which none of the other languages have.
    381 Some strange interaction is causing run-time to more than double for doing
    382 twice as many raises.
    383 Java and Python avoid this problem and have similar run-time for both tests,
    384 possibly through resource reuse or their program representation.
    385 However \CFA is built like \Cpp and avoids the problem as well, this matches
    386 the pattern of the conditional match, which makes the two execution paths
    387 very similar.
    388 
    389 \end{description}
    390 
    391 \subsection{Resumption \texorpdfstring{(\autoref{t:PerformanceResumption})}{}}
    392 
    393 Moving on to resumption, there is one general note,
    394 resumption is \textit{fast}. The only test where it fell
    395 behind termination is Cross Handler.
    396 In every other case, the number of iterations had to be increased by a
    397 factor of 10 to get the run-time in an appropriate range
    398 and in some cases resumption still took less time.
    399 
    400 % I tried \paragraph and \subparagraph, maybe if I could adjust spacing
    401 % between paragraphs those would work.
    402 \begin{description}
    403 \item[Empty Traversal]
    404 See above for the general speed-up notes.
    405 This result is not surprising as resumption's linked-list approach
    406 means that traversing over stack frames without a resumption handler is
    407 $O(1)$.
    408 
    409 \item[D'tor Traversal]
    410 Resumption does have the same spike in run-time that termination has.
    411 The run-time is actually very similar to Finally Traversal.
    412 As resumption does not unwind the stack, both destructors and finally
    413 clauses are run while walking down the stack during the recursive returns.
    414 So it follows their performance is similar.
    415 
    416 \item[Finally Traversal]
    417 Same as D'tor Traversal,
    418 except termination did not have a spike in run-time on this test case.
    419 
    420 \item[Other Traversal]
    421 Traversing across handlers reduces resumption's advantage as it actually
    422 has to stop and check each one.
    423 Resumption still came out ahead (adjusting for iterations) but by much less
    424 than the other cases.
    425 
    426 \item[Cross Handler]
    427 The only test case where resumption could not keep up with termination,
    428 although the difference is not as significant as many other cases.
    429 It is simply a matter of where the costs come from,
    430 both termination and resumption have some work to set-up or tear-down a
    431 handler. It just so happens that resumption's work is slightly slower.
    432 
    433 \item[Conditional Match]
    434 Resumption shows a slight slowdown if the exception is not matched
    435 by the first handler, which follows from the fact the second handler now has
    436 to be checked. However the difference is not large.
    437 
    438 \end{description}
    439 
    440 \subsection{Resumption/Fixup \texorpdfstring{(\autoref{t:PerformanceFixupRoutines})}{}}
    441 
    442 Finally are the results of the resumption/fixup routine comparison.
    443 These results are surprisingly varied. It is possible that creating a closure
    444 has more to do with performance than passing the argument through layers of
    445 calls.
    446 At 100 stack frames, resumption and manual fixup routines have similar
    447 performance in \CFA.
    448 More experiments could try to tease out the exact trade-offs,
    449 but the prototype's only performance goal is to be reasonable.
    450 It has already in that range, and \CFA's fixup routine simulation is
    451 one of the faster simulations as well.
    452 Plus exceptions add features and remove syntactic overhead,
    453 so even at similar performance resumptions have advantages
    454 over fixup routines.
     222
     223One result that is not directly related to \CFA but is important to keep in
     224mind is that in exceptions the standard intuitions about which languages
     225should go faster often do not hold. There are cases where Python out-preforms
     226\Cpp and Java. The most likely explination is that, since exceptions are
     227rarely considered to be the common case, the more optimized langages have
     228optimized at their expence. In addition languages with high level           
     229repersentations have a much easier time scanning the stack as there is less
     230to decode.
     231
     232This means that while \CFA does not actually keep up with Python in every
     233case it is no worse than roughly half the speed of \Cpp. This is good
     234enough for the prototyping purposes of the project.
     235
     236One difference not shown is that optimizations in \CFA is very fragile.
     237The \CFA compiler uses gcc as part of its complation process and the version
     238of gcc could change the speed of some of the benchmarks by 10 times or more.
     239Similar changes to g++ for the \Cpp benchmarks had no significant changes.
     240Because of the connection between gcc and g++; this suggests it is not the
     241optimizations that are changing but how the optimizer is detecting if the
     242optimizations can be applied. So the optimizations are always applied in
     243g++, but only newer versions of gcc can detect that they can be applied in
     244the more complex \CFA code.
     245
     246Resumption exception handling is also incredibly fast. Often an order of
     247magnitude or two better than the best termination speed.
     248There is a simple explination for this; traversing a linked list is much   
     249faster than examining and unwinding the stack. When resumption does not do as
     250well its when more try statements are used per raise. Updating the interal
     251linked list is not very expencive but it does add up.
     252
     253The relative speed of the Match All and Match None tests (within each
     254language) can also show the effectiveness conditional matching as compared
     255to catch and rethrow.
     256\begin{itemize}[nosep]
     257\item
     258Java and Python get similar values in both tests.
     259Between the interperated code, a higher level repersentation of the call
     260stack and exception reuse it it is possible the cost for a second
     261throw can be folded into the first.
     262% Is this due to optimization?
     263\item
     264Both types of \CFA are slighly slower if there is not a match.
     265For termination this likely comes from unwinding a bit more stack through
     266libunwind instead of executing the code normally.
     267For resumption there is extra work in traversing more of the list and running
     268more checks for a matching exceptions.
     269% Resumption is a bit high for that but this is my best theory.
     270\item
     271Then there is \Cpp, which takes 2--3 times longer to catch and rethrow vs.
     272just the catch. This is very high, but it does have to repeat the same
     273process of unwinding the stack and may have to parse the LSDA of the function
     274with the catch and rethrow twice, once before the catch and once after the
     275rethrow.
     276% I spent a long time thinking of what could push it over twice, this is all
     277% I have to explain it.
     278\end{itemize}
     279The difference in relative performance does show that there are savings to
     280be made by performing the check without catching the exception.
  • doc/theses/andrew_beach_MMath/resumption-marking.fig

    r5a40e4e rdd1cc02  
    88-2
    991200 2
     106 5985 1530 6165 3105
     111 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6075 1620 90 90 6075 1620 6075 1710
     121 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6075 2340 90 90 6075 2340 6075 2430
     131 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6075 3015 90 90 6075 3015 6075 3105
     142 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     15        1 1 1.00 60.00 120.00
     16         6075 1755 6075 2205
     172 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     18        1 1 1.00 60.00 120.00
     19         6075 2475 6075 2925
     20-6
     216 3465 1530 3645 3105
     221 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3555 1620 90 90 3555 1620 3555 1710
     231 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3555 2340 90 90 3555 2340 3555 2430
     241 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3555 3015 90 90 3555 3015 3555 3105
     252 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     26        1 1 1.00 60.00 120.00
     27         3555 1755 3555 2205
     282 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     29        1 1 1.00 60.00 120.00
     30         3555 2475 3555 2925
     31-6
     326 2115 1530 2295 3105
     331 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2205 1620 90 90 2205 1620 2205 1710
     341 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2205 2340 90 90 2205 2340 2205 2430
     351 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2205 3015 90 90 2205 3015 2205 3105
     362 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     37        1 1 1.00 60.00 120.00
     38         2205 1755 2205 2205
     392 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     40        1 1 1.00 60.00 120.00
     41         2205 2475 2205 2925
     42-6
    10431 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4905 1620 90 90 4905 1620 4905 1710
     441 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4905 3015 90 90 4905 3015 4905 3105
    11451 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4905 945 90 90 4905 945 4905 1035
    12461 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4905 2340 90 90 4905 2340 4905 2430
    13 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1665 1620 90 90 1665 1620 1665 1710
    14 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1665 2340 90 90 1665 2340 1665 2430
    15 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1665 3060 90 90 1665 3060 1665 3150
    16 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3195 1620 90 90 3195 1620 3195 1710
    17 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3195 2340 90 90 3195 2340 3195 2430
    18 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3195 3060 90 90 3195 3060 3195 3150
    19 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6525 1620 90 90 6525 1620 6525 1710
    20 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6525 2340 90 90 6525 2340 6525 2430
    21 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4905 3060 90 90 4905 3060 4905 3150
    22 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6525 3060 90 90 6525 3060 6525 3150
     472 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     48        1 1 1.00 60.00 120.00
     49         2790 1620 2430 1620
     502 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     51        1 1 1.00 60.00 120.00
     52         4095 2340 3735 2340
     532 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     54        1 1 1.00 60.00 120.00
     55         6660 1620 6300 1620
     562 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
     57        1 1 1.00 60.00 120.00
     58         5490 945 5130 945
    23592 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    2460        1 1 1.00 60.00 120.00
     
    3066        1 1 1.00 60.00 120.00
    3167         4770 1080 4590 1260 4590 2070 4770 2250
    32 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    33         1 1 1.00 60.00 120.00
    34          1665 1755 1665 2205
    35 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    36         1 1 1.00 60.00 120.00
    37          1665 2475 1665 2925
    38 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    39         1 1 1.00 60.00 120.00
    40          3195 1755 3195 2205
    41 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    42         1 1 1.00 60.00 120.00
    43          3195 2475 3195 2925
    44 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    45         1 1 1.00 60.00 120.00
    46          6525 1755 6525 2205
    47 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    48         1 1 1.00 60.00 120.00
    49          6525 2475 6525 2925
    50 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    51         1 1 1.00 60.00 120.00
    52          1260 1620 1485 1620
    53 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    54         1 1 1.00 60.00 120.00
    55          1980 1440 1755 1440
    56 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    57         1 1 1.00 60.00 120.00
    58          2790 2340 3015 2340
    59 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    60         1 1 1.00 60.00 120.00
    61          3600 1620 3375 1620
    62 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    63         1 1 1.00 60.00 120.00
    64          4500 945 4725 945
    65 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    66         1 1 1.00 60.00 120.00
    67          5265 765 5040 765
    68 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    69         1 1 1.00 60.00 120.00
    70          6120 1620 6345 1620
    71 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    72         1 1 1.00 60.00 120.00
    73          6840 1440 6615 1440
    74 4 1 0 50 -1 0 12 0.0000 0 135 1170 1665 3375 Initial State\001
    75 4 1 0 50 -1 0 12 0.0000 0 135 1170 3195 3375 Found Handler\001
    76 4 1 0 50 -1 0 12 0.0000 0 165 1530 6570 3375 Handling Complete\001
    77 4 2 0 50 -1 0 12 0.0000 0 135 720 1485 2385 handlers\001
    78 4 1 0 50 -1 0 12 0.0000 0 135 900 4905 3375 Handler in\001
    79 4 1 0 50 -1 0 12 0.0000 0 165 810 4905 3600 Try block\001
    80 4 0 0 50 -1 0 12 0.0000 0 135 360 855 1665 head\001
    81 4 0 0 50 -1 0 12 0.0000 4 120 810 2025 1485 execution\001
    82 4 0 0 50 -1 0 12 0.0000 0 135 360 2385 2385 head\001
    83 4 0 0 50 -1 0 12 0.0000 4 120 810 3645 1665 execution\001
    84 4 0 0 50 -1 0 12 0.0000 0 135 360 4095 990 head\001
    85 4 0 0 50 -1 0 12 0.0000 4 120 810 5310 810 execution\001
    86 4 0 0 50 -1 0 12 0.0000 0 135 360 5715 1665 head\001
    87 4 0 0 50 -1 0 12 0.0000 4 120 810 6885 1485 execution\001
     684 0 0 50 -1 0 12 0.0000 4 135 1170 1980 3375 Initial State\001
     694 0 0 50 -1 0 12 0.0000 4 135 1170 3420 3375 Found Handler\001
     704 0 0 50 -1 0 12 0.0000 4 165 810 4770 3375 Try block\001
     714 0 0 50 -1 0 12 0.0000 4 135 900 4770 3555 in Handler\001
     724 0 0 50 -1 0 12 0.0000 4 165 1530 5940 3375 Handling Complete\001
  • doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex

    r5a40e4e rdd1cc02  
    129129\begin{center}\textbf{Abstract}\end{center}
    130130
    131 The \CFA (Cforall) programming language is an evolutionary refinement of
    132 the C programming language, adding modern programming features without
    133 changing the programming paradigms of C.
    134 One of these modern programming features is more powerful error handling
    135 through the addition of an exception handling mechanism (EHM).
    136 
    137 This thesis covers the design and implementation of the \CFA EHM,
    138 along with a review of the other required \CFA features.
    139 The EHM includes common features of termination exception handling and
    140 similar support for resumption exception handling.
    141 The design of both has been adapted to utilize other tools \CFA provides,
    142 as well as fit with the assertion based interfaces of the language.
    143 
    144 The EHM has been implemented into the \CFA compiler and run-time environment.
    145 Although it has not yet been optimized, performance testing has shown it has
    146 comparable performance to other EHM's,
    147 which is sufficient for use in current \CFA programs.
     131This is the abstract.
    148132
    149133\cleardoublepage
     
    154138\begin{center}\textbf{Acknowledgements}\end{center}
    155139
    156 I would like to thank all the people who made this thesis possible.
    157 (I'm waiting until who is involved is finalized.)
    158 
     140I would like to thank all the little people who made this thesis possible.
    159141\cleardoublepage
    160142
  • doc/theses/andrew_beach_MMath/uw-ethesis.bib

    r5a40e4e rdd1cc02  
    11% Bibliography of key references for "LaTeX for Thesis and Large Documents"
    22% For use with BibTeX
    3 % The online reference does not seem to be supported here.
    43
    5 @misc{Dice21,
    6     author      = {Dave Dice},
    7     year        = 2021,
    8     month       = aug,
    9     howpublished= {personal communication}
     4@book{goossens.book,
     5        author =        "Michel Goossens and Frank Mittelbach and
     6                         Alexander Samarin",
     7        title =         "The \LaTeX\ Companion",
     8        year =          "1994",
     9        publisher =     "Addison-Wesley",
     10        address =       "Reading, Massachusetts"
    1011}
    1112
    12 @misc{CforallExceptionBenchmarks,
    13     contributer = {pabuhr@plg},
    14     key         = {Cforall Exception Benchmarks},
    15     author      = {{\textsf{C}{$\mathbf{\forall}$} Exception Benchmarks}},
    16     howpublished= {\href{https://github.com/cforall/ExceptionBenchmarks_SPE20}{https://\-github.com/\-cforall/\-ExceptionBenchmarks\_SPE20}},
     13@book{knuth.book,
     14        author =        "Donald Knuth",
     15        title =         "The \TeX book",
     16        year =          "1986",
     17        publisher =     "Addison-Wesley",
     18        address =       "Reading, Massachusetts"
    1719}
    1820
    19 % Could not get `#the-for-statement` to work.
    20 @misc{PythonForLoop,
    21     author={Python Software Foundation},
    22     key={Python Compound Statements},
    23     howpublished={\href{https://docs.python.org/3/reference/compound_stmts.html}{https://\-docs.python.org/\-3/\-reference/\-compound\_stmts.html}},
    24     addendum={Accessed 2021-08-30},
     21@book{lamport.book,
     22        author =        "Leslie Lamport",
     23        title =         "\LaTeX\ --- A Document Preparation System",
     24        edition =       "Second",
     25        year =          "1994",
     26        publisher =     "Addison-Wesley",
     27        address =       "Reading, Massachusetts"
    2528}
    26 
    27 % Again, I would like this to have `#StopIteration`.
    28 @misc{PythonExceptions,
    29     author={Python Software Foundation},
    30     key={Python Exceptions},
    31     howpublished={\href{https://docs.python.org/3/library/exceptions.html}{https://\-docs.python.org/\-3/\-library/\-exceptions.html}},
    32     addendum={Accessed 2021-08-30},
    33 }
    34 
    35 @misc{CppHistory,
    36     author={C++ Community},
    37     key={Cpp Reference History},
    38     howpublished={\href{https://en.cppreference.com/w/cpp/language/history}{https://\-en.cppreference.com/\-w/\-cpp/\-language/\-history}},
    39     addendum={Accessed 2021-08-30},
    40 }
    41 
    42 @misc{RustPanicMacro,
    43     author={The Rust Team},
    44     key={Rust Panic Macro},
    45     howpublished={\href{https://doc.rust-lang.org/std/panic/index.html}{https://\-doc.rust-lang.org/\-std/\-panic/\-index.html}},
    46     addendum={Accessed 2021-08-31},
    47 }
    48 
    49 @misc{RustPanicModule,
    50     author={The Rust Team},
    51     key={Rust Panic Module},
    52     howpublished={\href{https://doc.rust-lang.org/std/panic/index.html}{https://\-doc.rust-lang.org/\-std/\-panic/\-index.html}},
    53     addendum={Accessed 2021-08-31},
    54 }
    55 
    56 @manual{Go:2021,
    57     keywords={Go programming language},
    58     author={Robert Griesemer and Rob Pike and Ken Thompson},
    59     title={{Go} Programming Language},
    60     organization={Google},
    61     year=2021,
    62     note={\href{http://golang.org/ref/spec}{http://\-golang.org/\-ref/\-spec}},
    63     addendum={Accessed 2021-08-31},
    64 }
  • doc/theses/andrew_beach_MMath/uw-ethesis.tex

    r5a40e4e rdd1cc02  
    210210\lstMakeShortInline@
    211211\lstset{language=CFA,style=cfacommon,basicstyle=\linespread{0.9}\tt}
     212% PAB causes problems with inline @=
     213%\lstset{moredelim=**[is][\protect\color{red}]{@}{@}}
    212214% Annotations from Peter:
    213215\newcommand{\PAB}[1]{{\color{blue}PAB: #1}}
  • doc/theses/andrew_beach_MMath/vtable-layout.fig

    r5a40e4e rdd1cc02  
    88-2
    991200 2
     102 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1
     11         1620 1665
    10122 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    1113         3510 1890 3645 1755
     
    14162 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    1517         3645 1305 3645 1755
    16 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    17          2115 1935 2250 1935
    18 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
    19          2250 1170 2115 1170 2115 2475 2250 2475
    20 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    21          2250 1350 2115 1350
    22184 0 0 50 -1 0 12 0.0000 4 165 630 2295 1305 type_id\001
    23194 0 0 50 -1 0 12 0.0000 4 165 1170 2295 1500 parent_field0\001
  • libcfa/prelude/builtins.c

    r5a40e4e rdd1cc02  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug 14 08:45:54 2021
    13 // Update Count     : 133
     12// Last Modified On : Wed Jul 21 13:31:34 2021
     13// Update Count     : 129
    1414//
    1515
     
    107107#endif // __SIZEOF_INT128__
    108108
    109 // for-control index constraints
    110 // forall( T | { void ?{}( T &, zero_t ); void ?{}( T &, one_t ); T ?+=?( T &, T ); T ?-=?( T &, T ); int ?<?( T, T ); } )
    111 // static inline T __for_control_index_constraints__( T t ) { return t; }
    112 
    113109// exponentiation operator implementation
    114110
  • libcfa/src/Makefile.am

    r5a40e4e rdd1cc02  
    4848        math.hfa \
    4949        time_t.hfa \
    50         bits/algorithm.hfa \
    5150        bits/align.hfa \
    5251        bits/containers.hfa \
     
    7877        memory.hfa \
    7978        parseargs.hfa \
    80         parseconfig.hfa \
    8179        rational.hfa \
    8280        stdlib.hfa \
     
    8785        containers/pair.hfa \
    8886        containers/result.hfa \
    89         containers/string.hfa \
    90         containers/string_res.hfa \
    9187        containers/vector.hfa \
    9288        device/cpu.hfa
     
    9490libsrc = ${inst_headers_src} ${inst_headers_src:.hfa=.cfa} \
    9591        assert.cfa \
     92        bits/algorithm.hfa \
    9693        bits/debug.cfa \
    9794        exception.c \
     
    109106        concurrency/invoke.h \
    110107        concurrency/future.hfa \
    111         concurrency/kernel/fwd.hfa \
    112         concurrency/mutex_stmt.hfa
     108        concurrency/kernel/fwd.hfa
    113109
    114110inst_thread_headers_src = \
  • libcfa/src/concurrency/kernel/startup.cfa

    r5a40e4e rdd1cc02  
    235235
    236236        register_tls( mainProcessor );
    237         mainThread->last_cpu = __kernel_getcpu();
    238237
    239238        //initialize the global state variables
     
    479478        state = Start;
    480479        self_cor{ info };
     480        last_cpu = __kernel_getcpu();
    481481        curr_cor = &self_cor;
    482482        curr_cluster = mainCluster;
  • libcfa/src/concurrency/locks.hfa

    r5a40e4e rdd1cc02  
    324324        }
    325325
     326        // linear backoff bounded by spin_count
     327        spin = spin_start;
     328        int spin_counter = 0;
     329        int yield_counter = 0;
     330        for ( ;; ) {
     331                if(try_lock_contention(this)) return true;
     332                if(spin_counter < spin_count) {
     333                        for (int i = 0; i < spin; i++) Pause();
     334                        if (spin < spin_end) spin += spin;
     335                        else spin_counter++;
     336                } else if (yield_counter < yield_count) {
     337                        // after linear backoff yield yield_count times
     338                        yield_counter++;
     339                        yield();
     340                } else { break; }
     341        }
     342
     343        // block until signalled
     344        while (block(this)) if(try_lock_contention(this)) return true;
     345
     346        // this should never be reached as block(this) always returns true
     347        return false;
     348}
     349
     350static inline bool lock_improved(linear_backoff_then_block_lock & this) with(this) {
     351        // if owner just return
     352        if (active_thread() == owner) return true;
     353        size_t compare_val = 0;
     354        int spin = spin_start;
     355        // linear backoff
     356        for( ;; ) {
     357                compare_val = 0;
     358                if (internal_try_lock(this, compare_val)) return true;
     359                if (2 == compare_val) break;
     360                for (int i = 0; i < spin; i++) Pause();
     361                if (spin >= spin_end) break;
     362                spin += spin;
     363        }
     364
     365        // linear backoff bounded by spin_count
     366        spin = spin_start;
     367        int spin_counter = 0;
     368        int yield_counter = 0;
     369        for ( ;; ) {
     370                compare_val = 0;
     371                if(internal_try_lock(this, compare_val)) return true;
     372                if (2 == compare_val) break;
     373                if(spin_counter < spin_count) {
     374                        for (int i = 0; i < spin; i++) Pause();
     375                        if (spin < spin_end) spin += spin;
     376                        else spin_counter++;
     377                } else if (yield_counter < yield_count) {
     378                        // after linear backoff yield yield_count times
     379                        yield_counter++;
     380                        yield();
     381                } else { break; }
     382        }
     383
    326384        if(2 != compare_val && try_lock_contention(this)) return true;
    327385        // block until signalled
     
    344402static inline void on_notify(linear_backoff_then_block_lock & this, struct thread$ * t ) { unpark(t); }
    345403static inline size_t on_wait(linear_backoff_then_block_lock & this) { unlock(this); return 0; }
    346 static inline void on_wakeup(linear_backoff_then_block_lock & this, size_t recursion ) { lock(this); }
     404static inline void on_wakeup(linear_backoff_then_block_lock & this, size_t recursion ) { lock_improved(this); }
    347405
    348406//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/monitor.cfa

    r5a40e4e rdd1cc02  
    367367
    368368        // __cfaabi_dbg_print_safe( "MGUARD : entered\n" );
    369 }
    370 
    371 void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count ) {
    372         this{ m, count, 0p };
    373369}
    374370
     
    990986}
    991987
    992 //-----------------------------------------------------------------------------
    993 // Enter routine for mutex stmt
    994 // Can't be accepted since a mutex stmt is effectively an anonymous routine
    995 // Thus we do not need a monitor group
    996 void lock( monitor$ * this ) {
    997         thread$ * thrd = active_thread();
    998 
    999         // Lock the monitor spinlock
    1000         lock( this->lock __cfaabi_dbg_ctx2 );
    1001 
    1002         __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    1003 
    1004         if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
    1005                 abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
    1006         }
    1007         else if( !this->owner ) {
    1008                 // No one has the monitor, just take it
    1009                 __set_owner( this, thrd );
    1010 
    1011                 __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
    1012         }
    1013         else if( this->owner == thrd) {
    1014                 // We already have the monitor, just note how many times we took it
    1015                 this->recursion += 1;
    1016 
    1017                 __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
    1018         }
    1019         else {
    1020                 __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    1021 
    1022                 // Some one else has the monitor, wait in line for it
    1023                 /* paranoid */ verify( thrd->link.next == 0p );
    1024                 append( this->entry_queue, thrd );
    1025                 /* paranoid */ verify( thrd->link.next == 1p );
    1026 
    1027                 unlock( this->lock );
    1028                 park();
    1029 
    1030                 __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    1031 
    1032                 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    1033                 return;
    1034         }
    1035 
    1036         __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    1037 
    1038         /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    1039         /* paranoid */ verify( this->lock.lock );
    1040 
    1041         // Release the lock and leave
    1042         unlock( this->lock );
    1043         return;
    1044 }
    1045 
    1046 // Leave routine for mutex stmt
    1047 // Is just a wrapper around __leave for the is_lock trait to see
    1048 void unlock( monitor$ * this ) { __leave( this ); }
    1049 
    1050988// Local Variables: //
    1051989// mode: c //
  • libcfa/src/concurrency/monitor.hfa

    r5a40e4e rdd1cc02  
    4848
    4949void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count, void (*func)() );
    50 void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count );
    5150void ^?{}( monitor_guard_t & this );
    5251
     
    149148void __waitfor_internal( const __waitfor_mask_t & mask, int duration );
    150149
    151 // lock and unlock routines for mutex statements to use
    152 void lock( monitor$ * this );
    153 void unlock( monitor$ * this );
    154 
    155150// Local Variables: //
    156151// mode: c //
  • libcfa/src/concurrency/thread.cfa

    r5a40e4e rdd1cc02  
    3434        preempted = __NO_PREEMPTION;
    3535        corctx_flag = false;
    36         disable_interrupts();
    3736        last_cpu = __kernel_getcpu();
    38         enable_interrupts();
    3937        curr_cor = &self_cor;
    4038        self_mon.owner = &this;
  • libcfa/src/fstream.cfa

    r5a40e4e rdd1cc02  
    124124void open( ofstream & os, const char name[], const char mode[] ) {
    125125        FILE * file = fopen( name, mode );
    126         // #ifdef __CFA_DEBUG__
     126        #ifdef __CFA_DEBUG__
    127127        if ( file == 0p ) {
    128128                throw (Open_Failure){ os };
    129129                // abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno );
    130130        } // if
    131         // #endif // __CFA_DEBUG__
     131        #endif // __CFA_DEBUG__
    132132        (os){ file };
    133133} // open
     
    262262void open( ifstream & is, const char name[], const char mode[] ) {
    263263        FILE * file = fopen( name, mode );
    264         // #ifdef __CFA_DEBUG__
     264        #ifdef __CFA_DEBUG__
    265265        if ( file == 0p ) {
    266266                throw (Open_Failure){ is };
    267267                // abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno );
    268268        } // if
    269         // #endif // __CFA_DEBUG__
     269        #endif // __CFA_DEBUG__
    270270        is.file$ = file;
    271271} // open
  • libcfa/src/heap.cfa

    r5a40e4e rdd1cc02  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug  9 19:03:02 2021
    13 // Update Count     : 1040
     12// Last Modified On : Sat May 22 08:46:39 2021
     13// Update Count     : 1036
    1414//
    1515
     
    102102} // prtUnfreed
    103103
    104 extern int cfa_main_returned;                                                   // from bootloader.cf
    105104extern "C" {
    106105        void heapAppStart() {                                                           // called by __cfaabi_appready_startup
     
    110109        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    111110                fclose( stdin ); fclose( stdout );
    112                 if ( cfa_main_returned ) prtUnfreed();                  // do not check unfreed storage if exit called
     111                prtUnfreed();
    113112        } // heapAppStop
    114113} // extern "C"
  • libcfa/src/memory.cfa

    r5a40e4e rdd1cc02  
    155155
    156156forall(T &)
    157 T * release(unique_ptr(T) & this) {
    158         T * data = this.data;
    159         this.data = 0p;
    160         return data;
    161 }
    162 
    163 forall(T &)
    164157int ?==?(unique_ptr(T) const & this, unique_ptr(T) const & that) {
    165158        return this.data == that.data;
  • libcfa/src/memory.hfa

    r5a40e4e rdd1cc02  
    9494
    9595forall(T &)
    96 T * release(unique_ptr(T) & this);
    97 
    98 forall(T &)
    9996int ?==?(unique_ptr(T) const & this, unique_ptr(T) const & that);
    10097forall(T &)
  • src/AST/Convert.cpp

    r5a40e4e rdd1cc02  
    606606        }
    607607
    608         const ast::Stmt * visit( const ast::MutexStmt * node ) override final {
    609                 if ( inCache( node ) ) return nullptr;
    610                  auto stmt = new MutexStmt(
    611                         get<Statement>().accept1( node->stmt ),
    612                         get<Expression>().acceptL( node->mutexObjs )
    613                 );
    614                 return stmtPostamble( stmt, node );
    615         }
    616 
    617608        TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
    618609
     
    21332124        }
    21342125
    2135         virtual void visit( const MutexStmt * old ) override final {
    2136                 if ( inCache( old ) ) return;
    2137                 this->node = new ast::MutexStmt(
    2138                         old->location,
    2139                         GET_ACCEPT_1(stmt, Stmt),
    2140                         GET_ACCEPT_V(mutexObjs, Expr)
    2141                 );
    2142                 cache.emplace( old, this->node );
    2143         }
    2144 
    21452126        // TypeSubstitution shouldn't exist yet in old.
    21462127        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
  • src/AST/Fwd.hpp

    r5a40e4e rdd1cc02  
    6060class NullStmt;
    6161class ImplicitCtorDtorStmt;
    62 class MutexStmt;
    6362
    6463class Expr;
  • src/AST/Node.cpp

    r5a40e4e rdd1cc02  
    176176template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::weak >;
    177177template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::strong >;
    178 template class ast::ptr_base< ast::MutexStmt, ast::Node::ref_type::weak >;
    179 template class ast::ptr_base< ast::MutexStmt, ast::Node::ref_type::strong >;
    180178template class ast::ptr_base< ast::Expr, ast::Node::ref_type::weak >;
    181179template class ast::ptr_base< ast::Expr, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    r5a40e4e rdd1cc02  
    162162        const ast::Stmt *             visit( const ast::DeclStmt             * ) override final;
    163163        const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * ) override final;
    164         const ast::Stmt *             visit( const ast::MutexStmt            * ) override final;
    165164        const ast::Expr *             visit( const ast::ApplicationExpr      * ) override final;
    166165        const ast::Expr *             visit( const ast::UntypedExpr          * ) override final;
  • src/AST/Pass.impl.hpp

    r5a40e4e rdd1cc02  
    10391039
    10401040//--------------------------------------------------------------------------
    1041 // MutexStmt
    1042 template< typename core_t >
    1043 const ast::Stmt * ast::Pass< core_t >::visit( const ast::MutexStmt * node ) {
    1044         VISIT_START( node );
    1045 
    1046         VISIT({
    1047                 // mutex statements introduce a level of scope (for the initialization)
    1048                 guard_symtab guard { *this };
    1049                 maybe_accept( node, &MutexStmt::stmt );
    1050                 maybe_accept( node, &MutexStmt::mutexObjs );
    1051         })
    1052 
    1053         VISIT_END( Stmt, node );
    1054 }
    1055 
    1056 //--------------------------------------------------------------------------
    10571041// ApplicationExpr
    10581042template< typename core_t >
  • src/AST/Print.cpp

    r5a40e4e rdd1cc02  
    794794                ++indent;
    795795                safe_print( node->callStmt );
    796                 --indent;
    797                 os << endl;
    798 
    799                 return node;
    800         }
    801 
    802         virtual const ast::Stmt * visit( const ast::MutexStmt * node ) override final {
    803                 os << "Mutex Statement" << endl;
    804                 os << indent << "... with Mutex Parameters: ";
    805                 ++indent;
    806                 printAll( node->mutexObjs );
    807                 --indent;
    808                 os << indent << "... with Statement: ";
    809                 ++indent;
    810                 safe_print( node->stmt );
    811796                --indent;
    812797                os << endl;
  • src/AST/Stmt.hpp

    r5a40e4e rdd1cc02  
    426426};
    427427
    428 /// Mutex Statement
    429 class MutexStmt final : public Stmt {
    430 public:
    431         ptr<Stmt> stmt;
    432         std::vector<ptr<Expr>> mutexObjs;
    433 
    434         MutexStmt( const CodeLocation & loc, const Stmt * stmt,
    435                 std::vector<ptr<Expr>> && mutexes, std::vector<Label> && labels = {} )
    436         : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
    437 
    438         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    439 private:
    440         MutexStmt * clone() const override { return new MutexStmt{ *this }; }
    441         MUTATE_FRIEND
    442 };
    443 
    444428}
    445429
  • src/AST/Visitor.hpp

    r5a40e4e rdd1cc02  
    5454    virtual const ast::Stmt *             visit( const ast::DeclStmt             * ) = 0;
    5555    virtual const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * ) = 0;
    56     virtual const ast::Stmt *             visit( const ast::MutexStmt            * ) = 0;
    5756    virtual const ast::Expr *             visit( const ast::ApplicationExpr      * ) = 0;
    5857    virtual const ast::Expr *             visit( const ast::UntypedExpr          * ) = 0;
  • src/CodeGen/CodeGenerator.cc

    r5a40e4e rdd1cc02  
    11871187        }
    11881188
    1189         void CodeGenerator::postvisit( MutexStmt * stmt ) {
    1190                 assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
    1191                 stmt->stmt->accept( *visitor );
    1192         }
    1193 
    11941189        void CodeGenerator::handleStorageClass( DeclarationWithType * decl ) {
    11951190                if ( decl->get_storageClasses().any() ) {
  • src/CodeGen/CodeGenerator.h

    r5a40e4e rdd1cc02  
    121121                void postvisit( DeclStmt * );
    122122                void postvisit( ImplicitCtorDtorStmt * );
    123                 void postvisit( MutexStmt * stmt );
    124123
    125124                void genAttributes( std::list< Attribute * > & attributes );
  • src/Common/CodeLocationTools.cpp

    r5a40e4e rdd1cc02  
    125125    macro(DeclStmt, Stmt) \
    126126    macro(ImplicitCtorDtorStmt, Stmt) \
    127     macro(MutexStmt, Stmt) \
    128127    macro(ApplicationExpr, Expr) \
    129128    macro(UntypedExpr, Expr) \
  • src/Common/PassVisitor.h

    r5a40e4e rdd1cc02  
    124124        virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    125125        virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    126         virtual void visit( MutexStmt * mutexStmt ) override final;
    127         virtual void visit( const MutexStmt * mutexStmt ) override final;
    128126
    129127        virtual void visit( ApplicationExpr * applicationExpr ) override final;
     
    293291        virtual Statement * mutate( DeclStmt * declStmt ) override final;
    294292        virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    295         virtual Statement * mutate( MutexStmt * mutexStmt ) override final;
    296293
    297294        virtual Expression * mutate( ApplicationExpr * applicationExpr ) override final;
  • src/Common/PassVisitor.impl.h

    r5a40e4e rdd1cc02  
    17811781
    17821782//--------------------------------------------------------------------------
    1783 // MutexStmt
    1784 template< typename pass_type >
    1785 void PassVisitor< pass_type >::visit( MutexStmt * node ) {
    1786         VISIT_START( node );
    1787         // mutex statements introduce a level of scope (for the initialization)
    1788         maybeAccept_impl( node->mutexObjs, *this );
    1789         {
    1790                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1791                 node->stmt = visitStatement( node->stmt );
    1792         }
    1793         VISIT_END( node );
    1794 }
    1795 
    1796 template< typename pass_type >
    1797 void PassVisitor< pass_type >::visit( const MutexStmt * node ) {
    1798         VISIT_START( node );
    1799         maybeAccept_impl( node->mutexObjs, *this );
    1800         {
    1801                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1802                 visitStatement( node->stmt );
    1803         }
    1804         VISIT_END( node );
    1805 }
    1806 
    1807 template< typename pass_type >
    1808 Statement * PassVisitor< pass_type >::mutate( MutexStmt * node ) {
    1809         MUTATE_START( node );
    1810         maybeMutate_impl( node->mutexObjs, *this );
    1811         {
    1812                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1813                 node->stmt = mutateStatement( node->stmt );
    1814         }
    1815         MUTATE_END( Statement, node );
    1816 }
    1817 
    1818 //--------------------------------------------------------------------------
    18191783// ApplicationExpr
    18201784template< typename pass_type >
  • src/Concurrency/Keywords.cc

    r5a40e4e rdd1cc02  
    9393                ObjectDecl * addField( StructDecl * );
    9494                void addRoutines( ObjectDecl *, FunctionDecl * );
    95                 void addLockUnlockRoutines( StructDecl * );
    9695
    9796                virtual bool is_target( StructDecl * decl ) = 0;
     
    303302                void postvisit( FunctionDecl * decl );
    304303                void postvisit(   StructDecl * decl );
    305                 Statement * postmutate( MutexStmt * stmt );
    306304
    307305                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
     
    309307                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    310308                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    311                 void addStatements( CompoundStmt * body, const std::list<Expression * > & args );
    312309                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
    313310
     
    315312                        PassVisitor< MutexKeyword > impl;
    316313                        acceptAll( translationUnit, impl );
    317                         mutateAll( translationUnit, impl );
    318314                }
    319315
     
    323319                StructDecl* dtor_guard_decl = nullptr;
    324320                StructDecl* thread_guard_decl = nullptr;
    325                 StructDecl* lock_guard_decl = nullptr;
    326321
    327322                static std::unique_ptr< Type > generic_func;
     
    465460        }
    466461
     462
    467463        void ConcurrentSueKeyword::handle( StructDecl * decl ) {
    468464                if( ! decl->body ) return;
     
    480476                FunctionDecl * func = forwardDeclare( decl );
    481477                ObjectDecl * field = addField( decl );
    482 
    483                 // add get_.* routine
    484478                addRoutines( field, func );
    485                 // add lock/unlock routines to monitors for use by mutex stmt
    486                 addLockUnlockRoutines( decl );
    487479        }
    488480
     
    617609        }
    618610
    619         // This function adds the get_.* routine body for coroutines, monitors etc
    620         //              after their corresponding struct has been made
    621611        void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
    622612                CompoundStmt * statement = new CompoundStmt();
     
    641631
    642632                declsToAddAfter.push_back( get_decl );
    643         }
    644 
    645         // Generates lock/unlock routines for monitors to be used by mutex stmts
    646         void ConcurrentSueKeyword::addLockUnlockRoutines( StructDecl * decl ) {
    647                 // this routine will be called for all ConcurrentSueKeyword children so only continue if we are a monitor
    648                 if ( !decl->is_monitor() ) return;
    649 
    650                 FunctionType * lock_fn_type = new FunctionType( noQualifiers, false );
    651                 FunctionType * unlock_fn_type = new FunctionType( noQualifiers, false );
    652 
    653                 // create this ptr parameter for both routines
    654                 ObjectDecl * this_decl = new ObjectDecl(
    655                         "this",
    656                         noStorageClasses,
    657                         LinkageSpec::Cforall,
    658                         nullptr,
    659                         new ReferenceType(
    660                                 noQualifiers,
    661                                 new StructInstType(
    662                                         noQualifiers,
    663                                         decl
    664                                 )
    665                         ),
    666                         nullptr
    667                 );
    668 
    669                 lock_fn_type->get_parameters().push_back( this_decl->clone() );
    670                 unlock_fn_type->get_parameters().push_back( this_decl->clone() );
    671                 fixupGenerics(lock_fn_type, decl);
    672                 fixupGenerics(unlock_fn_type, decl);
    673 
    674                 delete this_decl;
    675 
    676 
    677                 //////////////////////////////////////////////////////////////////////
    678                 // The following generates this lock routine for all monitors
    679                 /*
    680                         void lock (monitor_t & this) {
    681                                 lock(get_monitor(this));
    682                         }       
    683                 */
    684                 FunctionDecl * lock_decl = new FunctionDecl(
    685                         "lock",
    686                         Type::Static,
    687                         LinkageSpec::Cforall,
    688                         lock_fn_type,
    689                         nullptr,
    690                         { },
    691                         Type::Inline
    692                 );
    693 
    694                 UntypedExpr * get_monitor_lock =  new UntypedExpr (
    695                         new NameExpr( "get_monitor" ),
    696                         { new VariableExpr( lock_fn_type->get_parameters().front() ) }
    697                 );
    698 
    699                 CompoundStmt * lock_statement = new CompoundStmt();
    700                 lock_statement->push_back(
    701                         new ExprStmt(
    702                                 new UntypedExpr (
    703                                         new NameExpr( "lock" ),
    704                                         {
    705                                                 get_monitor_lock
    706                                         }
    707                                 )
    708                         )
    709                 );
    710                 lock_decl->set_statements( lock_statement );
    711 
    712                 //////////////////////////////////////////////////////////////////
    713                 // The following generates this routine for all monitors
    714                 /*
    715                         void unlock (monitor_t & this) {
    716                                 unlock(get_monitor(this));
    717                         }       
    718                 */
    719                 FunctionDecl * unlock_decl = new FunctionDecl(
    720                         "unlock",
    721                         Type::Static,
    722                         LinkageSpec::Cforall,
    723                         unlock_fn_type,
    724                         nullptr,
    725                         { },
    726                         Type::Inline
    727                 );
    728 
    729                 CompoundStmt * unlock_statement = new CompoundStmt();
    730 
    731                 UntypedExpr * get_monitor_unlock =  new UntypedExpr (
    732                         new NameExpr( "get_monitor" ),
    733                         { new VariableExpr( unlock_fn_type->get_parameters().front() ) }
    734                 );
    735 
    736                 unlock_statement->push_back(
    737                         new ExprStmt(
    738                                 new UntypedExpr(
    739                                         new NameExpr( "unlock" ),
    740                                         {
    741                                                 get_monitor_unlock
    742                                         }
    743                                 )
    744                         )
    745                 );
    746                 unlock_decl->set_statements( unlock_statement );
    747                
    748                 // pushes routines to declsToAddAfter to add at a later time
    749                 declsToAddAfter.push_back( lock_decl );
    750                 declsToAddAfter.push_back( unlock_decl );
    751633        }
    752634
     
    1052934                        assert( !thread_guard_decl );
    1053935                        thread_guard_decl = decl;
    1054                 }
    1055                 else if ( decl->name == "__mutex_stmt_lock_guard" && decl->body ) {
    1056                         assert( !lock_guard_decl );
    1057                         lock_guard_decl = decl;
    1058                 }
    1059         }
    1060 
    1061         Statement * MutexKeyword::postmutate( MutexStmt * stmt ) {
    1062                 std::list<Statement *> stmtsForCtor;
    1063                 stmtsForCtor.push_back(stmt->stmt);
    1064                 CompoundStmt * body = new CompoundStmt( stmtsForCtor );
    1065                 addStatements( body, stmt->mutexObjs);
    1066                 return body;
     936                }
    1067937        }
    1068938
     
    11881058                        ))
    11891059                );
    1190         }
    1191 
    1192         void MutexKeyword::addStatements( CompoundStmt * body, const std::list<Expression * > & args ) {
    1193                 ObjectDecl * monitors = new ObjectDecl(
    1194                         "__monitors",
    1195                         noStorageClasses,
    1196                         LinkageSpec::Cforall,
    1197                         nullptr,
    1198                         new ArrayType(
    1199                                 noQualifiers,
    1200                                 new PointerType(
    1201                                         noQualifiers,
    1202                                         new TypeofType( noQualifiers, args.front()->clone() )
    1203                                 ),
    1204                                 new ConstantExpr( Constant::from_ulong( args.size() ) ),
    1205                                 false,
    1206                                 false
    1207                         ),
    1208                         new ListInit(
    1209                                 map_range < std::list<Initializer*> > ( args, [](Expression * var ){
    1210                                         return new SingleInit( new AddressExpr( var ) );
    1211                                 })
    1212                         )
    1213                 );
    1214 
    1215                 StructInstType * lock_guard_struct = new StructInstType( noQualifiers, lock_guard_decl );
    1216                 TypeExpr * lock_type_expr = new TypeExpr( new TypeofType( noQualifiers, args.front()->clone() ) );
    1217 
    1218                 lock_guard_struct->parameters.push_back( lock_type_expr ) ;
    1219 
    1220                 // in reverse order :
    1221                 // monitor_guard_t __guard = { __monitors, # };
    1222                 body->push_front(
    1223                         new DeclStmt( new ObjectDecl(
    1224                                 "__guard",
    1225                                 noStorageClasses,
    1226                                 LinkageSpec::Cforall,
    1227                                 nullptr,
    1228                                 lock_guard_struct,
    1229                                 new ListInit(
    1230                                         {
    1231                                                 new SingleInit( new VariableExpr( monitors ) ),
    1232                                                 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
    1233                                         },
    1234                                         noDesignators,
    1235                                         true
    1236                                 )
    1237                         ))
    1238                 );
    1239 
    1240                 //monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
    1241                 body->push_front( new DeclStmt( monitors) );
    12421060        }
    12431061
  • src/MakeLibCfa.h

    r5a40e4e rdd1cc02  
    1919
    2020class Declaration;
    21 namespace ast {
    22         struct TranslationUnit;
    23 }
    2421
    2522namespace LibCfa {
    2623        void makeLibCfa( std::list< Declaration* > &prelude );
    27         void makeLibCfa( ast::TranslationUnit & translationUnit );
    2824} // namespace LibCfa
    2925
  • src/Makefile.am

    r5a40e4e rdd1cc02  
    2323      CompilationState.h \
    2424      MakeLibCfa.cc \
    25           MakeLibCfaNew.cpp \
    2625        MakeLibCfa.h
    2726
  • src/Parser/ExpressionNode.cc

    r5a40e4e rdd1cc02  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  7 09:18:56 2021
    13 // Update Count     : 1077
     12// Last Modified On : Thu Aug 20 14:01:46 2020
     13// Update Count     : 1076
    1414//
    1515
     
    514514        return expr;
    515515} // build_varref
    516 
    517516// TODO: get rid of this and OperKinds and reuse code from OperatorTable
    518517static const char * OperName[] = {                                              // must harmonize with OperKinds
  • src/Parser/ParseNode.h

    r5a40e4e rdd1cc02  
    437437WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
    438438Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
    439 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
    440439
    441440//##############################################################################
  • src/Parser/StatementNode.cc

    r5a40e4e rdd1cc02  
    374374} // build_directive
    375375
    376 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
    377         std::list< Expression * > expList;
    378         buildMoveList( exprs, expList );
    379         Statement * body = maybeMoveBuild<Statement>( stmt );
    380         return new MutexStmt( body, expList );
    381 } // build_mutex
    382 
    383376// Local Variables: //
    384377// tab-width: 4 //
  • src/Parser/parser.yy

    r5a40e4e rdd1cc02  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  8 09:14:44 2021
    13 // Update Count     : 5038
     12// Last Modified On : Tue Jul 20 22:03:04 2021
     13// Update Count     : 5031
    1414//
    1515
     
    185185                type = new ExpressionNode( new CastExpr( maybeMoveBuild<Expression>(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
    186186        } // if
    187 //      type = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__for_control_index_constraints__" ) ) ), type ) );
    188187        return new ForCtrl(
    189188                distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
     
    13471346mutex_statement:
    13481347        MUTEX '(' argument_expression_list_opt ')' statement
    1349                 { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
     1348                { SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; }
    13501349        ;
    13511350
  • src/SynTree/Mutator.h

    r5a40e4e rdd1cc02  
    5858        virtual Statement * mutate( DeclStmt * declStmt ) = 0;
    5959        virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
    60         virtual Statement * mutate( MutexStmt * mutexStmt ) = 0;
    6160
    6261        virtual Expression * mutate( ApplicationExpr * applicationExpr ) = 0;
  • src/SynTree/Statement.cc

    r5a40e4e rdd1cc02  
    565565}
    566566
    567 MutexStmt::MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs )
    568         : Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
    569 
    570 MutexStmt::MutexStmt( const MutexStmt & other ) : Statement( other ), stmt( maybeClone( other.stmt ) ) {
    571         cloneAll( other.mutexObjs, mutexObjs );
    572 }
    573 
    574 MutexStmt::~MutexStmt() {
    575         deleteAll( mutexObjs );
    576         delete stmt;
    577 }
    578 
    579 void MutexStmt::print( std::ostream & os, Indenter indent ) const {
    580         os << "Mutex Statement" << endl;
    581         os << indent << "... with Expressions: " << endl;
    582         for (auto * obj : mutexObjs) {
    583                 os << indent+1;
    584                 obj->print( os, indent+1);
    585                 os << endl;
    586         }
    587         os << indent << "... with Statement: " << endl << indent+1;
    588         stmt->print( os, indent+1 );
    589 }
    590 
    591567// Local Variables: //
    592568// tab-width: 4 //
  • src/SynTree/Statement.h

    r5a40e4e rdd1cc02  
    535535};
    536536
    537 class MutexStmt : public Statement {
    538   public:
    539         Statement * stmt;
    540         std::list<Expression *> mutexObjs; // list of mutex objects to acquire
    541 
    542         MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs );
    543         MutexStmt( const MutexStmt & other );
    544         virtual ~MutexStmt();
    545 
    546         virtual MutexStmt * clone() const override { return new MutexStmt( *this ); }
    547         virtual void accept( Visitor & v ) override { v.visit( this ); }
    548         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    549         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    550         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    551 };
    552 
    553537// Local Variables: //
    554538// tab-width: 4 //
  • src/SynTree/SynTree.h

    r5a40e4e rdd1cc02  
    6262class NullStmt;
    6363class ImplicitCtorDtorStmt;
    64 class MutexStmt;
    6564
    6665class Expression;
  • src/SynTree/Visitor.h

    r5a40e4e rdd1cc02  
    9292        virtual void visit( ImplicitCtorDtorStmt * node ) { visit( const_cast<const ImplicitCtorDtorStmt *>(node) ); }
    9393        virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
    94         virtual void visit( MutexStmt * node ) { visit( const_cast<const MutexStmt *>(node) ); }
    95         virtual void visit( const MutexStmt * mutexStmt ) = 0;
    9694
    9795        virtual void visit( ApplicationExpr * node ) { visit( const_cast<const ApplicationExpr *>(node) ); }
  • src/Tuples/Tuples.h

    r5a40e4e rdd1cc02  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Henry Xue
    12 // Last Modified On : Mon Aug 23 15:36:09 2021
    13 // Update Count     : 19
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Jun 18 09:36:00 2019
     13// Update Count     : 18
    1414//
    1515
     
    3939        /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
    4040        void expandMemberTuples( std::list< Declaration * > & translationUnit );
    41         void expandMemberTuples( ast::TranslationUnit & translationUnit );
    4241
    4342        /// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
  • src/Tuples/module.mk

    r5a40e4e rdd1cc02  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Henry Xue
    13 ## Last Modified On : Mon Aug 23 15:36:09 2021
    14 ## Update Count     : 2
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Mon Jun  1 17:54:33 2015
     14## Update Count     : 1
    1515###############################################################################
    1616
     
    2020        Tuples/TupleAssignment.cc \
    2121        Tuples/TupleExpansion.cc \
    22         Tuples/TupleExpansionNew.cpp \
    2322        Tuples/Tuples.cc \
    2423        Tuples/Tuples.h
  • src/main.cc

    r5a40e4e rdd1cc02  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Henry Xue
    12 // Last Modified On : Mon Aug 23 15:42:08 2021
    13 // Update Count     : 650
     12// Last Modified On : Tue Jul 20 04:27:35 2021
     13// Update Count     : 658
    1414//
    1515
     
    335335                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
    336336                PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    337 
     337                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
    338338                if ( libcfap ) {
    339339                        // generate the bodies of cfa library functions
     
    365365                        }
    366366                        auto transUnit = convert( move( translationUnit ) );
    367 
    368                         PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
    369                        
    370367                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    371368                        if ( exprp ) {
     
    379376                        translationUnit = convert( move( transUnit ) );
    380377                } else {
    381                         PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
    382 
    383378                        PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    384379                        if ( exprp ) {
  • tests/.expect/declarationSpecifier.arm64.txt

    r5a40e4e rdd1cc02  
    11321132char **_X13cfa_args_argvPPc_1;
    11331133char **_X13cfa_args_envpPPc_1;
    1134 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    11351134signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    11361135    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    11471146    }
    11481147
    1149     signed int _tmp_cp_ret6;
    1150     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    1151     {
    1152         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    1153     }
    1154 
    1155     {
    1156         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     1148    {
     1149        signed int _tmp_cp_ret6;
     1150        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    11571151    }
    11581152
  • tests/.expect/declarationSpecifier.x64.txt

    r5a40e4e rdd1cc02  
    11321132char **_X13cfa_args_argvPPc_1;
    11331133char **_X13cfa_args_envpPPc_1;
    1134 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    11351134signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    11361135    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    11471146    }
    11481147
    1149     signed int _tmp_cp_ret6;
    1150     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    1151     {
    1152         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    1153     }
    1154 
    1155     {
    1156         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     1148    {
     1149        signed int _tmp_cp_ret6;
     1150        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    11571151    }
    11581152
  • tests/.expect/declarationSpecifier.x86.txt

    r5a40e4e rdd1cc02  
    11321132char **_X13cfa_args_argvPPc_1;
    11331133char **_X13cfa_args_envpPPc_1;
    1134 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    11351134signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    11361135    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    11471146    }
    11481147
    1149     signed int _tmp_cp_ret6;
    1150     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    1151     {
    1152         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    1153     }
    1154 
    1155     {
    1156         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     1148    {
     1149        signed int _tmp_cp_ret6;
     1150        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    11571151    }
    11581152
  • tests/.expect/gccExtensions.arm64.txt

    r5a40e4e rdd1cc02  
    324324char **_X13cfa_args_argvPPc_1;
    325325char **_X13cfa_args_envpPPc_1;
    326 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    327326signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    328327    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    339338    }
    340339
    341     signed int _tmp_cp_ret6;
    342     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    343     {
    344         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    345     }
    346 
    347     {
    348         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     340    {
     341        signed int _tmp_cp_ret6;
     342        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    349343    }
    350344
  • tests/.expect/gccExtensions.x64.txt

    r5a40e4e rdd1cc02  
    324324char **_X13cfa_args_argvPPc_1;
    325325char **_X13cfa_args_envpPPc_1;
    326 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    327326signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    328327    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    339338    }
    340339
    341     signed int _tmp_cp_ret6;
    342     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    343     {
    344         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    345     }
    346 
    347     {
    348         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     340    {
     341        signed int _tmp_cp_ret6;
     342        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    349343    }
    350344
  • tests/.expect/gccExtensions.x86.txt

    r5a40e4e rdd1cc02  
    302302char **_X13cfa_args_argvPPc_1;
    303303char **_X13cfa_args_envpPPc_1;
    304 signed int _X17cfa_main_returnedi_1 = ((signed int )0);
    305304signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    306305    __attribute__ ((unused)) signed int _X12_retval_maini_1;
     
    317316    }
    318317
    319     signed int _tmp_cp_ret6;
    320     signed int _X3reti_2 = (((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6);
    321     {
    322         ((void)(_X17cfa_main_returnedi_1=((signed int )1)));
    323     }
    324 
    325     {
    326         ((void)(_X12_retval_maini_1=_X3reti_2) /* ?{} */);
     318    {
     319        signed int _tmp_cp_ret6;
     320        ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret6=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret6)) /* ?{} */);
    327321    }
    328322
  • tests/Makefile.am

    r5a40e4e rdd1cc02  
    7575        pybin/tools.py \
    7676        long_tests.hfa \
    77         .in/parseconfig-all.txt \
    78         .in/parseconfig-errors.txt \
    79         .in/parseconfig-missing.txt \
    8077        io/.in/io.data \
    8178        io/.in/many_read.data \
  • tests/bitmanip3.cfa

    r5a40e4e rdd1cc02  
    1010// Created On       : Tue Apr  7 21:22:59 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  8 23:12:19 2021
    13 // Update Count     : 76
     12// Last Modified On : Mon Aug 24 09:53:26 2020
     13// Update Count     : 66
    1414//
    1515
     
    133133        sout | nl | "floor2" | nl | nl;
    134134
    135         sout | "signed char";
     135        printf( "signed char\n" );
    136136        for ( sc = 1; sc != 0; sc <<= 1 ) {
    137137                scr1 = floor2( sc, sc ); scr2 = floor2( sc + 2hh, sc ); scr3 = floor2( -sc - 2hh, sc );
    138 //              printf( "floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );
    139                 sout | "floor2(" | sc | "," | sc | ") = " | scr1 | ", floor2(" | sc + 2hh | "," | sc | ") = " | scr2 | ", floor2(" | -sc - 2hh | "," | sc | ") = " | scr3;
    140         } // for
    141         sout | nl;
    142 
    143         sout | "unsigned char";
     138                printf( "floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );
     139        } // for
     140        printf( "\n" );
     141
     142        printf( "unsigned char\n" );
    144143        for ( uc = 1; uc != 0; uc <<= 1 ) {
    145144                ucr1 = floor2( uc, uc ); ucr2 = floor2( uc + 2hh, uc ); ucr3 = floor2( -uc - 2hh, uc );
    146 //              printf( "floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );
    147                 sout | "floor2(" | uc | "," | uc | ") = " | ucr1 | ", floor2(" | uc + 2uhh | "," | uc | ") = " | ucr2 | ", floor2(" | -uc - 2uhh | "," | uc | ") = " | ucr3;
    148         } // for
    149         sout | nl;
    150 
    151         sout | "short int";
     145                printf( "floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );
     146        } // for
     147        printf( "\n" );
     148
     149        printf( "short int\n" );
    152150        for ( si = 1; si != 0; si <<= 1 ) {
    153151                sir1 = floor2( si, si ); sir2 = floor2( si + 2hh, si ); sir3 = floor2( -si - 2hh, si );
    154 //              printf( "floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );
    155                 sout | "floor2(" | si | "," | si | ") = " | sir1 | ", floor2(" | si + 2h | "," | si | ") = " | sir2 | ", floor2(" | -si - 2h | "," | si | ") = " | sir3;
    156         } // for
    157         sout | nl;
    158 
    159         sout | "unsigned short int";
     152                printf( "floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );
     153        } // for
     154        printf( "\n" );
     155
     156        printf( "unsigned short int\n" );
    160157        for ( usi = 1; usi != 0; usi <<= 1 ) {
    161158                usir1 = floor2( usi, usi ); usir2 = floor2( usi + 2hh, usi ); usir3 = floor2( -usi - 2hh, usi );
    162 //              printf( "floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );
    163                 sout | "floor2(" | usi | "," | usi | ") = " | usir1 | ", floor2(" | usi + 2uh | "," | usi | ") = " | usir2 | ", floor2(" | -usi - 2uh | "," | usi | ") = " | usir3;
    164         } // for
    165         sout | nl;
    166 
    167         sout | "int";
     159                printf( "floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );
     160        } // for
     161        printf( "\n" );
     162
     163        printf( "int\n" );
    168164        for ( i = 1; i != 0; i <<= 1 ) {
    169165                ir1 = floor2( i, i ); ir2 = floor2( i + 2hh, i ); ir3 = floor2( -i - 2hh, i );
    170 //              printf( "floor2(%d, %d) = %d, floor2(%d, %d) = %d, floor2(%d, %d) = %d\n", i, i, ir1, i + 2, i, ir2, -i - 2, i, ir3 );
    171                 sout | "floor2(" | i | "," | i | ") = " | ir1 | ", floor2(" | i + 2 | "," | i | ") = " | ir2 | ", floor2(" | -i - 2 | "," | i | ") = " | ir3;
    172         } // for
    173         sout | nl;
    174 
    175         sout | "unsigned int";
     166                printf( "floor2(%d, %d) = %d, floor2(%d, %d) = %d, floor2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 );
     167        } // for
     168        printf( "\n" );
     169
     170        printf( "unsigned int\n" );
    176171        for ( ui = 1; ui != 0; ui <<= 1 ) {
    177172                uir1 = floor2( ui, ui ); uir2 = floor2( ui + 2hh, ui ); uir3 = floor2( -ui - 2hh, ui );
    178 //              printf( "floor2(%u, %u) = %u, floor2(%u, %u) = %u, floor2(%u, %u) = %u\n", ui, ui, uir1, ui + 2, ui, uir2, -ui - 2, ui, uir3 );
    179                 sout | "floor2(" | ui | "," | ui | ") = " | uir1 | ", floor2(" | ui + 2 | "," | ui | ") = " | uir2 | ", floor2(" | -ui - 2 | "," | ui | ") = " | uir3;
    180         } // for
    181         sout | nl;
    182 
    183         sout | "long int";
     173                printf( "floor2(%u, %u) = %u, floor2(%u, %u) = %u, floor2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 );
     174        } // for
     175        printf( "\n" );
     176
     177        printf( "long int\n" );
    184178        for ( li = 1; li != 0; li <<= 1 ) {
    185179                lir1 = floor2( li, li ); lir2 = floor2( li + 2hh, li ); lir3 = floor2( -li - 2hh, li );
    186 //              printf( "floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld\n", li, li, lir1, li + 2l, li, lir2, -li - 2l, li, lir3 );
    187                 sout | "floor2(" | li | "," | li | ") = " | lir1 | ", floor2(" | li + 2l | "," | li | ") = " | lir2 | ", floor2(" | -li - 2l | "," | li | ") = " | lir3;
    188         } // for
    189         sout | nl;
    190 
    191         sout | "unsigned long int";
     180                printf( "floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 );
     181        } // for
     182        printf( "\n" );
     183
     184        printf( "unsigned long int\n" );
    192185        for ( uli = 1; uli != 0; uli <<= 1 ) {
    193186                ulir1 = floor2( uli, uli ); ulir2 = floor2( uli + 2hh, uli ); ulir3 = floor2( -uli - 2hh, uli );
    194 //              printf( "floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2l, uli, ulir2, -uli - 2l, uli, ulir3 );
    195                 sout | "floor2(" | uli | "," | uli | ") = " | ulir1 | ", floor2(" | uli + 2l | "," | uli | ") = " | ulir2 | ", floor2(" | -uli - 2l | "," | uli | ") = " | ulir3;
    196         } // for
    197         sout | nl;
    198 
    199         sout | "long long int";
     187                printf( "floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 );
     188        } // for
     189        printf( "\n" );
     190
     191        printf( "long long int\n" );
    200192        for ( lli = 1; lli != 0; lli <<= 1 ) {
    201193                llir1 = floor2( lli, lli ); llir2 = floor2( lli + 2hh, lli ); llir3 = floor2( -lli - 2hh, lli );
    202 //              printf( "floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2ll, lli, llir2, -lli - 2ll, lli, llir3 );
    203                 sout | "floor2(" | lli | "," | lli | ") = " | llir1 | ", floor2(" | lli + 2ll | "," | lli | ") = " | llir2 | ", floor2(" | -lli - 2ll | "," | lli | ") = " | llir3;
    204         } // for
    205         sout | nl;
    206 
    207         sout | "unsigned long long int";
     194                printf( "floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 );
     195        } // for
     196        printf( "\n" );
     197
     198        printf( "unsigned long long int\n" );
    208199        for ( ulli = 1; ulli != 0; ulli <<= 1 ) {
    209200                ullir1 = floor2( ulli, ulli ); ullir2 = floor2( ulli + 2hh, ulli ); ullir3 = floor2( -ulli - 2hh, ulli );
    210 //              printf( "floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );
    211                 sout | "floor2(" | ulli | "," | ulli | ") = " | ullir1 | ", floor2(" | ulli + 2ll | "," | ulli | ") = " | ullir2 | ", floor2(" | -ulli - 2ll | "," | ulli | ") = " | ullir3;
    212         } // for
    213         sout | nl;
     201                printf( "floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );
     202        } // for
     203        printf( "\n" );
    214204#endif // 0
    215205        //============================================================
     
    217207        sout | nl | "ceiling2" | nl | nl;
    218208
    219         sout | "signed char";
     209        printf( "signed char\n" );
    220210        for ( sc = 1; sc != 0; sc <<= 1 ) {
    221211                scr1 = ceiling2( sc, sc ); scr2 = ceiling2( sc + 2hh, sc ); scr3 = ceiling2( -sc - 2hh, sc );
    222 //              printf( "ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );
    223                 sout | "ceiling2(" | sc | "," | sc | ") = " | scr1 | ", ceiling2(" | sc + 2hh | "," | sc | ") = " | scr2 | ", ceiling2(" | -sc - 2hh | "," | sc | ") = " | scr3;
    224         } // for
    225         sout | nl;
    226 
    227         sout | "unsigned char";
     212                printf( "ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );
     213        } // for
     214        printf( "\n" );
     215
     216        printf( "unsigned char\n" );
    228217        for ( uc = 1; uc != 0; uc <<= 1 ) {
    229218                ucr1 = ceiling2( uc, uc ); ucr2 = ceiling2( uc + 2hh, uc ); ucr3 = ceiling2( -uc - 2hh, uc );
    230 //              printf( "ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );
    231                 sout | "ceiling2(" | uc | "," | uc | ") = " | ucr1 | ", ceiling2(" | uc + 2hh | "," | uc | ") = " | ucr2 | ", ceiling2(" | -uc - 2hh | "," | uc | ") = " | ucr3;
    232         } // for
    233         sout | nl;
    234 
    235         sout | "short int";
     219                printf( "ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );
     220        } // for
     221        printf( "\n" );
     222
     223        printf( "short int\n" );
    236224        for ( si = 1; si != 0; si <<= 1 ) {
    237225                sir1 = ceiling2( si, si ); sir2 = ceiling2( si + 2hh, si ); sir3 = ceiling2( -si - 2hh, si );
    238 //              printf( "ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );
    239                 sout | "ceiling2(" | si | "," | si | ") = " | sir1 | ", ceiling2(" | si + 2h | "," | si | ") = " | sir2 | ", ceiling2(" | -si - 2h | "," | si | ") = " | sir3;
    240         } // for
    241         sout | nl;
    242 
    243         sout | "unsigned short int";
     226                printf( "ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );
     227        } // for
     228        printf( "\n" );
     229
     230        printf( "unsigned short int\n" );
    244231        for ( usi = 1; usi != 0; usi <<= 1 ) {
    245232                usir1 = ceiling2( usi, usi ); usir2 = ceiling2( usi + 2hh, usi ); usir3 = ceiling2( -usi - 2hh, usi );
    246 //              printf( "ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );
    247                 sout | "ceiling2(" | usi | "," | usi | ") = " | usir1 | ", ceiling2(" | usi + 2h | "," | usi | ") = " | usir2 | ", ceiling2(" | -usi - 2h | "," | usi | ") = " | usir3;
    248         } // for
    249         sout | nl;
    250 
    251         sout | "int";
     233                printf( "ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );
     234        } // for
     235        printf( "\n" );
     236
     237        printf( "int\n" );
    252238        for ( i = 1; i != 0; i <<= 1 ) {
    253239                ir1 = ceiling2( i, i ); ir2 = ceiling2( i + 2hh, i ); ir3 = ceiling2( -i - 2hh, i );
    254 //              printf( "ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d\n", i, i, ir1, i + 2, i, ir2, -i - 2, i, ir3 );
    255                 sout | "ceiling2(" | i | "," | i | ") = " | ir1 | ", ceiling2(" | i + 2 | "," | i | ") = " | ir2 | ", ceiling2(" | -i - 2 | "," | i | ") = " | ir3;
    256         } // for
    257         sout | nl;
    258 
    259         sout | "unsigned int";
     240                printf( "ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 );
     241        } // for
     242        printf( "\n" );
     243
     244        printf( "unsigned int\n" );
    260245        for ( ui = 1; ui != 0; ui <<= 1 ) {
    261246                uir1 = ceiling2( ui, ui ); uir2 = ceiling2( ui + 2hh, ui ); uir3 = ceiling2( -ui - 2hh, ui );
    262 //              printf( "ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u\n", ui, ui, uir1, ui + 2, ui, uir2, -ui - 2, ui, uir3 );
    263                 sout | "ceiling2(" | ui | "," | ui | ") = " | uir1 | ", ceiling2(" | ui + 2 | "," | ui | ") = " | uir2 | ", ceiling2(" | -ui - 2 | "," | ui | ") = " | uir3;
    264         } // for
    265         sout | nl;
    266 
    267         sout | "long int";
     247                printf( "ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 );
     248        } // for
     249        printf( "\n" );
     250
     251        printf( "long int\n" );
    268252        for ( li = 1; li != 0; li <<= 1 ) {
    269253                lir1 = ceiling2( li, li ); lir2 = ceiling2( li + 2hh, li ); lir3 = ceiling2( -li - 2hh, li );
    270 //              printf( "ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld\n", li, li, lir1, li + 2l, li, lir2, -li - 2l, li, lir3 );
    271                 sout | "ceiling2(" | li | "," | li | ") = " | lir1 | ", ceiling2(" | li + 2l | "," | li | ") = " | lir2 | ", ceiling2(" | -li - 2l | "," | li | ") = " | lir3;
    272         } // for
    273         sout | nl;
    274 
    275         sout | "unsigned long int";
     254                printf( "ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 );
     255        } // for
     256        printf( "\n" );
     257
     258        printf( "unsigned long int\n" );
    276259        for ( uli = 1; uli != 0; uli <<= 1 ) {
    277260                ulir1 = ceiling2( uli, uli ); ulir2 = ceiling2( uli + 2hh, uli ); ulir3 = ceiling2( -uli - 2hh, uli );
    278 //              printf( "ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2, uli, ulir2, -uli - 2, uli, ulir3 );
    279                 sout | "ceiling2(" | uli | "," | uli | ") = " | ulir1 | ", ceiling2(" | uli + 2l | "," | uli | ") = " | ulir2 | ", ceiling2(" | -uli - 2l | "," | uli | ") = " | ulir3;
    280         } // for
    281         sout | nl;
    282 
    283         sout | "long long int";
     261                printf( "ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 );
     262        } // for
     263        printf( "\n" );
     264
     265        printf( "long long int\n" );
    284266        for ( lli = 1; lli != 0; lli <<= 1 ) {
    285267                llir1 = ceiling2( lli, lli ); llir2 = ceiling2( lli + 2hh, lli ); llir3 = ceiling2( -lli - 2hh, lli );
    286 //              printf( "ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2ll, lli, llir2, -lli - 2ll, lli, llir3 );
    287                 sout | "ceiling2(" | lli | "," | lli | ") = " | llir1 | ", ceiling2(" | lli + 2ll | "," | lli | ") = " | llir2 | ", ceiling2(" | -lli - 2ll | "," | lli | ") = " | llir3;
    288         } // for
    289         sout | nl;
    290 
    291         sout | "unsigned long long int";
     268                printf( "ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 );
     269        } // for
     270        printf( "\n" );
     271
     272        printf( "unsigned long long int\n" );
    292273        for ( ulli = 1; ulli != 0; ulli <<= 1 ) {
    293274                ullir1 = ceiling2( ulli, ulli ); ullir2 = ceiling2( ulli + 2hh, ulli ); ullir3 = ceiling2( -ulli - 2hh, ulli );
    294 //              printf( "ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );
    295                 sout | "ceiling2(" | ulli | "," | ulli | ") = " | ullir1 | ", ceiling2(" | ulli + 2ll | "," | ulli | ") = " | ullir2 | ", ceiling2(" | -ulli - 2ll | "," | ulli | ") = " | ullir3;
    296         } // for
    297         sout | nl;
     275                printf( "ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );
     276        } // for
     277        printf( "\n" );
    298278#endif // 0
    299279} // main
  • tests/exceptions/.expect/type-check.txt

    r5a40e4e rdd1cc02  
    1 exceptions/type-check.cfa:6:1 error: catch must have pointer to an exception type
    2 exceptions/type-check.cfa:7:1 error: catch must have pointer to an exception type
    3 exceptions/type-check.cfa:8:1 error: catchResume must have pointer to an exception type
    4 exceptions/type-check.cfa:9:1 error: catchResume must have pointer to an exception type
     1exceptions/type-check.cfa:8:1 error: catch must have pointer to an exception type
     2exceptions/type-check.cfa:9:1 error: catch must have pointer to an exception type
     3exceptions/type-check.cfa:10:1 error: catchResume must have pointer to an exception type
     4exceptions/type-check.cfa:11:1 error: catchResume must have pointer to an exception type
  • tests/exceptions/cancel/coroutine.cfa

    r5a40e4e rdd1cc02  
    22
    33#include <coroutine.hfa>
     4#include <exception.hfa>
    45
    5 exception internal_error {};
    6 vtable(internal_error) internal_vt;
     6EHM_EXCEPTION(internal_error)();
     7EHM_VIRTUAL_TABLE(internal_error, internal_vt);
    78
    89coroutine WillCancel {};
  • tests/exceptions/cancel/thread.cfa

    r5a40e4e rdd1cc02  
    22
    33#include <thread.hfa>
     4#include <exception.hfa>
    45
    5 exception internal_error {};
    6 vtable(internal_error) internal_vt;
     6EHM_EXCEPTION(internal_error)();
     7EHM_VIRTUAL_TABLE(internal_error, internal_vt);
    78
    89thread WillCancel {};
  • tests/exceptions/conditional.cfa

    r5a40e4e rdd1cc02  
    44// up the non-trivial exception is reasonable to do.
    55
    6 exception num_error {
     6#include <exception.hfa>
     7
     8EHM_EXCEPTION(num_error)(
    79        int num;
    8 };
     10);
    911
    10 vtable(num_error) num_error_vt;
     12EHM_VIRTUAL_TABLE(num_error, num_error_vt);
    1113
    1214void caught_num_error(int expect, num_error * actual) {
  • tests/exceptions/data-except.cfa

    r5a40e4e rdd1cc02  
    11// Test exceptions that add data but no functionality.
    22
    3 exception paired {
     3#include <exception.hfa>
     4
     5EHM_EXCEPTION(paired)(
    46        int first;
    57        int second;
    6 };
     8);
    79
    8 vtable(paired) paired_vt;
     10EHM_VIRTUAL_TABLE(paired, paired_vt);
    911
    1012const char * virtual_msg(paired * this) {
  • tests/exceptions/defaults.cfa

    r5a40e4e rdd1cc02  
    44#include <exception.hfa>
    55
    6 exception log_message {
     6EHM_EXCEPTION(log_message)(
    77        char * msg;
    8 };
     8);
    99
    1010_EHM_DEFINE_COPY(log_message, )
     
    3232
    3333// I don't have a good use case for doing the same with termination.
    34 exception jump {};
     34EHM_EXCEPTION(jump)();
    3535void defaultTerminationHandler(jump &) {
    3636        printf("jump default handler.\n");
    3737}
    3838
    39 vtable(jump) jump_vt;
     39EHM_VIRTUAL_TABLE(jump, jump_vt);
    4040
    4141void jump_test(void) {
     
    4848}
    4949
    50 exception first {};
    51 vtable(first) first_vt;
     50EHM_EXCEPTION(first)();
     51EHM_VIRTUAL_TABLE(first, first_vt);
    5252
    53 exception unhandled_exception {};
    54 vtable(unhandled_exception) unhandled_vt;
     53EHM_EXCEPTION(unhandled_exception)();
     54EHM_VIRTUAL_TABLE(unhandled_exception, unhandled_vt);
    5555
    5656void unhandled_test(void) {
     
    6969}
    7070
    71 exception second {};
    72 vtable(second) second_vt;
     71EHM_EXCEPTION(second)();
     72EHM_VIRTUAL_TABLE(second, second_vt);
    7373
    7474void cross_test(void) {
  • tests/exceptions/finally.cfa

    r5a40e4e rdd1cc02  
    11// Finally Clause Tests
    22
     3#include <exception.hfa>
    34#include "except-io.hfa"
    45
    5 exception myth {};
     6EHM_EXCEPTION(myth)();
    67
    7 vtable(myth) myth_vt;
     8EHM_VIRTUAL_TABLE(myth, myth_vt);
    89
    910int main(int argc, char * argv[]) {
  • tests/exceptions/interact.cfa

    r5a40e4e rdd1cc02  
    11// Testing Interactions Between Termination and Resumption
    22
     3#include <exception.hfa>
    34#include "except-io.hfa"
    45
    5 exception star {};
    6 exception moon {};
     6EHM_EXCEPTION(star)();
     7EHM_EXCEPTION(moon)();
    78
    8 vtable(star) star_vt;
    9 vtable(moon) moon_vt;
     9EHM_VIRTUAL_TABLE(star, star_vt);
     10EHM_VIRTUAL_TABLE(moon, moon_vt);
    1011
    1112int main(int argc, char * argv[]) {
  • tests/exceptions/polymorphic.cfa

    r5a40e4e rdd1cc02  
    11// Testing polymophic exception types.
    22
    3 forall(T &) exception proxy {};
     3#include <exception.hfa>
    44
    5 vtable(proxy(int)) proxy_int;
    6 vtable(proxy(char)) proxy_char;
     5EHM_FORALL_EXCEPTION(proxy, (T&), (T))();
     6
     7EHM_FORALL_VIRTUAL_TABLE(proxy, (int), proxy_int);
     8EHM_FORALL_VIRTUAL_TABLE(proxy, (char), proxy_char);
    79
    810void proxy_test(void) {
     
    3133}
    3234
    33 forall(T) exception cell {
     35EHM_FORALL_EXCEPTION(cell, (T), (T))(
    3436        T data;
    35 };
     37);
    3638
    37 vtable(cell(int)) int_cell;
    38 vtable(cell(char)) char_cell;
    39 vtable(cell(bool)) bool_cell;
     39EHM_FORALL_VIRTUAL_TABLE(cell, (int), int_cell);
     40EHM_FORALL_VIRTUAL_TABLE(cell, (char), char_cell);
     41EHM_FORALL_VIRTUAL_TABLE(cell, (bool), bool_cell);
    4042
    4143void cell_test(void) {
  • tests/exceptions/resume.cfa

    r5a40e4e rdd1cc02  
    11// Resumption Exception Tests
    22
     3#include <exception.hfa>
    34#include "except-io.hfa"
    45
    5 exception yin {};
    6 exception yang {};
    7 exception zen {};
     6EHM_EXCEPTION(yin)();
     7EHM_EXCEPTION(yang)();
     8EHM_EXCEPTION(zen)();
    89
    9 vtable(yin) yin_vt;
    10 vtable(yang) yang_vt;
    11 vtable(zen) zen_vt;
     10EHM_VIRTUAL_TABLE(yin, yin_vt);
     11EHM_VIRTUAL_TABLE(yang, yang_vt);
     12EHM_VIRTUAL_TABLE(zen, zen_vt);
    1213
    1314void in_void(void);
  • tests/exceptions/terminate.cfa

    r5a40e4e rdd1cc02  
    11// Termination Exception Tests
    22
     3#include <exception.hfa>
    34#include "except-io.hfa"
    45
    5 exception yin {};
    6 exception yang {};
    7 exception zen {};
     6EHM_EXCEPTION(yin)();
     7EHM_EXCEPTION(yang)();
     8EHM_EXCEPTION(zen)();
    89
    9 vtable(yin) yin_vt;
    10 vtable(yang) yang_vt;
    11 vtable(zen) zen_vt;
     10EHM_VIRTUAL_TABLE(yin, yin_vt);
     11EHM_VIRTUAL_TABLE(yang, yang_vt);
     12EHM_VIRTUAL_TABLE(zen, zen_vt);
    1213
    1314void in_void(void);
  • tests/exceptions/trash.cfa

    r5a40e4e rdd1cc02  
    11// Make sure throw-catch during unwind does not trash internal data.
    22
    3 exception yin {};
    4 exception yang {};
     3#include <exception.hfa>
    54
    6 vtable(yin) yin_vt;
    7 vtable(yang) yang_vt;
     5EHM_EXCEPTION(yin)();
     6EHM_EXCEPTION(yang)();
     7
     8EHM_VIRTUAL_TABLE(yin, yin_vt);
     9EHM_VIRTUAL_TABLE(yang, yang_vt);
    810
    911int main(int argc, char * argv[]) {
  • tests/exceptions/type-check.cfa

    r5a40e4e rdd1cc02  
    11// Check that the exception type check works.
    22
    3 exception truth {};
     3#include <exception.hfa>
     4
     5EHM_EXCEPTION(truth)();
    46
    57int main(int argc, char * argv[]) {
  • tests/mathX.cfa

    r5a40e4e rdd1cc02  
    1010// Created On       : Thu May 24 20:56:54 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  8 22:33:46 2021
    13 // Update Count     : 31
     12// Last Modified On : Sat Feb 20 18:26:38 2021
     13// Update Count     : 30
    1414//
    1515
     
    255255                sout | "ceiling(" | ulli | ", " | ulli | ") = " | ullir1 | ", ceiling(" | ulli + 2ull | ", " | ulli | ") = " | ullir2 | ", ceiling(" | -ulli - 2ull | ", " | ulli | ") = " | ullir3;
    256256        } // for
    257         sout | nl;
     257        printf( "\n" );
    258258#endif // 0
    259259} // main
Note: See TracChangeset for help on using the changeset viewer.