Changeset 1a6a6f2


Ignore:
Timestamp:
Aug 19, 2021, 4:04:43 PM (3 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, pthread-emulation, qualifiedEnum
Children:
d8f8d08
Parents:
ed4d7c1 (diff), 315e5e3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into 'andrew-mmath', collecting updates.

Files:
14 added
62 edited
13 moved

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/code/CondCatch.java

    red4d7c1 r1a6a6f2  
    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 
    228        private static long loop(int times) {
    239                long startTime = System.nanoTime();
    2410                for (int count = 0 ; count < times ; ++count) {
    2511                        try {
    26                                 cond_catch();
     12                                try {
     13                                        throw new EmptyException();
     14                                } catch (EmptyException exc) {
     15                                        if (!should_catch) {
     16                                                throw exc;
     17                                        }
     18                                }
    2719                        } catch (EmptyException exc) {
    2820                                // ...
     
    4638
    4739                long time = loop(times);
    48                 System.out.println("Run-Time (ns): " + time);
     40                System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
    4941        }
    5042}
  • doc/theses/andrew_beach_MMath/code/ThrowEmpty.java

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

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

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

    red4d7c1 r1a6a6f2  
    33class NotRaisedException extends Exception {}
    44
    5 public class CrossCatch {
     5public class TryCatch {
    66        private static boolean shouldThrow = false;
    77
     
    3131
    3232                long time = loop(times);
    33                 System.out.println("Run-Time (ns): " + time);
     33                System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
    3434        }
    3535}
  • doc/theses/andrew_beach_MMath/code/TryFinally.java

    red4d7c1 r1a6a6f2  
    1 // Cross a Try Statement with a Finally Clause
     1// Enter and Leave a Try Statement with a Finally Handler
    22
    3 public class CrossFinally {
     3public class TryFinally {
    44        private static boolean shouldThrow = false;
    55
     
    2727
    2828                long time = loop(times);
    29                 System.out.println("Run-Time (ns): " + time);
     29                System.out.format("Run-Time (s): %.1f%n", time / 1_000_000_000.);
    3030        }
    3131}
  • doc/theses/andrew_beach_MMath/code/cond-catch.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.h>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110bool should_catch = false;
    12 
    13 void throw_exception() {
    14         throw (empty_exception){&empty_vt};
    15 }
    16 
    17 void cond_catch() {
    18         try {
    19                 throw_exception();
    20         } catch (empty_exception * exc ; should_catch) {
    21                 asm volatile ("# catch block (conditional)");
    22         }
    23 }
    2411
    2512int main(int argc, char * argv[]) {
    2613        unsigned int times = 1;
    2714        if (1 < argc) {
    28                 times = strtol(argv[1], 0p, 10);
     15                times = strto(argv[1], 0p, 10);
    2916        }
    3017        if (2 < argc) {
    31                 should_catch = strtol(argv[2], 0p, 10);
     18                should_catch = (unsigned int)strto(argv[2], 0p, 2);
    3219        }
    3320
     
    3522        for (unsigned int count = 0 ; count < times ; ++count) {
    3623                try {
    37                         cond_catch();
     24                        throw (empty_exception){&empty_vt};
     25                } catch (empty_exception * exc ; should_catch) {
     26                        asm volatile ("# catch block (conditional)");
    3827                } catch (empty_exception * exc) {
    3928                        asm volatile ("# catch block (unconditional)");
     
    4130        }
    4231        Time end_time = timeHiRes();
    43         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     32        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4433}
  • doc/theses/andrew_beach_MMath/code/cond-catch.cpp

    red4d7c1 r1a6a6f2  
    44#include <exception>
    55#include <iostream>
     6#include <iomanip>
    67
     8using namespace std;
    79using namespace std::chrono;
    810
     
    1012
    1113bool should_catch = false;
    12 
    13 void throw_exception() {
    14         throw EmptyException();
    15 }
    16 
    17 void 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 }
    2714
    2815int main(int argc, char * argv[]) {
     
    3825    for (unsigned int count = 0 ; count < times ; ++count) {
    3926        try {
    40                         cond_catch();
     27                        try {
     28                                throw EmptyException();
     29                        } catch (EmptyException & exc) {
     30                                if (!should_catch) {
     31                                        throw;
     32                                }
     33                                asm volatile ("# catch block (conditional)");
     34                        }
    4135                } catch (EmptyException &) {
    4236                        asm volatile ("# catch block (unconditional)");
     
    4539        time_point<steady_clock> end_time = steady_clock::now();
    4640        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    47         std::cout << "Run-Time (ns): " << duration.count() << std::endl;
     41        cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
    4842}
  • doc/theses/andrew_beach_MMath/code/cond-catch.py

    red4d7c1 r1a6a6f2  
    1313
    1414
    15 def throw_exception():
    16     raise EmptyException()
    17 
    18 
    19 def cond_catch():
    20     try:
    21         throw_exception()
    22     except EmptyException as exc:
    23         if not should_catch:
    24             raise
    25 
    26 
    2715def main(argv):
    2816    times = 1
     
    3523    for count in range(times):
    3624        try:
    37             cond_catch();
     25            try:
     26                raise EmptyException()
     27            except EmptyException as exc:
     28                if not should_catch:
     29                    raise
    3830        except EmptyException:
    3931            pass
    4032
    4133    end_time = thread_time_ns()
    42     print('Run-Time (ns):', end_time - start_time)
     34    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    4335
    4436
  • doc/theses/andrew_beach_MMath/code/cond-fixup.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110bool should_catch = false;
    12 
    13 void throw_exception() {
    14         throwResume (empty_exception){&empty_vt};
    15 }
    16 
    17 void cond_catch() {
    18         try {
    19                 throw_exception();
    20         } catchResume (empty_exception * exc ; should_catch) {
    21                 asm volatile ("# fixup block (conditional)");
    22         }
    23 }
    2411
    2512int main(int argc, char * argv[]) {
    2613        unsigned int times = 1;
    2714        if (1 < argc) {
    28                 times = strtol(argv[1], 0p, 10);
     15                times = strto(argv[1], 0p, 10);
    2916        }
    3017        if (2 < argc) {
    31                 should_catch = strtol(argv[2], 0p, 10);
     18                should_catch = (unsigned int)strto(argv[2], 0p, 2);
    3219        }
    3320
     
    3522        for (unsigned int count = 0 ; count < times ; ++count) {
    3623                try {
    37                         cond_catch();
     24                        throwResume (empty_exception){&empty_vt};
     25                } catchResume (empty_exception * exc ; should_catch) {
     26                        asm volatile ("# fixup block (conditional)");
    3827                } catchResume (empty_exception * exc) {
    3928                        asm volatile ("# fixup block (unconditional)");
     
    4130        }
    4231        Time end_time = timeHiRes();
    43         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     32        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4433}
  • doc/theses/andrew_beach_MMath/code/resume-detor.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110struct WithDestructor {};
     
    1716void unwind_destructor(unsigned int frames) {
    1817        if (frames) {
    19 
    2018                WithDestructor object;
    2119                unwind_destructor(frames - 1);
     
    2927        unsigned int total_frames = 1;
    3028        if (1 < argc) {
    31                 times = strtol(argv[1], 0p, 10);
     29                times = strto(argv[1], 0p, 10);
    3230        }
    3331        if (2 < argc) {
    34                 total_frames = strtol(argv[2], 0p, 10);
     32                total_frames = strto(argv[2], 0p, 10);
    3533        }
    3634
     
    4442        }
    4543        Time end_time = timeHiRes();
    46         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     44        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4745}
  • doc/theses/andrew_beach_MMath/code/resume-empty.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    89
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    10 
    11 void unwind_empty(unsigned int frames) {
     10void nounwind_empty(unsigned int frames) {
    1211        if (frames) {
    13                 unwind_empty(frames - 1);
     12                nounwind_empty(frames - 1);
    1413        } else {
    1514                throwResume (empty_exception){&empty_vt};
     
    2120        unsigned int total_frames = 1;
    2221        if (1 < argc) {
    23                 times = strtol(argv[1], 0p, 10);
     22                times = strto(argv[1], 0p, 10);
    2423        }
    2524        if (2 < argc) {
    26                 total_frames = strtol(argv[2], 0p, 10);
     25                total_frames = strto(argv[2], 0p, 10);
    2726        }
    2827
    2928        Time start_time = timeHiRes();
    30         for (int count = 0 ; count < times ; ++count) {
     29        for (unsigned int count = 0 ; count < times ; ++count) {
    3130                try {
    32                         unwind_empty(total_frames);
     31                        nounwind_empty(total_frames);
    3332                } catchResume (empty_exception *) {
    3433                        asm volatile ("# fixup block");
     
    3635        }
    3736        Time end_time = timeHiRes();
    38         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     37        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    3938}
  • doc/theses/andrew_beach_MMath/code/resume-finally.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110void unwind_finally(unsigned int frames) {
     
    2524        unsigned int total_frames = 1;
    2625        if (1 < argc) {
    27                 times = strtol(argv[1], 0p, 10);
     26                times = strto(argv[1], 0p, 10);
    2827        }
    2928        if (2 < argc) {
    30                 total_frames = strtol(argv[2], 0p, 10);
     29                total_frames = strto(argv[2], 0p, 10);
    3130        }
    3231
     
    4039        }
    4140        Time end_time = timeHiRes();
    42         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     41        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4342}
  • doc/theses/andrew_beach_MMath/code/resume-other.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
     9exception not_raised_exception;
    810
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
    10 
    11 EHM_EXCEPTION(not_raised_exception)();
    12 
    13 void unwind_other(unsigned int frames) {
     11void nounwind_other(unsigned int frames) {
    1412        if (frames) {
    1513                try {
    16                         unwind_other(frames - 1);
     14                        nounwind_other(frames - 1);
    1715                } catchResume (not_raised_exception *) {
    1816                        asm volatile ("# fixup block (stack)");
     
    2725        unsigned int total_frames = 1;
    2826        if (1 < argc) {
    29                 times = strtol(argv[1], 0p, 10);
     27                times = strto(argv[1], 0p, 10);
    3028        }
    3129        if (2 < argc) {
    32                 total_frames = strtol(argv[2], 0p, 10);
     30                total_frames = strto(argv[2], 0p, 10);
    3331        }
    3432
     
    3634        for (int count = 0 ; count < times ; ++count) {
    3735                try {
    38                         unwind_other(total_frames);
     36                        nounwind_other(total_frames);
    3937                } catchResume (empty_exception *) {
    4038                        asm volatile ("# fixup block (base)");
     
    4240        }
    4341        Time end_time = timeHiRes();
    44         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     42        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4543}
  • doc/theses/andrew_beach_MMath/code/run.sh

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

    red4d7c1 r1a6a6f2  
    44# test.sh LANGUAGE TEST
    55#   Run the TEST in LANGUAGE.
     6# test.sh -a
     7#   Build all tests.
    68# test.sh -b SOURCE_FILE...
    79#   Build a test from SOURCE_FILE(s).
     10# test.sh -c
     11#   Clean all executables.
    812# test.sh -v LANGUAGE TEST FILE
    913#   View the result from TEST in LANGUAGE stored in FILE.
    1014
    11 readonly ITERATIONS=1000000 # 1 000 000, one million
     15readonly ITERS_1M=1000000 # 1 000 000, one million
     16readonly ITERS_10M=10000000 # 10 000 000, ten million
     17readonly ITERS_100M=100000000 # 100 000 000, hundred million
     18readonly ITERS_1000M=1000000000 # 1 000 000 000, billion
    1219readonly STACK_HEIGHT=100
    1320
     
    2431        *.cfa)
    2532                # Requires a symbolic link.
    26                 mmake "${1%.cfa}" "$1" ./cfa -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
     33                mmake "${1%.cfa}" "$1" cfa -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
    2734                ;;
    2835        *.cpp)
    29                 mmake "${1%.cpp}-cpp" "$1" g++ -DNDEBUG -O3 "$1" -o "${1%.cpp}-cpp"
     36                mmake "${1%.cpp}-cpp" "$1" g++-10 -DNDEBUG -O3 "$1" -o "${1%.cpp}-cpp"
    3037                ;;
    3138        *.java)
     
    3946)
    4047
    41 if [ "-b" = "$1" ]; then
     48if [ "-a" = "$1" ]; then                        # build all
     49        for file in *.cfa *.cpp *.java; do
     50                build $file
     51        done
     52        exit 0
     53elif [ "-b" = "$1" ]; then                      # build given
    4254        for file in "${@:2}"; do
    4355                build $file
    4456        done
    4557        exit 0
     58elif [ "-c" = "$1" ]; then                      # clean all
     59        rm -f `basename -s ".cfa" -a *.cfa`
     60        rm -f `basename -s ".cpp" -a *.cpp`
     61        rm -f *-cpp
     62        rm -f *.class
     63        exit 0
    4664elif [ "-v" = "$1" -a 4 = "$#" ]; then
    47     TEST_LANG="$2"
    48     TEST_CASE="$3"
    49     VIEW_FILE="$4"
     65        TEST_LANG="$2"
     66        TEST_CASE="$3"
     67        VIEW_FILE="$4"
    5068elif [ 2 -eq "$#" ]; then
    5169        TEST_LANG="$1"
     
    6381
    6482case "$TEST_CASE" in
    65 cond-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         ;;
    72 cond-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         ;;
    79 cross-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         ;;
    86 cross-finally)
    87         CFAT="./cross-finally $ITERATIONS"
    88         CFAR=unsupported
    89         CPP=unsupported
    90         JAVA="java CrossFinally $ITERATIONS"
    91         PYTHON="./cross_finally.py $ITERATIONS"
     83raise-empty)
     84        CFAT="./throw-empty $ITERS_1M $STACK_HEIGHT"
     85# see resume-fixup-empty-r      CFAR="./resume-empty $ITERS_1M $STACK_HEIGHT"
     86        CPP="./throw-empty-cpp $ITERS_1M $STACK_HEIGHT"
     87        JAVA="java ThrowEmpty $ITERS_1M $STACK_HEIGHT"
     88        PYTHON="./throw-empty.py $ITERS_1M $STACK_HEIGHT"
    9289        ;;
    9390raise-detor)
    94         CFAT="./throw-detor $ITERATIONS $STACK_HEIGHT"
    95         CFAR="./resume-detor $ITERATIONS $STACK_HEIGHT"
    96         CPP="./throw-detor-cpp $ITERATIONS $STACK_HEIGHT"
     91        CFAT="./throw-detor $ITERS_1M $STACK_HEIGHT"
     92# N/A   CFAR="./resume-detor $ITERS_1M $STACK_HEIGHT"
     93        CPP="./throw-detor-cpp $ITERS_1M $STACK_HEIGHT"
    9794        JAVA=unsupported
    9895        PYTHON=unsupported
    9996        ;;
    100 raise-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         ;;
    10797raise-finally)
    108         CFAT="./throw-finally $ITERATIONS $STACK_HEIGHT"
    109         CFAR="./resume-finally $ITERATIONS $STACK_HEIGHT"
     98        CFAT="./throw-finally $ITERS_1M $STACK_HEIGHT"
     99# N/A   CFAR="./resume-finally $ITERS_1M $STACK_HEIGHT"
    110100        CPP=unsupported
    111         JAVA="java ThrowFinally $ITERATIONS $STACK_HEIGHT"
    112         PYTHON="./throw_finally.py $ITERATIONS $STACK_HEIGHT"
     101        JAVA="java ThrowFinally $ITERS_1M $STACK_HEIGHT"
     102        PYTHON="./throw-finally.py $ITERS_1M $STACK_HEIGHT"
    113103        ;;
    114104raise-other)
    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"
     105        CFAT="./throw-other $ITERS_1M $STACK_HEIGHT"
     106# N/A   CFAR="./resume-other $ITERS_1M $STACK_HEIGHT"
     107        CPP="./throw-other-cpp $ITERS_1M $STACK_HEIGHT"
     108        JAVA="java ThrowOther $ITERS_1M $STACK_HEIGHT"
     109        PYTHON="./throw-other.py $ITERS_1M $STACK_HEIGHT"
     110        ;;
     111try-catch)
     112        CFAT="./try-catch $ITERS_1000M"
     113        CFAR="./try-resume $ITERS_1000M"
     114        CPP="./try-catch-cpp $ITERS_1000M"
     115        JAVA="java TryCatch $ITERS_1000M"
     116        PYTHON="./try-catch.py $ITERS_1000M"
     117        ;;
     118try-finally)
     119        CFAT="./try-finally $ITERS_1000M"
     120        CFAR=unsupported
     121        CPP=unsupported
     122        JAVA="java TryFinally $ITERS_1000M"
     123        PYTHON="./try-finally.py $ITERS_1000M"
     124        ;;
     125cond-match-all)
     126        CFAT="./cond-catch $ITERS_10M 1"
     127        CFAR="./cond-fixup $ITERS_10M 1"
     128        CPP="./cond-catch-cpp $ITERS_10M 1"
     129        JAVA="java CondCatch $ITERS_10M 1"
     130        PYTHON="./cond-catch.py $ITERS_10M 1"
     131        ;;
     132cond-match-none)
     133        CFAT="./cond-catch $ITERS_10M 0"
     134        CFAR="./cond-fixup $ITERS_10M 0"
     135        CPP="./cond-catch-cpp $ITERS_10M 0"
     136        JAVA="java CondCatch $ITERS_10M 0"
     137        PYTHON="./cond-catch.py $ITERS_10M 0"
     138        ;;
     139raise-fixup-empty)
     140        CFAT="./resume-fixup-empty-f $ITERS_10M $STACK_HEIGHT"
     141        CFAR="./resume-fixup-empty-r $ITERS_10M $STACK_HEIGHT"
     142        CPP="./resume-fixup-empty-cpp $ITERS_10M $STACK_HEIGHT"
     143        JAVA="java ResumeFixupEmpty $ITERS_10M $STACK_HEIGHT"
     144        PYTHON="./resume-fixup-empty.py $ITERS_10M $STACK_HEIGHT"
     145        ;;
     146raise-fixup-other)
     147        CFAT="./resume-fixup-other-f $ITERS_10M $STACK_HEIGHT"
     148        CFAR="./resume-fixup-other-r $ITERS_10M $STACK_HEIGHT"
     149        CPP="./resume-fixup-other-cpp $ITERS_10M $STACK_HEIGHT"
     150        JAVA="java ResumeFixupOther $ITERS_10M $STACK_HEIGHT"
     151        PYTHON="./resume-fixup-other.py $ITERS_10M $STACK_HEIGHT"
    120152        ;;
    121153*)
     
    126158
    127159case "$TEST_LANG" in
    128 cfa-t) CALL="$CFAT";;
    129 cfa-r) CALL="$CFAR";;
    130 cpp) CALL="$CPP";;
    131 java) CALL="$JAVA";;
    132 python) CALL="$PYTHON";;
    133 *)
    134         echo "No such language: $TEST_LANG" >&2
    135         exit 2
     160        cfa-t) CALL="$CFAT";;
     161        cfa-r) CALL="$CFAR";;
     162        cpp) CALL="$CPP";;
     163        java) CALL="$JAVA";;
     164        python) CALL="$PYTHON";;
     165        *)
     166                echo "No such language: $TEST_LANG" >&2
     167                exit 2
    136168        ;;
    137169esac
     
    140172
    141173if [ -n "$VIEW_FILE" ]; then
    142     grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
    143     exit
     174        grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
     175        exit
    144176fi
    145177
  • doc/theses/andrew_beach_MMath/code/throw-detor.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110struct WithDestructor {};
     
    2827        unsigned int total_frames = 1;
    2928        if (1 < argc) {
    30                 times = strtol(argv[1], 0p, 10);
     29                times = strto(argv[1], 0p, 10);
    3130        }
    3231        if (2 < argc) {
    33                 total_frames = strtol(argv[2], 0p, 10);
     32                total_frames = strto(argv[2], 0p, 10);
    3433        }
    3534
     
    4342        }
    4443        Time end_time = timeHiRes();
    45         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     44        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4645}
  • doc/theses/andrew_beach_MMath/code/throw-detor.cpp

    red4d7c1 r1a6a6f2  
    44#include <exception>
    55#include <iostream>
     6#include <iomanip>
    67
     8using namespace std;
    79using namespace std::chrono;
    810
     
    4446        time_point<steady_clock> end_time = steady_clock::now();
    4547        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    46         std::cout << "Run-Time (ns): " << duration.count() << std::endl;
     48        cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
    4749}
  • doc/theses/andrew_beach_MMath/code/throw-empty.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    109
    1110void unwind_empty(unsigned int frames) {
     
    2120        unsigned int total_frames = 1;
    2221        if (1 < argc) {
    23                 times = strtol(argv[1], 0p, 10);
     22                times = strto(argv[1], 0p, 10);
    2423        }
    2524        if (2 < argc) {
    26                 total_frames = strtol(argv[2], 0p, 10);
     25                total_frames = strto(argv[2], 0p, 10);
    2726        }
    2827
     
    3635        }
    3736        Time end_time = timeHiRes();
    38         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     37        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    3938}
  • doc/theses/andrew_beach_MMath/code/throw-empty.cpp

    red4d7c1 r1a6a6f2  
    44#include <exception>
    55#include <iostream>
     6#include <iomanip>
    67
     8using namespace std;
    79using namespace std::chrono;
    810
     
    3739        time_point<steady_clock> end_time = steady_clock::now();
    3840        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    39         std::cout << "Run-Time (ns): " << duration.count() << std::endl;
     41        cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
    4042}
  • doc/theses/andrew_beach_MMath/code/throw-empty.py

    red4d7c1 r1a6a6f2  
    3333
    3434    end_time = thread_time_ns()
    35     print('Run-Time (ns):', end_time - start_time)
     35    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    3636
    3737
  • doc/theses/andrew_beach_MMath/code/throw-finally.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
    89
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     10unsigned int frames;                                                                    // use global because of gcc thunk problem
    1011
    11 void unwind_finally(unsigned int frames) {
     12void unwind_finally(unsigned int dummy) {
    1213        if (frames) {
     14                frames -= 1;
    1315                try {
    14                         unwind_finally(frames - 1);
     16                        unwind_finally(42);
    1517                } finally {
    1618                        asm volatile ("# finally block");
    1719                }
    1820        } else {
     21                dummy = 42;
    1922                throw (empty_exception){&empty_vt};
    2023        }
     
    2528        unsigned int total_frames = 1;
    2629        if (1 < argc) {
    27                 times = strtol(argv[1], 0p, 10);
     30                times = strto(argv[1], 0p, 10);
    2831        }
    2932        if (2 < argc) {
    30                 total_frames = strtol(argv[2], 0p, 10);
     33                total_frames = strto(argv[2], 0p, 10);
    3134        }
     35        frames = total_frames;
    3236
    3337        Time start_time = timeHiRes();
    3438        for (int count = 0 ; count < times ; ++count) {
    3539                try {
    36                         unwind_finally(total_frames);
     40                        unwind_finally(42);
    3741                } catch (empty_exception *) {
    3842                        asm volatile ("# catch block");
     
    4044        }
    4145        Time end_time = timeHiRes();
    42         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     46        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4347}
  • doc/theses/andrew_beach_MMath/code/throw-finally.py

    red4d7c1 r1a6a6f2  
    3636
    3737    end_time = thread_time_ns()
    38     print('Run-Time (ns):', end_time - start_time)
     38    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    3939
    4040
  • doc/theses/andrew_beach_MMath/code/throw-other.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(empty_exception)();
     7exception empty_exception;
     8vtable(empty_exception) empty_vt;
     9exception not_raised_exception;
    810
    9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt);
     11unsigned int frames;                                                                    // use global because of gcc thunk problem
    1012
    11 EHM_EXCEPTION(not_raised_exception)();
    12 
    13 void unwind_other(unsigned int frames) {
     13void unwind_other(unsigned int dummy) {
    1414        if (frames) {
     15                frames -= 1;
    1516                try {
    16                         unwind_other(frames - 1);
     17                        unwind_other(42);
    1718                } catch (not_raised_exception *) {
    1819                        asm volatile ("# catch block (stack)");
    1920                }
    2021        } else {
     22                dummy = 42;
    2123                throw (empty_exception){&empty_vt};
    2224        }
     
    2729        unsigned int total_frames = 1;
    2830        if (1 < argc) {
    29                 times = strtol(argv[1], 0p, 10);
     31                times = strto(argv[1], 0p, 10);
    3032        }
    3133        if (2 < argc) {
    32                 total_frames = strtol(argv[2], 0p, 10);
     34                total_frames = strto(argv[2], 0p, 10);
    3335        }
     36        frames = total_frames;
    3437
    3538        Time start_time = timeHiRes();
    3639        for (int count = 0 ; count < times ; ++count) {
    3740                try {
    38                         unwind_other(total_frames);
     41                        unwind_other(42);
    3942                } catch (empty_exception *) {
    4043                        asm volatile ("# catch block (base)");
     
    4245        }
    4346        Time end_time = timeHiRes();
    44         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     47        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    4548}
  • doc/theses/andrew_beach_MMath/code/throw-other.cpp

    red4d7c1 r1a6a6f2  
    44#include <exception>
    55#include <iostream>
     6#include <iomanip>
    67
     8using namespace std;
    79using namespace std::chrono;
    810
     
    4345        time_point<steady_clock> end_time = steady_clock::now();
    4446        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    45         std::cout << "Run-Time (ns): " << duration.count() << std::endl;
     47        cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
    4648}
  • doc/theses/andrew_beach_MMath/code/throw-other.py

    red4d7c1 r1a6a6f2  
    4040
    4141    end_time = thread_time_ns()
    42     print('Run-Time (ns):', end_time - start_time)
     42    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    4343
    4444
  • doc/theses/andrew_beach_MMath/code/throw-with.py

    red4d7c1 r1a6a6f2  
    4343
    4444    end_time = thread_time_ns()
    45     print('Run-Time (ns):', end_time - start_time)
     45    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    4646
    4747
  • doc/theses/andrew_beach_MMath/code/try-catch.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(not_raised_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(not_raised_exception, not_vt);
     7exception not_raised_exception;
     8vtable(not_raised_exception) not_vt;
    109
    1110int main(int argc, char * argv[]) {
     
    1312        volatile bool should_throw = false;
    1413        if (1 < argc) {
    15                 times = strtol(argv[1], 0p, 10);
     14                times = strto(argv[1], 0p, 10);
    1615        }
    1716
     
    2827        }
    2928        Time end_time = timeHiRes();
    30         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     29        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    3130}
  • doc/theses/andrew_beach_MMath/code/try-catch.cpp

    red4d7c1 r1a6a6f2  
    44#include <exception>
    55#include <iostream>
     6#include <iomanip>
    67
     8using namespace std;
    79using namespace std::chrono;
    810
     
    2931        time_point<steady_clock> end_time = steady_clock::now();
    3032        nanoseconds duration = duration_cast<nanoseconds>(end_time - start_time);
    31         std::cout << "Run-Time (ns): " << duration.count() << std::endl;
     33        cout << "Run-Time (s): " << fixed << setprecision(1) << duration.count() / 1'000'000'000. << endl;
    3234}
  • doc/theses/andrew_beach_MMath/code/try-catch.py

    red4d7c1 r1a6a6f2  
    2323
    2424    end_time = thread_time_ns()
    25     print('Run-Time (ns):', end_time - start_time)
     25    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    2626
    2727
  • doc/theses/andrew_beach_MMath/code/try-finally.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(not_raised_exception)();
    8 
    9 EHM_VIRTUAL_TABLE(not_raised_exception, not_vt);
     7exception not_raised_exception;
     8vtable(not_raised_exception) not_vt;
    109
    1110int main(int argc, char * argv[]) {
     
    1312        volatile bool should_throw = false;
    1413        if (1 < argc) {
    15                 times = strtol(argv[1], 0p, 10);
     14                times = strto(argv[1], 0p, 10);
    1615        }
    1716
     
    2827        }
    2928        Time end_time = timeHiRes();
    30         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     29        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    3130}
  • doc/theses/andrew_beach_MMath/code/try-finally.py

    red4d7c1 r1a6a6f2  
    2222
    2323    end_time = thread_time_ns()
    24     print('Run-Time (ns):', end_time - start_time)
     24    print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
    2525
    2626
  • doc/theses/andrew_beach_MMath/code/try-resume.cfa

    red4d7c1 r1a6a6f2  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>
     5#include <stdlib.hfa>                                                                   // strto
    66
    7 EHM_EXCEPTION(not_raised_exception)();
     7exception not_raised_exception;
    88
    99int main(int argc, char * argv[]) {
     
    1111        unsigned int total_frames = 1;
    1212        if (1 < argc) {
    13                 times = strtol(argv[1], 0p, 10);
     13                times = strto(argv[1], 0p, 10);
    1414        }
    1515        if (2 < argc) {
    16                 total_frames = strtol(argv[2], 0p, 10);
     16                total_frames = strto(argv[2], 0p, 10);
    1717        }
    1818
     
    2626        }
    2727        Time end_time = timeHiRes();
    28         sout | "Run-Time (ns): " | (end_time - start_time)`ns;
     28        sout | "Run-Time (s): " | wd(0,1, (end_time - start_time)`ns / 1_000_000_000.);
    2929}
  • doc/theses/andrew_beach_MMath/conclusion.tex

    red4d7c1 r1a6a6f2  
    44
    55In the previous chapters this thesis presents the design and implementation
    6 of \CFA's exception handling mechanism (EHM).
     6of \CFA's EHM.
    77Both the design and implementation are based off of tools and techniques
    88developed for other programming languages but they were adapted to better fit
    9 \CFA's feature set.
     9\CFA's feature set and add a few features that do not exist in other EHMs,
     10like conditional catch.
    1011
    1112The resulting features cover all of the major use cases of the most popular
    1213termination EHMs of today, along with reintroducing resumption exceptions and
    13 creating some new features that fix with \CFA's larger programming patterns.
     14creating some new features that fit with \CFA's larger programming patterns,
     15such as virtuals independent of traditional objects.
    1416
    15 The implementation has been tested and compared to other implementations.
     17The implementation has been tested through a set of small but interesting micro-benchmarks
     18and compared to other implementations.
    1619The results, while not cutting edge, are good enough for prototyping, which
    17 is \CFA's stage of development.
     20is \CFA's current stage of development.
    1821
    19 This is a valuable new feature for \CFA in its own right but also serves
    20 as a tool (and motivation) for other developments in the language.
     22This initial EHM is a valuable new feature for \CFA in its own right but also serves
     23as a tool and motivation for other developments in the language.
  • doc/theses/andrew_beach_MMath/future.tex

    red4d7c1 r1a6a6f2  
    22\label{c:future}
    33
     4The following discussion covers both missing language features that affected my
     5work and research based improvements.
     6
    47\section{Language Improvements}
    5 \todo{Future/Language Improvements seems to have gotten mixed up. It is
    6 presented as ``waiting on language improvements" but really its more
    7 non-research based impovements.}
     8
    89\CFA is a developing programming language. As such, there are partially or
    9 unimplemented features of the language (including several broken components)
    10 that I had to workaround while building an exception handling system largely in
     10unimplemented features (including several broken components)
     11that I had to workaround while building an EHM largely in
    1112the \CFA language (some C components).  The following are a few of these
    1213issues, and once implemented/fixed, how they would affect the exception system.
     
    1415\item
    1516The implementation of termination is not portable because it includes
    16 hand-crafted assembly statements.
    17 The existing compilers cannot translate that for other platforms and those
    18 sections must be ported by hand to
    19 support more hardware architectures, such as the ARM processor.
     17hand-crafted assembly statements for each architecture, where the
     18ARM processor was just added.
     19% The existing compilers cannot translate that for other platforms and those
     20% sections must be ported by hand to
     21Supporting more hardware architectures in a general way is important.
    2022\item
    2123Due to a type-system problem, the catch clause cannot bind the exception to a
     
    2729@return@, \etc. The reason is that current code generation hoists a handler
    2830into a nested function for convenience (versus assemble-code generation at the
    29 @try@ statement). Hence, when the handler runs, its code is not in the lexical
    30 scope of the @try@ statement, where the local control-flow transfers are
    31 meaningful.
     31@try@ statement). Hence, when the handler runs, its can access local variable
     32in the lexical scope of the @try@ statement, but the closure does not capture
     33local control-flow points so it cannot perform non-local transfers in the
     34hoisted function.
    3235\item
    3336There is no detection of colliding unwinds. It is possible for clean-up code
    3437run during an unwind to trigger another unwind that escapes the clean-up code
    3538itself; such as a termination exception caught further down the stack or a
    36 cancellation. There do exist ways to handle this but currently they are not
    37 even detected and the first unwind will simply be forgotten, often leaving
     39cancellation. There do exist ways to handle this case, but currently there is no
     40detection and the first unwind is simply forgotten, often leaving
    3841it in a bad state.
    3942\item
    40 Also the exception system did not have a lot of time to be tried and tested.
    41 So just letting people use the exception system more will reveal new
    42 quality of life upgrades that can be made with time.
     43Finally, the exception system has not have a lot programmer testing.
     44More time with encouraged usage will reveal new
     45quality of life upgrades that can be made.
    4346\end{itemize}
    4447
     
    4750project, but was thrust upon it to do exception inheritance; hence, only
    4851minimal work is done. A draft for a complete virtual system is available but
    49 it is not finalized.  A future \CFA project is to complete that work and then
     52not finalized.  A future \CFA project is to complete that work and then
    5053update the exception system that uses the current version.
    5154
     
    5356exception traits. The most important one is an assertion to check one virtual
    5457type is a child of another. This check precisely captures many of the
    55 correctness requirements.
     58current ad-hoc correctness requirements.
    5659
    5760The full virtual system might also include other improvement like associated
    5861types to allow traits to refer to types not listed in their header. This
    5962feature allows exception traits to not refer to the virtual-table type
    60 explicitly, removing the need for the current interface macros.
     63explicitly. %, removing the need for the current interface macros.
    6164
    6265\section{Additional Raises}
     
    9396Checked exceptions make exceptions part of a function's type by adding an
    9497exception signature. An exception signature must declare all checked
    95 exceptions that could propagate from the function (either because they were
    96 raised inside the function or came from a sub-function). This improves safety
     98exceptions that could propagate from the function, either because they were
     99raised inside the function or a call to a sub-function. This improves safety
    97100by making sure every checked exception is either handled or consciously
    98101passed on.
    99102
    100103However checked exceptions were never seriously considered for this project
    101 because they have significant trade-offs in usablity and code reuse in
     104because they have significant trade-offs in usability and code reuse in
    102105exchange for the increased safety.
    103106These trade-offs are most problematic when trying to pass exceptions through
     
    129132not support a successful-exiting stack-search without doing an unwind.
    130133Workarounds are possible but awkward. Ideally an extension to libunwind could
    131 be made, but that would either require separate maintenance or gain enough
    132 support to have it folded into the standard.
     134be made, but that would either require separate maintenance or gaining enough
     135support to have it folded into the code base.
    133136
    134137Also new techniques to skip previously searched parts of the stack need to be
     
    158161to leave the handler.
    159162Currently, mimicking this behaviour in \CFA is possible by throwing a
    160 termination inside a resumption handler.
     163termination exception inside a resumption handler.
    161164
    162165% Maybe talk about the escape; and escape CONTROL_STMT; statements or how
  • doc/theses/andrew_beach_MMath/performance.tex

    red4d7c1 r1a6a6f2  
    33
    44Performance is of secondary importance for most of this project.
    5 Instead, the focus is to get the features working. The only performance
     5Instead, the focus was to get the features working. The only performance
    66requirement is to ensure the tests for correctness run in a reasonable
    7 amount of time.
     7amount of time. Hence, a few basic performance tests were performed to
     8check this requirement.
    89
    910\section{Test Set-Up}
     
    1415C++ is the most comparable language because both it and \CFA use the same
    1516framework, libunwind.
    16 In fact, the comparison is almost entirely a quality of implementation
    17 comparison: \CFA's EHM has had significantly less time to be optimized and
     17In fact, the comparison is almost entirely a quality of implementation.
     18Specifically, \CFA's EHM has had significantly less time to be optimized and
    1819does not generate its own assembly. It does have a slight advantage in that
    1920there are some features it handles directly instead of through utility functions,
    20 but otherwise \Cpp has a significant advantage.
    21 
    22 Java is another very popular language with similar termination semantics.
    23 It is implemented in a very different environment, a virtual machine with
     21but otherwise \Cpp should have a significant advantage.
     22
     23Java is a popular language with similar termination semantics, but
     24it is implemented in a very different environment, a virtual machine with
    2425garbage collection.
    2526It also implements the @finally@ clause on @try@ blocks allowing for a direct
    2627feature-to-feature comparison.
    27 As with \Cpp, Java's implementation is mature, optimizations
     28As with \Cpp, Java's implementation is mature, optimized
    2829and has extra features.
    2930
    30 Python is used as an alternative point of comparison because of the \CFA EHM's
     31Python is used as an alternative comparison because of the \CFA EHM's
    3132current performance goals, which is not to be prohibitively slow while the
    3233features are designed and examined. Python has similar performance goals for
     
    3637resumption exceptions. Even the older programming languages with resumption
    3738seem to be notable only for having resumption.
    38 So instead, resumption is compared to a less similar but much more familiar
    39 feature, termination exceptions.
     39So instead, resumption is compared to its simulation in other programming
     40languages using fixup functions that are explicitly passed for correction or
     41logging purposes.
     42% So instead, resumption is compared to a less similar but much more familiar
     43%feature, termination exceptions.
    4044
    4145All tests are run inside a main loop that repeatedly performs a test.
    4246This approach avoids start-up or tear-down time from
    4347affecting the timing results.
    44 Each test is run a million times.
    45 The Java versions of the test run this loop an extra 1000 times before
    46 beginning to actual test to ``warm-up" the JVM.
     48Each test is run a N times (configurable from the command line).
     49The Java tests runs the main loop 1000 times before
     50beginning the actual test to ``warm-up" the JVM.
    4751
    4852Timing is done internally, with time measured immediately before and
     
    6670
    6771The tests are compiled with gcc-10 for \CFA and g++-10 for \Cpp. Java is
    68 compiled with 11.0.11. Python with 3.8. The tests were run on:
     72compiled with version 11.0.11. Python with version 3.8. The tests were run on:
    6973\begin{itemize}[nosep]
    7074\item
     
    7377AMD 6380 Abu Dhabi 16-core 4$\times$socket \lstinline{@} 2.5 GHz running Linux v5.11.0-25
    7478\end{itemize}
     79Two kinds of hardware architecture allows discriminating any implementation and
     80architectural effects.
     81
    7582
    7683% We don't use catch-alls but if we did:
     
    8491
    8592\paragraph{Raise and Handle}
    86 The first group measures the cost of a try statement when exceptions are raised
    87 and \emph{the stack is unwound}.  Each test has has a repeating function like
    88 the following
    89 \begin{cfa}
     93This group measures the cost of a try statement when exceptions are raised and
     94the stack is unwound (termination) or not unwound (resumption).  Each test has
     95has a repeating function like the following
     96\begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}]
    9097void unwind_empty(unsigned int frames) {
    9198        if (frames) {
    92                 unwind_empty(frames - 1);
     99                @unwind_empty(frames - 1);@ // AUGMENTED IN OTHER EXPERIMENTS
    93100        } else throw (empty_exception){&empty_vt};
    94101}
    95 \end{cfa}
    96 which is called M times, where each call recurses to a depth of N, an
     102\end{lstlisting}
     103which is called N times, where each call recurses to a depth of R (configurable from the command line), an
    97104exception is raised, the stack is a unwound, and the exception caught.
    98105\begin{itemize}[nosep]
    99106\item Empty:
    100 This test measures the cost of raising (stack walking) an exception through empty
    101 empty stack frames to an empty handler. (see above)
     107For termination, this test measures the cost of raising (stack walking) an
     108exception through empty stack frames from the bottom of the recursion to an
     109empty handler, and unwinding the stack. (see above code)
     110
     111\medskip
     112For resumption, this test measures the same raising cost but does not unwind
     113the stack. For languages without resumption, a fixup function is to the bottom
     114of the recursion and called to simulate a fixup operation at that point.
     115\begin{cfa}
     116void nounwind_fixup(unsigned int frames, void (*raised_rtn)(int &)) {
     117        if (frames) {
     118                nounwind_fixup(frames - 1, raised_rtn);
     119        } else {
     120                int fixup = 17;
     121                raised_rtn(fixup);
     122        }
     123}
     124\end{cfa}
     125where the passed fixup function is:
     126\begin{cfa}
     127void raised(int & fixup) {
     128        fixup = 42;
     129}
     130\end{cfa}
     131For comparison, a \CFA version passing a function is also included.
    102132\item Destructor:
    103 
    104 This test measures the cost of raising an exception through non-empty frames
    105 where each frame has an object requiring destruction, to an empty
    106 handler. Hence, there are N destructor calls during unwinding.
    107 \begin{cfa}
    108 if (frames) {
     133This test measures the cost of raising an exception through non-empty frames,
     134where each frame has an object requiring destruction, from the bottom of the
     135recursion to an empty handler. Hence, there are N destructor calls during
     136unwinding.
     137
     138\medskip
     139This test is not meaningful for resumption because the stack is only unwound as
     140the recursion returns.
     141\begin{cfa}
    109142        WithDestructor object;
    110         unwind_empty(frames - 1);
     143        unwind_destructor(frames - 1);
    111144\end{cfa}
    112145\item Finally:
    113146This test measures the cost of establishing a try block with an empty finally
    114 clause on the front side of the recursion and running the empty finally clause
    115 on the back side of the recursion during stack unwinding.
    116 \begin{cfa}
    117 if (frames) {
     147clause on the front side of the recursion and running the empty finally clauses
     148during stack unwinding from the bottom of the recursion to an empty handler.
     149\begin{cfa}
    118150        try {
    119151                unwind_finally(frames - 1);
    120152        } finally {}
    121153\end{cfa}
     154
     155\medskip
     156This test is not meaningful for resumption because the stack is only unwound as
     157the recursion returns.
    122158\item Other Handler:
    123 This test is like the finally test but the try block has a catch clause for an
    124 exception that is not raised, so catch matching is executed during stack
    125 unwinding but the match never successes until the catch at the bottom of the
    126 stack.
    127 \begin{cfa}
    128 if (frames) {
     159For termination, this test is like the finally test but the try block has a
     160catch clause for an exception that is not raised, so catch matching is executed
     161during stack unwinding but the match never successes until the catch at the
     162bottom of the recursion.
     163\begin{cfa}
    129164        try {
    130165                unwind_other(frames - 1);
    131166        } catch (not_raised_exception *) {}
    132167\end{cfa}
     168
     169\medskip
     170For resumption, this test measures the same raising cost but does not unwind
     171the stack. For languages without resumption, the same fixup function is passed
     172and called.
    133173\end{itemize}
    134174
    135 \paragraph{Cross Try Statement}
    136 The next group measures just the cost of executing a try statement so
     175\paragraph{Try/Handle/Finally Statement}
     176This group measures just the cost of executing a try statement so
    137177\emph{there is no stack unwinding}.  Hence, the program main loops N times
    138178around:
     
    143183\begin{itemize}[nosep]
    144184\item Handler:
    145 The try statement has a handler.
     185The try statement has a handler (catch/resume).
    146186\item Finally:
    147 The try statement replaces the handler with a finally clause.
     187The try statement has a finally clause.
    148188\end{itemize}
    149189
    150190\paragraph{Conditional Matching}
    151 This final group measures the cost of conditional matching.
     191This group measures the cost of conditional matching.
    152192Only \CFA implements the language level conditional match,
    153 the other languages must mimic with an ``unconditional" match (it still
    154 checks the exception's type) and conditional re-raise if it was not supposed
     193the other languages mimic with an ``unconditional" match (it still
     194checks the exception's type) and conditional re-raise if it is not suppose
    155195to handle that exception.
    156196\begin{center}
     
    180220The condition is always false. (Never matches or always re-raises.)
    181221\end{itemize}
     222
     223\medskip
     224\noindent
     225All omitted test code for other languages is functionally identical to the \CFA
     226tests or simulated, and available online~\cite{CforallExceptionBenchmarks}.
    182227
    183228%\section{Cost in Size}
     
    192237
    193238\section{Results}
    194 In cases where a feature is not supported by a language the test is skipped
    195 for that language.
    196 \PAB{Report all values.
    197 
    198 Similarly, if a test does not change between resumption
    199 and termination in \CFA, then only one test is written and the result
    200 was put into the termination column.
    201 }
     239One result not directly related to \CFA but important to keep in
     240mind is that, for exceptions, the standard intuition about which languages
     241should go faster often does not hold. For example, there are a few cases where Python out-performs
     242\CFA, \Cpp and Java. The most likely explanation is that, since exceptions are
     243rarely considered to be the common case, the more optimized languages
     244make that case expense. In addition, languages with high-level
     245representations have a much easier time scanning the stack as there is less
     246to decode.
     247
     248Tables~\ref{t:PerformanceTermination} and~\ref{t:PerformanceResumption} show
     249the test results for termination and resumption, respectively.  In cases where
     250a feature is not supported by a language, the test is skipped for that language
     251(marked N/A).  For some Java experiments it was impossible to measure certain
     252effects because the JIT corrupted the test (marked N/C). No workaround was
     253possible~\cite{Dice21}.  To get experiments in the range of 1--100 seconds, the
     254number of times an experiment is run (N) is varied (N is marked beside each
     255experiment, e.g., 1M $\Rightarrow$ 1 million test iterations).
     256
     257An anomaly exists with gcc nested functions used as thunks for implementing
     258much of the \CFA EHM. If a nested-function closure captures local variables in
     259its lexical scope, performance dropped by a factor of 10.  Specifically, in try
     260statements of the form:
     261\begin{cfa}
     262        try {
     263                unwind_other(frames - 1);
     264        } catch (not_raised_exception *) {}
     265\end{cfa}
     266the try block is hoisted into a nested function and the variable @frames@ is
     267the local parameter to the recursive function, which triggers the anomaly. The
     268workaround is to remove the recursion parameter and make it a global variable
     269that is explicitly decremented outside of the try block (marked with a ``*''):
     270\begin{cfa}
     271        frames -= 1;
     272        try {
     273                unwind_other();
     274        } catch (not_raised_exception *) {}
     275\end{cfa}
     276To make comparisons fair, a dummy parameter is added and the dummy value passed
     277in the recursion. Note, nested functions in gcc are rarely used (if not
     278completely unknown) and must follow the C calling convention, unlike \Cpp
     279lambdas, so it is not surprising if there are performance issues efficiently
     280capturing closures.
     281
     282% Similarly, if a test does not change between resumption
     283% and termination in \CFA, then only one test is written and the result
     284% was put into the termination column.
    202285
    203286% Raw Data:
     
    235318% Match None    & 0.0 & 0.0 &  9476060146 & 0.0 & 0.0 \\
    236319
    237 \begin{tabular}{|l|c c c c c|}
    238 \hline
    239               & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\
    240 \hline
    241 Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    242 Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
    243 Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
    244 Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    245 Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    246 Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
    247 Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    248 Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    249 \hline
    250 \end{tabular}
    251 
    252320% run-plg7a-a.sat
    253321% ---------------
     
    284352% Match None    & 0.0 & 0.0 &  7829059869 & 0.0 & 0.0 \\
    285353
    286 % PLG7A (in seconds)
    287 \begin{tabular}{|l|c c c c c|}
     354\begin{table}
     355\centering
     356\caption{Performance Results Termination (sec)}
     357\label{t:PerformanceTermination}
     358\begin{tabular}{|r|*{2}{|r r r r|}}
    288359\hline
    289               & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\
    290 \hline
    291 Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    292 Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
    293 Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
    294 Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    295 Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    296 Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
    297 Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
    298 Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
     360                        & \multicolumn{4}{c||}{AMD}             & \multicolumn{4}{c|}{ARM}      \\
     361\cline{2-9}
     362N\hspace{8pt}           & \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c||}{Python} &
     363                          \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
     364\hline                                                                             
     365Throw Empty (1M)        & 3.4   & 2.8   & 18.3  & 23.4          & 3.7   & 3.2   & 15.5  & 14.8  \\
     366Throw D'tor (1M)        & 48.4  & 23.6  & N/A   & N/A           & 64.2  & 29.0  & N/A   & N/A   \\
     367Throw Finally (1M)      & 3.4*  & N/A   & 17.9  & 29.0          & 4.1*  & N/A   & 15.6  & 19.0  \\
     368Throw Other (1M)        & 3.6*  & 23.2  & 18.2  & 32.7          & 4.0*  & 24.5  & 15.5  & 21.4  \\
     369Try/Catch (100M)        & 6.0   & 0.9   & N/C   & 37.4          & 10.0  & 0.8   & N/C   & 32.2  \\
     370Try/Finally (100M)      & 0.9   & N/A   & N/C   & 44.1          & 0.8   & N/A   & N/C   & 37.3  \\
     371Match All (10M)         & 32.9  & 20.7  & 13.4  & 4.9           & 36.2  & 24.5  & 12.0  & 3.1   \\
     372Match None (10M)        & 32.7  & 50.3  & 11.0  & 5.1           & 36.3  & 71.9  & 12.3  & 4.2   \\
    299373\hline
    300374\end{tabular}
    301 
    302 One result not directly related to \CFA but important to keep in
    303 mind is that, for exceptions, the standard intuition about which languages
    304 should go faster often does not hold. For example, there are cases where Python out-performs
    305 \Cpp and Java. The most likely explanation is that, since exceptions are
    306 rarely considered to be the common case, the more optimized languages
    307 make that case expense. In addition, languages with high-level
    308 representations have a much easier time scanning the stack as there is less
    309 to decode.
    310 
    311 This observation means that while \CFA does not actually keep up with Python in every
    312 case, it is usually no worse than roughly half the speed of \Cpp. This performance is good
    313 enough for the prototyping purposes of the project.
     375\end{table}
     376
     377\begin{table}
     378\centering
     379\small
     380\caption{Performance Results Resumption (sec)}
     381\label{t:PerformanceResumption}
     382\setlength{\tabcolsep}{5pt}
     383\begin{tabular}{|r|*{2}{|r r r r|}}
     384\hline
     385                        & \multicolumn{4}{c||}{AMD}             & \multicolumn{4}{c|}{ARM}      \\
     386\cline{2-9}
     387N\hspace{8pt}           & \multicolumn{1}{c}{\CFA (R/F)} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c||}{Python} &
     388                          \multicolumn{1}{c}{\CFA (R/F)} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
     389\hline                                                                             
     390Resume Empty (10M)      & 3.8/3.5       & 14.7  & 2.3   & 176.1 & 0.3/0.1       & 8.9   & 1.2   & 119.9 \\
     391Resume Other (10M)      & 4.0*/0.1*     & 21.9  & 6.2   & 381.0 & 0.3*/0.1*     & 13.2  & 5.0   & 290.7 \\
     392Try/Resume (100M)       & 8.8           & N/A   & N/A   & N/A   & 12.3          & N/A   & N/A   & N/A   \\
     393Match All (10M)         & 0.3           & N/A   & N/A   & N/A   & 0.3           & N/A   & N/A   & N/A   \\
     394Match None (10M)        & 0.3           & N/A   & N/A   & N/A   & 0.4           & N/A   & N/A   & N/A   \\
     395\hline
     396\end{tabular}
     397\end{table}
     398
     399As stated, the performance tests are not attempting to compare exception
     400handling across languages.  The only performance requirement is to ensure the
     401\CFA EHM implementation runs in a reasonable amount of time, given its
     402constraints. In general, the \CFA implement did very well. Each of the tests is
     403analysed.
     404\begin{description}
     405\item[Throw/Resume Empty]
     406For termination, \CFA is close to \Cpp, where other languages have a higher cost.
     407
     408For resumption, \CFA is better than the fixup simulations in the other languages, except Java.
     409The \CFA results on the ARM computer for both resumption and function simulation are particularly low;
     410I have no explanation for this anomaly, except the optimizer has managed to remove part of the experiment.
     411Python has a high cost for passing the lambda during the recursion.
     412
     413\item[Throw D'tor]
     414For termination, \CFA is twice the cost of \Cpp.
     415The higher cost for \CFA must be related to how destructors are handled.
     416
     417\item[Throw Finally]
     418\CFA is better than the other languages with a @finally@ clause, which is the
     419same for termination and resumption.
     420
     421\item[Throw/Resume Other]
     422For termination, \CFA is better than the other languages.
     423
     424For resumption, \CFA is equal to or better the other languages.
     425Again, the \CFA results on the ARM computer for both resumption and function simulation are particularly low.
     426Python has a high cost for passing the lambda during the recursion.
     427
     428\item[Try/Catch/Resume]
     429For termination, installing a try statement is more expressive than \Cpp
     430because the try components are hoisted into local functions.  At runtime, these
     431functions are than passed to libunwind functions to set up the try statement.
     432\Cpp zero-cost try-entry accounts for its performance advantage.
     433
     434For resumption, there are similar costs to termination to set up the try
     435statement but libunwind is not used.
     436
     437\item[Try/Finally]
     438Setting up a try finally is less expensive in \CFA than setting up handlers,
     439and is significantly less than other languages.
     440
     441\item[Throw/Resume Match All]
     442For termination, \CFA is close to the other language simulations.
     443
     444For resumption, the stack unwinding is much faster because it does not use
     445libunwind.  Instead resumption is just traversing a linked list with each node
     446being the next stack frame with the try block.
     447
     448\item[Throw/Resume Match None]
     449The same results as for Match All.
     450\end{description}
     451
     452\begin{comment}
     453This observation means that while \CFA does not actually keep up with Python in
     454every case, it is usually no worse than roughly half the speed of \Cpp. This
     455performance is good enough for the prototyping purposes of the project.
    314456
    315457The test case where \CFA falls short is Raise Other, the case where the
    316458stack is unwound including a bunch of non-matching handlers.
    317459This slowdown seems to come from missing optimizations.
    318 
    319 Importantly, there is a huge slowdown in \Cpp's results bringing that brings
    320 \CFA's performance back in that roughly half speed area. However many other
    321 \CFA benchmarks increase their run-time by a similar amount falling far
    322 behind their \Cpp counter-parts.
    323460
    324461This suggests that the performance issue in Raise Other is just an
     
    364501The difference in relative performance does show that there are savings to
    365502be made by performing the check without catching the exception.
     503\end{comment}
     504
     505
     506\begin{comment}
     507From: Dave Dice <dave.dice@oracle.com>
     508To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
     509Subject: Re: [External] : JIT
     510Date: Mon, 16 Aug 2021 01:21:56 +0000
     511
     512> On 2021-8-15, at 7:14 PM, Peter A. Buhr <pabuhr@uwaterloo.ca> wrote:
     513>
     514> My student is trying to measure the cost of installing a try block with a
     515> finally clause in Java.
     516>
     517> We tried the random trick (see below). But if the try block is comment out, the
     518> results are the same. So the program measures the calls to the random number
     519> generator and there is no cost for installing the try block.
     520>
     521> Maybe there is no cost for a try block with an empty finally, i.e., the try is
     522> optimized away from the get-go.
     523
     524There's quite a bit of optimization magic behind the HotSpot curtains for
     525try-finally.  (I sound like the proverbial broken record (:>)).
     526
     527In many cases we can determine that the try block can't throw any exceptions,
     528so we can elide all try-finally plumbing.  In other cases, we can convert the
     529try-finally to normal if-then control flow, in the case where the exception is
     530thrown into the same method.  This makes exceptions _almost cost-free.  If we
     531actually need to "physically" rip down stacks, then things get expensive,
     532impacting both the throw cost, and inhibiting other useful optimizations at the
     533catch point.  Such "true" throws are not just expensive, they're _very
     534expensive.  The extremely aggressive inlining used by the JIT helps, because we
     535can convert cases where a heavy rip-down would normally needed back into simple
     536control flow.
     537
     538Other quirks involve the thrown exception object.  If it's never accessed then
     539we're apply a nice set of optimizations to avoid its construction.  If it's
     540accessed but never escapes the catch frame (common) then we can also cheat.
     541And if we find we're hitting lots of heavy rip-down cases, the JIT will
     542consider recompilation - better inlining -- to see if we can merge the throw
     543and catch into the same physical frame, and shift to simple branches.
     544
     545In your example below, System.out.print() can throw, I believe.  (I could be
     546wrong, but most IO can throw).  Native calls that throw will "unwind" normally
     547in C++ code until they hit the boundary where they reenter java emitted code,
     548at which point the JIT-ed code checks for a potential pending exception.  So in
     549a sense the throw point is implicitly after the call to the native method, so
     550we can usually make those cases efficient.
     551
     552Also, when we're running in the interpreter and warming up, we'll notice that
     553the == 42 case never occurs, and so when we start to JIT the code, we elide the
     554call to System.out.print(), replacing it (and anything else which appears in
     555that if x == 42 block) with a bit of code we call an "uncommon trap".  I'm
     556presuming we encounter 42 rarely.  So if we ever hit the x == 42 case, control
     557hits the trap, which triggers synchronous recompilation of the method, this
     558time with the call to System.out.print() and, because of that, we now to adapt
     559the new code to handle any traps thrown by print().  This is tricky stuff, as
     560we may need to rebuild stack frames to reflect the newly emitted method.  And
     561we have to construct a weird bit of "thunk" code that allows us to fall back
     562directly into the newly emitted "if" block.  So there's a large one-time cost
     563when we bump into the uncommon trap and recompile, and subsequent execution
     564might get slightly slower as the exception could actually be generated, whereas
     565before we hit the trap, we knew the exception could never be raised.
     566
     567Oh, and things also get expensive if we need to actually fill in the stack
     568trace associated with the exception object.  Walking stacks is hellish.
     569
     570Quite a bit of effort was put into all this as some of the specjvm benchmarks
     571showed significant benefit.
     572
     573It's hard to get sensible measurements as the JIT is working against you at
     574every turn.  What's good for the normal user is awful for anybody trying to
     575benchmark.  Also, all the magic results in fairly noisy and less reproducible
     576results.
     577
     578Regards
     579Dave
     580
     581p.s., I think I've mentioned this before, but throwing in C++ is grim as
     582unrelated throws in different threads take common locks, so nothing scales as
     583you might expect.
     584\end{comment}
  • doc/theses/andrew_beach_MMath/uw-ethesis.bib

    red4d7c1 r1a6a6f2  
    22% For use with BibTeX
    33
    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"
     4@misc{Dice21,
     5    author      = {Dave Dice},
     6    year        = 2021,
     7    month       = aug,
     8    howpublished= {personal communication}
    119}
    1210
    13 @book{knuth.book,
    14         author =        "Donald Knuth",
    15         title =         "The \TeX book",
    16         year =          "1986",
    17         publisher =     "Addison-Wesley",
    18         address =       "Reading, Massachusetts"
     11@misc{CforallExceptionBenchmarks,
     12    contributer = {pabuhr@plg},
     13    key         = {Cforall Exception Benchmarks},
     14    author      = {{\textsf{C}{$\mathbf{\forall}$} Exception Benchmarks}},
     15    howpublished= {\href{https://github.com/cforall/ExceptionBenchmarks_SPE20}{https://\-github.com/\-cforall/\-ExceptionBenchmarks\_SPE20}},
    1916}
    20 
    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"
    28 }
  • libcfa/prelude/builtins.c

    red4d7c1 r1a6a6f2  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 21 13:31:34 2021
    13 // Update Count     : 129
     12// Last Modified On : Sat Aug 14 08:45:54 2021
     13// Update Count     : 133
    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
    109113// exponentiation operator implementation
    110114
  • libcfa/src/concurrency/monitor.cfa

    red4d7c1 r1a6a6f2  
    367367
    368368        // __cfaabi_dbg_print_safe( "MGUARD : entered\n" );
     369}
     370
     371void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count ) {
     372        this{ m, count, 0p };
    369373}
    370374
  • libcfa/src/concurrency/monitor.hfa

    red4d7c1 r1a6a6f2  
    4848
    4949void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count, void (*func)() );
     50void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count );
    5051void ^?{}( monitor_guard_t & this );
    5152
  • src/AST/Convert.cpp

    red4d7c1 r1a6a6f2  
    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
    608617        TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
    609618
     
    21242133        }
    21252134
     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
    21262145        // TypeSubstitution shouldn't exist yet in old.
    21272146        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
  • src/AST/Fwd.hpp

    red4d7c1 r1a6a6f2  
    6060class NullStmt;
    6161class ImplicitCtorDtorStmt;
     62class MutexStmt;
    6263
    6364class Expr;
  • src/AST/Node.cpp

    red4d7c1 r1a6a6f2  
    176176template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::weak >;
    177177template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::strong >;
     178template class ast::ptr_base< ast::MutexStmt, ast::Node::ref_type::weak >;
     179template class ast::ptr_base< ast::MutexStmt, ast::Node::ref_type::strong >;
    178180template class ast::ptr_base< ast::Expr, ast::Node::ref_type::weak >;
    179181template class ast::ptr_base< ast::Expr, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    red4d7c1 r1a6a6f2  
    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;
    164165        const ast::Expr *             visit( const ast::ApplicationExpr      * ) override final;
    165166        const ast::Expr *             visit( const ast::UntypedExpr          * ) override final;
  • src/AST/Pass.impl.hpp

    red4d7c1 r1a6a6f2  
    10391039
    10401040//--------------------------------------------------------------------------
     1041// MutexStmt
     1042template< typename core_t >
     1043const 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//--------------------------------------------------------------------------
    10411057// ApplicationExpr
    10421058template< typename core_t >
  • src/AST/Print.cpp

    red4d7c1 r1a6a6f2  
    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 );
    796811                --indent;
    797812                os << endl;
  • src/AST/Stmt.hpp

    red4d7c1 r1a6a6f2  
    426426};
    427427
     428/// Mutex Statement
     429class MutexStmt final : public Stmt {
     430public:
     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 ); }
     439private:
     440        MutexStmt * clone() const override { return new MutexStmt{ *this }; }
     441        MUTATE_FRIEND
     442};
     443
    428444}
    429445
  • src/AST/Visitor.hpp

    red4d7c1 r1a6a6f2  
    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;
    5657    virtual const ast::Expr *             visit( const ast::ApplicationExpr      * ) = 0;
    5758    virtual const ast::Expr *             visit( const ast::UntypedExpr          * ) = 0;
  • src/CodeGen/CodeGenerator.cc

    red4d7c1 r1a6a6f2  
    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
    11891194        void CodeGenerator::handleStorageClass( DeclarationWithType * decl ) {
    11901195                if ( decl->get_storageClasses().any() ) {
  • src/CodeGen/CodeGenerator.h

    red4d7c1 r1a6a6f2  
    121121                void postvisit( DeclStmt * );
    122122                void postvisit( ImplicitCtorDtorStmt * );
     123                void postvisit( MutexStmt * stmt );
    123124
    124125                void genAttributes( std::list< Attribute * > & attributes );
  • src/Common/CodeLocationTools.cpp

    red4d7c1 r1a6a6f2  
    125125    macro(DeclStmt, Stmt) \
    126126    macro(ImplicitCtorDtorStmt, Stmt) \
     127    macro(MutexStmt, Stmt) \
    127128    macro(ApplicationExpr, Expr) \
    128129    macro(UntypedExpr, Expr) \
  • src/Common/PassVisitor.h

    red4d7c1 r1a6a6f2  
    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;
    126128
    127129        virtual void visit( ApplicationExpr * applicationExpr ) override final;
     
    291293        virtual Statement * mutate( DeclStmt * declStmt ) override final;
    292294        virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
     295        virtual Statement * mutate( MutexStmt * mutexStmt ) override final;
    293296
    294297        virtual Expression * mutate( ApplicationExpr * applicationExpr ) override final;
  • src/Common/PassVisitor.impl.h

    red4d7c1 r1a6a6f2  
    17811781
    17821782//--------------------------------------------------------------------------
     1783// MutexStmt
     1784template< typename pass_type >
     1785void 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
     1796template< typename pass_type >
     1797void 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
     1807template< typename pass_type >
     1808Statement * 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//--------------------------------------------------------------------------
    17831819// ApplicationExpr
    17841820template< typename pass_type >
  • src/Concurrency/Keywords.cc

    red4d7c1 r1a6a6f2  
    302302                void postvisit( FunctionDecl * decl );
    303303                void postvisit(   StructDecl * decl );
     304                Statement * postmutate( MutexStmt * stmt );
    304305
    305306                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
     
    307308                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    308309                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     310                void addStatements( CompoundStmt * body, const std::list<Expression * > & args );
    309311                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
    310312
     
    312314                        PassVisitor< MutexKeyword > impl;
    313315                        acceptAll( translationUnit, impl );
     316                        mutateAll( translationUnit, impl );
    314317                }
    315318
     
    935938                        thread_guard_decl = decl;
    936939                }
     940        }
     941
     942        Statement * MutexKeyword::postmutate( MutexStmt * stmt ) {
     943                std::list<Statement *> stmtsForCtor;
     944                stmtsForCtor.push_back(stmt->stmt);
     945                CompoundStmt * body = new CompoundStmt( stmtsForCtor );
     946                addStatements( body, stmt->mutexObjs);
     947                return body;
    937948        }
    938949
     
    10581069                        ))
    10591070                );
     1071        }
     1072
     1073        void MutexKeyword::addStatements( CompoundStmt * body, const std::list<Expression * > & args ) {
     1074                ObjectDecl * monitors = new ObjectDecl(
     1075                        "__monitors",
     1076                        noStorageClasses,
     1077                        LinkageSpec::Cforall,
     1078                        nullptr,
     1079                        new ArrayType(
     1080                                noQualifiers,
     1081                                new PointerType(
     1082                                        noQualifiers,
     1083                                        new StructInstType(
     1084                                                noQualifiers,
     1085                                                monitor_decl
     1086                                        )
     1087                                ),
     1088                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
     1089                                false,
     1090                                false
     1091                        ),
     1092                        new ListInit(
     1093                                map_range < std::list<Initializer*> > ( args, [](Expression * var ){
     1094                                        return new SingleInit( new UntypedExpr(
     1095                                                new NameExpr( "get_monitor" ),
     1096                                                { var }
     1097                                        ) );
     1098                                })
     1099                        )
     1100                );
     1101
     1102                // in reverse order :
     1103                // monitor_guard_t __guard = { __monitors, # };
     1104                body->push_front(
     1105                        new DeclStmt( new ObjectDecl(
     1106                                "__guard",
     1107                                noStorageClasses,
     1108                                LinkageSpec::Cforall,
     1109                                nullptr,
     1110                                new StructInstType(
     1111                                        noQualifiers,
     1112                                        guard_decl
     1113                                ),
     1114                                new ListInit(
     1115                                        {
     1116                                                new SingleInit( new VariableExpr( monitors ) ),
     1117                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
     1118                                        },
     1119                                        noDesignators,
     1120                                        true
     1121                                )
     1122                        ))
     1123                );
     1124
     1125                //monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
     1126                body->push_front( new DeclStmt( monitors) );
    10601127        }
    10611128
  • src/Parser/ParseNode.h

    red4d7c1 r1a6a6f2  
    437437WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
    438438Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
     439Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
    439440
    440441//##############################################################################
  • src/Parser/StatementNode.cc

    red4d7c1 r1a6a6f2  
    374374} // build_directive
    375375
     376Statement * 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
    376383// Local Variables: //
    377384// tab-width: 4 //
  • src/Parser/parser.yy

    red4d7c1 r1a6a6f2  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul 20 22:03:04 2021
    13 // Update Count     : 5031
     12// Last Modified On : Sun Aug  8 09:14:44 2021
     13// Update Count     : 5038
    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 ) );
    187188        return new ForCtrl(
    188189                distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
     
    13461347mutex_statement:
    13471348        MUTEX '(' argument_expression_list_opt ')' statement
    1348                 { SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; }
     1349                { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
    13491350        ;
    13501351
  • src/SynTree/Mutator.h

    red4d7c1 r1a6a6f2  
    5858        virtual Statement * mutate( DeclStmt * declStmt ) = 0;
    5959        virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
     60        virtual Statement * mutate( MutexStmt * mutexStmt ) = 0;
    6061
    6162        virtual Expression * mutate( ApplicationExpr * applicationExpr ) = 0;
  • src/SynTree/Statement.cc

    red4d7c1 r1a6a6f2  
    565565}
    566566
     567MutexStmt::MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs )
     568        : Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
     569
     570MutexStmt::MutexStmt( const MutexStmt & other ) : Statement( other ), stmt( maybeClone( other.stmt ) ) {
     571        cloneAll( other.mutexObjs, mutexObjs );
     572}
     573
     574MutexStmt::~MutexStmt() {
     575        deleteAll( mutexObjs );
     576        delete stmt;
     577}
     578
     579void 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
    567591// Local Variables: //
    568592// tab-width: 4 //
  • src/SynTree/Statement.h

    red4d7c1 r1a6a6f2  
    535535};
    536536
     537class 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
    537553// Local Variables: //
    538554// tab-width: 4 //
  • src/SynTree/SynTree.h

    red4d7c1 r1a6a6f2  
    6262class NullStmt;
    6363class ImplicitCtorDtorStmt;
     64class MutexStmt;
    6465
    6566class Expression;
  • src/SynTree/Visitor.h

    red4d7c1 r1a6a6f2  
    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;
    9496
    9597        virtual void visit( ApplicationExpr * node ) { visit( const_cast<const ApplicationExpr *>(node) ); }
  • tests/exceptions/.expect/type-check.txt

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

    red4d7c1 r1a6a6f2  
    22
    33#include <coroutine.hfa>
    4 #include <exception.hfa>
    54
    6 EHM_EXCEPTION(internal_error)();
    7 EHM_VIRTUAL_TABLE(internal_error, internal_vt);
     5exception internal_error {};
     6vtable(internal_error) internal_vt;
    87
    98coroutine WillCancel {};
  • tests/exceptions/cancel/thread.cfa

    red4d7c1 r1a6a6f2  
    22
    33#include <thread.hfa>
    4 #include <exception.hfa>
    54
    6 EHM_EXCEPTION(internal_error)();
    7 EHM_VIRTUAL_TABLE(internal_error, internal_vt);
     5exception internal_error {};
     6vtable(internal_error) internal_vt;
    87
    98thread WillCancel {};
  • tests/exceptions/conditional.cfa

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

    red4d7c1 r1a6a6f2  
    11// Test exceptions that add data but no functionality.
    22
    3 #include <exception.hfa>
    4 
    5 EHM_EXCEPTION(paired)(
     3exception paired {
    64        int first;
    75        int second;
    8 );
     6};
    97
    10 EHM_VIRTUAL_TABLE(paired, paired_vt);
     8vtable(paired) paired_vt;
    119
    1210const char * virtual_msg(paired * this) {
  • tests/exceptions/defaults.cfa

    red4d7c1 r1a6a6f2  
    44#include <exception.hfa>
    55
    6 EHM_EXCEPTION(log_message)(
     6exception 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 EHM_EXCEPTION(jump)();
     34exception jump {};
    3535void defaultTerminationHandler(jump &) {
    3636        printf("jump default handler.\n");
    3737}
    3838
    39 EHM_VIRTUAL_TABLE(jump, jump_vt);
     39vtable(jump) jump_vt;
    4040
    4141void jump_test(void) {
     
    4848}
    4949
    50 EHM_EXCEPTION(first)();
    51 EHM_VIRTUAL_TABLE(first, first_vt);
     50exception first {};
     51vtable(first) first_vt;
    5252
    53 EHM_EXCEPTION(unhandled_exception)();
    54 EHM_VIRTUAL_TABLE(unhandled_exception, unhandled_vt);
     53exception unhandled_exception {};
     54vtable(unhandled_exception) unhandled_vt;
    5555
    5656void unhandled_test(void) {
     
    6969}
    7070
    71 EHM_EXCEPTION(second)();
    72 EHM_VIRTUAL_TABLE(second, second_vt);
     71exception second {};
     72vtable(second) second_vt;
    7373
    7474void cross_test(void) {
  • tests/exceptions/finally.cfa

    red4d7c1 r1a6a6f2  
    11// Finally Clause Tests
    22
    3 #include <exception.hfa>
    43#include "except-io.hfa"
    54
    6 EHM_EXCEPTION(myth)();
     5exception myth {};
    76
    8 EHM_VIRTUAL_TABLE(myth, myth_vt);
     7vtable(myth) myth_vt;
    98
    109int main(int argc, char * argv[]) {
  • tests/exceptions/interact.cfa

    red4d7c1 r1a6a6f2  
    11// Testing Interactions Between Termination and Resumption
    22
    3 #include <exception.hfa>
    43#include "except-io.hfa"
    54
    6 EHM_EXCEPTION(star)();
    7 EHM_EXCEPTION(moon)();
     5exception star {};
     6exception moon {};
    87
    9 EHM_VIRTUAL_TABLE(star, star_vt);
    10 EHM_VIRTUAL_TABLE(moon, moon_vt);
     8vtable(star) star_vt;
     9vtable(moon) moon_vt;
    1110
    1211int main(int argc, char * argv[]) {
  • tests/exceptions/polymorphic.cfa

    red4d7c1 r1a6a6f2  
    11// Testing polymophic exception types.
    22
    3 #include <exception.hfa>
     3forall(T &) exception proxy {};
    44
    5 EHM_FORALL_EXCEPTION(proxy, (T&), (T))();
    6 
    7 EHM_FORALL_VIRTUAL_TABLE(proxy, (int), proxy_int);
    8 EHM_FORALL_VIRTUAL_TABLE(proxy, (char), proxy_char);
     5vtable(proxy(int)) proxy_int;
     6vtable(proxy(char)) proxy_char;
    97
    108void proxy_test(void) {
     
    3331}
    3432
    35 EHM_FORALL_EXCEPTION(cell, (T), (T))(
     33forall(T) exception cell {
    3634        T data;
    37 );
     35};
    3836
    39 EHM_FORALL_VIRTUAL_TABLE(cell, (int), int_cell);
    40 EHM_FORALL_VIRTUAL_TABLE(cell, (char), char_cell);
    41 EHM_FORALL_VIRTUAL_TABLE(cell, (bool), bool_cell);
     37vtable(cell(int)) int_cell;
     38vtable(cell(char)) char_cell;
     39vtable(cell(bool)) bool_cell;
    4240
    4341void cell_test(void) {
  • tests/exceptions/resume.cfa

    red4d7c1 r1a6a6f2  
    11// Resumption Exception Tests
    22
    3 #include <exception.hfa>
    43#include "except-io.hfa"
    54
    6 EHM_EXCEPTION(yin)();
    7 EHM_EXCEPTION(yang)();
    8 EHM_EXCEPTION(zen)();
     5exception yin {};
     6exception yang {};
     7exception zen {};
    98
    10 EHM_VIRTUAL_TABLE(yin, yin_vt);
    11 EHM_VIRTUAL_TABLE(yang, yang_vt);
    12 EHM_VIRTUAL_TABLE(zen, zen_vt);
     9vtable(yin) yin_vt;
     10vtable(yang) yang_vt;
     11vtable(zen) zen_vt;
    1312
    1413void in_void(void);
  • tests/exceptions/terminate.cfa

    red4d7c1 r1a6a6f2  
    11// Termination Exception Tests
    22
    3 #include <exception.hfa>
    43#include "except-io.hfa"
    54
    6 EHM_EXCEPTION(yin)();
    7 EHM_EXCEPTION(yang)();
    8 EHM_EXCEPTION(zen)();
     5exception yin {};
     6exception yang {};
     7exception zen {};
    98
    10 EHM_VIRTUAL_TABLE(yin, yin_vt);
    11 EHM_VIRTUAL_TABLE(yang, yang_vt);
    12 EHM_VIRTUAL_TABLE(zen, zen_vt);
     9vtable(yin) yin_vt;
     10vtable(yang) yang_vt;
     11vtable(zen) zen_vt;
    1312
    1413void in_void(void);
  • tests/exceptions/trash.cfa

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

    red4d7c1 r1a6a6f2  
    11// Check that the exception type check works.
    22
    3 #include <exception.hfa>
    4 
    5 EHM_EXCEPTION(truth)();
     3exception truth {};
    64
    75int main(int argc, char * argv[]) {
Note: See TracChangeset for help on using the changeset viewer.