Changeset 1a6a6f2 for doc/theses/andrew_beach_MMath
- Timestamp:
- Aug 19, 2021, 4:04:43 PM (3 years ago)
- 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. - Location:
- doc/theses/andrew_beach_MMath
- Files:
-
- 10 added
- 24 edited
- 13 moved
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/andrew_beach_MMath/code/CondCatch.java
red4d7c1 r1a6a6f2 6 6 static boolean should_catch = false; 7 7 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 22 8 private static long loop(int times) { 23 9 long startTime = System.nanoTime(); 24 10 for (int count = 0 ; count < times ; ++count) { 25 11 try { 26 cond_catch(); 12 try { 13 throw new EmptyException(); 14 } catch (EmptyException exc) { 15 if (!should_catch) { 16 throw exc; 17 } 18 } 27 19 } catch (EmptyException exc) { 28 20 // ... … … 46 38 47 39 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.); 49 41 } 50 42 } -
doc/theses/andrew_beach_MMath/code/ThrowEmpty.java
red4d7c1 r1a6a6f2 39 39 40 40 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.); 42 42 } 43 43 } -
doc/theses/andrew_beach_MMath/code/ThrowFinally.java
red4d7c1 r1a6a6f2 44 44 45 45 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.); 47 47 } 48 48 } -
doc/theses/andrew_beach_MMath/code/ThrowOther.java
red4d7c1 r1a6a6f2 52 52 53 53 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.); 55 55 } 56 56 } -
doc/theses/andrew_beach_MMath/code/TryCatch.java
red4d7c1 r1a6a6f2 3 3 class NotRaisedException extends Exception {} 4 4 5 public class CrossCatch {5 public class TryCatch { 6 6 private static boolean shouldThrow = false; 7 7 … … 31 31 32 32 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.); 34 34 } 35 35 } -
doc/theses/andrew_beach_MMath/code/TryFinally.java
red4d7c1 r1a6a6f2 1 // Cross a Try Statement with a Finally Clause1 // Enter and Leave a Try Statement with a Finally Handler 2 2 3 public class CrossFinally {3 public class TryFinally { 4 4 private static boolean shouldThrow = false; 5 5 … … 27 27 28 28 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.); 30 30 } 31 31 } -
doc/theses/andrew_beach_MMath/code/cond-catch.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.h >5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 bool 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 }24 11 25 12 int main(int argc, char * argv[]) { 26 13 unsigned int times = 1; 27 14 if (1 < argc) { 28 times = strto l(argv[1], 0p, 10);15 times = strto(argv[1], 0p, 10); 29 16 } 30 17 if (2 < argc) { 31 should_catch = strtol(argv[2], 0p, 10);18 should_catch = (unsigned int)strto(argv[2], 0p, 2); 32 19 } 33 20 … … 35 22 for (unsigned int count = 0 ; count < times ; ++count) { 36 23 try { 37 cond_catch(); 24 throw (empty_exception){&empty_vt}; 25 } catch (empty_exception * exc ; should_catch) { 26 asm volatile ("# catch block (conditional)"); 38 27 } catch (empty_exception * exc) { 39 28 asm volatile ("# catch block (unconditional)"); … … 41 30 } 42 31 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.); 44 33 } -
doc/theses/andrew_beach_MMath/code/cond-catch.cpp
red4d7c1 r1a6a6f2 4 4 #include <exception> 5 5 #include <iostream> 6 #include <iomanip> 6 7 8 using namespace std; 7 9 using namespace std::chrono; 8 10 … … 10 12 11 13 bool 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 }27 14 28 15 int main(int argc, char * argv[]) { … … 38 25 for (unsigned int count = 0 ; count < times ; ++count) { 39 26 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 } 41 35 } catch (EmptyException &) { 42 36 asm volatile ("# catch block (unconditional)"); … … 45 39 time_point<steady_clock> end_time = steady_clock::now(); 46 40 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; 48 42 } -
doc/theses/andrew_beach_MMath/code/cond-catch.py
red4d7c1 r1a6a6f2 13 13 14 14 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 raise25 26 27 15 def main(argv): 28 16 times = 1 … … 35 23 for count in range(times): 36 24 try: 37 cond_catch(); 25 try: 26 raise EmptyException() 27 except EmptyException as exc: 28 if not should_catch: 29 raise 38 30 except EmptyException: 39 31 pass 40 32 41 33 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.)) 43 35 44 36 -
doc/theses/andrew_beach_MMath/code/cond-fixup.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 bool 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 }24 11 25 12 int main(int argc, char * argv[]) { 26 13 unsigned int times = 1; 27 14 if (1 < argc) { 28 times = strto l(argv[1], 0p, 10);15 times = strto(argv[1], 0p, 10); 29 16 } 30 17 if (2 < argc) { 31 should_catch = strtol(argv[2], 0p, 10);18 should_catch = (unsigned int)strto(argv[2], 0p, 2); 32 19 } 33 20 … … 35 22 for (unsigned int count = 0 ; count < times ; ++count) { 36 23 try { 37 cond_catch(); 24 throwResume (empty_exception){&empty_vt}; 25 } catchResume (empty_exception * exc ; should_catch) { 26 asm volatile ("# fixup block (conditional)"); 38 27 } catchResume (empty_exception * exc) { 39 28 asm volatile ("# fixup block (unconditional)"); … … 41 30 } 42 31 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.); 44 33 } -
doc/theses/andrew_beach_MMath/code/resume-detor.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 struct WithDestructor {}; … … 17 16 void unwind_destructor(unsigned int frames) { 18 17 if (frames) { 19 20 18 WithDestructor object; 21 19 unwind_destructor(frames - 1); … … 29 27 unsigned int total_frames = 1; 30 28 if (1 < argc) { 31 times = strto l(argv[1], 0p, 10);29 times = strto(argv[1], 0p, 10); 32 30 } 33 31 if (2 < argc) { 34 total_frames = strto l(argv[2], 0p, 10);32 total_frames = strto(argv[2], 0p, 10); 35 33 } 36 34 … … 44 42 } 45 43 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.); 47 45 } -
doc/theses/andrew_beach_MMath/code/resume-empty.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 8 9 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 10 11 void unwind_empty(unsigned int frames) { 10 void nounwind_empty(unsigned int frames) { 12 11 if (frames) { 13 unwind_empty(frames - 1);12 nounwind_empty(frames - 1); 14 13 } else { 15 14 throwResume (empty_exception){&empty_vt}; … … 21 20 unsigned int total_frames = 1; 22 21 if (1 < argc) { 23 times = strto l(argv[1], 0p, 10);22 times = strto(argv[1], 0p, 10); 24 23 } 25 24 if (2 < argc) { 26 total_frames = strto l(argv[2], 0p, 10);25 total_frames = strto(argv[2], 0p, 10); 27 26 } 28 27 29 28 Time start_time = timeHiRes(); 30 for ( int count = 0 ; count < times ; ++count) {29 for (unsigned int count = 0 ; count < times ; ++count) { 31 30 try { 32 unwind_empty(total_frames);31 nounwind_empty(total_frames); 33 32 } catchResume (empty_exception *) { 34 33 asm volatile ("# fixup block"); … … 36 35 } 37 36 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.); 39 38 } -
doc/theses/andrew_beach_MMath/code/resume-finally.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 void unwind_finally(unsigned int frames) { … … 25 24 unsigned int total_frames = 1; 26 25 if (1 < argc) { 27 times = strto l(argv[1], 0p, 10);26 times = strto(argv[1], 0p, 10); 28 27 } 29 28 if (2 < argc) { 30 total_frames = strto l(argv[2], 0p, 10);29 total_frames = strto(argv[2], 0p, 10); 31 30 } 32 31 … … 40 39 } 41 40 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.); 43 42 } -
doc/theses/andrew_beach_MMath/code/resume-other.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 9 exception not_raised_exception; 8 10 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 10 11 EHM_EXCEPTION(not_raised_exception)(); 12 13 void unwind_other(unsigned int frames) { 11 void nounwind_other(unsigned int frames) { 14 12 if (frames) { 15 13 try { 16 unwind_other(frames - 1);14 nounwind_other(frames - 1); 17 15 } catchResume (not_raised_exception *) { 18 16 asm volatile ("# fixup block (stack)"); … … 27 25 unsigned int total_frames = 1; 28 26 if (1 < argc) { 29 times = strto l(argv[1], 0p, 10);27 times = strto(argv[1], 0p, 10); 30 28 } 31 29 if (2 < argc) { 32 total_frames = strto l(argv[2], 0p, 10);30 total_frames = strto(argv[2], 0p, 10); 33 31 } 34 32 … … 36 34 for (int count = 0 ; count < times ; ++count) { 37 35 try { 38 unwind_other(total_frames);36 nounwind_other(total_frames); 39 37 } catchResume (empty_exception *) { 40 38 asm volatile ("# fixup block (base)"); … … 42 40 } 43 41 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.); 45 43 } -
doc/theses/andrew_beach_MMath/code/run.sh
red4d7c1 r1a6a6f2 1 1 #!/usr/bin/env bash 2 2 3 readonly ALL_TESTS=( cond-match-{all,none} cross-{catch,finally} \4 raise-{detor,empty,finally,other})3 readonly ALL_TESTS=(raise-{empty,detor,finally,other} try-{catch,finally} cond-match-{all,none} \ 4 raise-{fixup-empty,fixup-other}) 5 5 6 6 gen-file-name() ( … … 18 18 ) 19 19 20 readonly N=${1:-5} 20 #readonly N=${1:-5} 21 readonly N=${1:-1} 21 22 readonly OUT_FILE=$(gen-file-name ${2:-run-%-$N}) 22 23 -
doc/theses/andrew_beach_MMath/code/test.sh
red4d7c1 r1a6a6f2 4 4 # test.sh LANGUAGE TEST 5 5 # Run the TEST in LANGUAGE. 6 # test.sh -a 7 # Build all tests. 6 8 # test.sh -b SOURCE_FILE... 7 9 # Build a test from SOURCE_FILE(s). 10 # test.sh -c 11 # Clean all executables. 8 12 # test.sh -v LANGUAGE TEST FILE 9 13 # View the result from TEST in LANGUAGE stored in FILE. 10 14 11 readonly ITERATIONS=1000000 # 1 000 000, one million 15 readonly ITERS_1M=1000000 # 1 000 000, one million 16 readonly ITERS_10M=10000000 # 10 000 000, ten million 17 readonly ITERS_100M=100000000 # 100 000 000, hundred million 18 readonly ITERS_1000M=1000000000 # 1 000 000 000, billion 12 19 readonly STACK_HEIGHT=100 13 20 … … 24 31 *.cfa) 25 32 # 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}" 27 34 ;; 28 35 *.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" 30 37 ;; 31 38 *.java) … … 39 46 ) 40 47 41 if [ "-b" = "$1" ]; then 48 if [ "-a" = "$1" ]; then # build all 49 for file in *.cfa *.cpp *.java; do 50 build $file 51 done 52 exit 0 53 elif [ "-b" = "$1" ]; then # build given 42 54 for file in "${@:2}"; do 43 55 build $file 44 56 done 45 57 exit 0 58 elif [ "-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 46 64 elif [ "-v" = "$1" -a 4 = "$#" ]; then 47 48 49 65 TEST_LANG="$2" 66 TEST_CASE="$3" 67 VIEW_FILE="$4" 50 68 elif [ 2 -eq "$#" ]; then 51 69 TEST_LANG="$1" … … 63 81 64 82 case "$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" 83 raise-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" 92 89 ;; 93 90 raise-detor) 94 CFAT="./throw-detor $ITER ATIONS$STACK_HEIGHT"95 CFAR="./resume-detor $ITERATIONS$STACK_HEIGHT"96 CPP="./throw-detor-cpp $ITER ATIONS$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" 97 94 JAVA=unsupported 98 95 PYTHON=unsupported 99 96 ;; 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 ;;107 97 raise-finally) 108 CFAT="./throw-finally $ITER ATIONS$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" 110 100 CPP=unsupported 111 JAVA="java ThrowFinally $ITER ATIONS$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" 113 103 ;; 114 104 raise-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 ;; 111 try-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 ;; 118 try-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 ;; 125 cond-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 ;; 132 cond-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 ;; 139 raise-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 ;; 146 raise-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" 120 152 ;; 121 153 *) … … 126 158 127 159 case "$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" >&2135 exit 2160 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 136 168 ;; 137 169 esac … … 140 172 141 173 if [ -n "$VIEW_FILE" ]; then 142 143 174 grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p' 175 exit 144 176 fi 145 177 -
doc/theses/andrew_beach_MMath/code/throw-detor.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 struct WithDestructor {}; … … 28 27 unsigned int total_frames = 1; 29 28 if (1 < argc) { 30 times = strto l(argv[1], 0p, 10);29 times = strto(argv[1], 0p, 10); 31 30 } 32 31 if (2 < argc) { 33 total_frames = strto l(argv[2], 0p, 10);32 total_frames = strto(argv[2], 0p, 10); 34 33 } 35 34 … … 43 42 } 44 43 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.); 46 45 } -
doc/theses/andrew_beach_MMath/code/throw-detor.cpp
red4d7c1 r1a6a6f2 4 4 #include <exception> 5 5 #include <iostream> 6 #include <iomanip> 6 7 8 using namespace std; 7 9 using namespace std::chrono; 8 10 … … 44 46 time_point<steady_clock> end_time = steady_clock::now(); 45 47 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; 47 49 } -
doc/theses/andrew_beach_MMath/code/throw-empty.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 8 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 10 9 11 10 void unwind_empty(unsigned int frames) { … … 21 20 unsigned int total_frames = 1; 22 21 if (1 < argc) { 23 times = strto l(argv[1], 0p, 10);22 times = strto(argv[1], 0p, 10); 24 23 } 25 24 if (2 < argc) { 26 total_frames = strto l(argv[2], 0p, 10);25 total_frames = strto(argv[2], 0p, 10); 27 26 } 28 27 … … 36 35 } 37 36 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.); 39 38 } -
doc/theses/andrew_beach_MMath/code/throw-empty.cpp
red4d7c1 r1a6a6f2 4 4 #include <exception> 5 5 #include <iostream> 6 #include <iomanip> 6 7 8 using namespace std; 7 9 using namespace std::chrono; 8 10 … … 37 39 time_point<steady_clock> end_time = steady_clock::now(); 38 40 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; 40 42 } -
doc/theses/andrew_beach_MMath/code/throw-empty.py
red4d7c1 r1a6a6f2 33 33 34 34 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.)) 36 36 37 37 -
doc/theses/andrew_beach_MMath/code/throw-finally.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 8 9 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 10 unsigned int frames; // use global because of gcc thunk problem 10 11 11 void unwind_finally(unsigned int frames) {12 void unwind_finally(unsigned int dummy) { 12 13 if (frames) { 14 frames -= 1; 13 15 try { 14 unwind_finally( frames - 1);16 unwind_finally(42); 15 17 } finally { 16 18 asm volatile ("# finally block"); 17 19 } 18 20 } else { 21 dummy = 42; 19 22 throw (empty_exception){&empty_vt}; 20 23 } … … 25 28 unsigned int total_frames = 1; 26 29 if (1 < argc) { 27 times = strto l(argv[1], 0p, 10);30 times = strto(argv[1], 0p, 10); 28 31 } 29 32 if (2 < argc) { 30 total_frames = strto l(argv[2], 0p, 10);33 total_frames = strto(argv[2], 0p, 10); 31 34 } 35 frames = total_frames; 32 36 33 37 Time start_time = timeHiRes(); 34 38 for (int count = 0 ; count < times ; ++count) { 35 39 try { 36 unwind_finally( total_frames);40 unwind_finally(42); 37 41 } catch (empty_exception *) { 38 42 asm volatile ("# catch block"); … … 40 44 } 41 45 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.); 43 47 } -
doc/theses/andrew_beach_MMath/code/throw-finally.py
red4d7c1 r1a6a6f2 36 36 37 37 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.)) 39 39 40 40 -
doc/theses/andrew_beach_MMath/code/throw-other.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(empty_exception)(); 7 exception empty_exception; 8 vtable(empty_exception) empty_vt; 9 exception not_raised_exception; 8 10 9 EHM_VIRTUAL_TABLE(empty_exception, empty_vt); 11 unsigned int frames; // use global because of gcc thunk problem 10 12 11 EHM_EXCEPTION(not_raised_exception)(); 12 13 void unwind_other(unsigned int frames) { 13 void unwind_other(unsigned int dummy) { 14 14 if (frames) { 15 frames -= 1; 15 16 try { 16 unwind_other( frames - 1);17 unwind_other(42); 17 18 } catch (not_raised_exception *) { 18 19 asm volatile ("# catch block (stack)"); 19 20 } 20 21 } else { 22 dummy = 42; 21 23 throw (empty_exception){&empty_vt}; 22 24 } … … 27 29 unsigned int total_frames = 1; 28 30 if (1 < argc) { 29 times = strto l(argv[1], 0p, 10);31 times = strto(argv[1], 0p, 10); 30 32 } 31 33 if (2 < argc) { 32 total_frames = strto l(argv[2], 0p, 10);34 total_frames = strto(argv[2], 0p, 10); 33 35 } 36 frames = total_frames; 34 37 35 38 Time start_time = timeHiRes(); 36 39 for (int count = 0 ; count < times ; ++count) { 37 40 try { 38 unwind_other( total_frames);41 unwind_other(42); 39 42 } catch (empty_exception *) { 40 43 asm volatile ("# catch block (base)"); … … 42 45 } 43 46 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.); 45 48 } -
doc/theses/andrew_beach_MMath/code/throw-other.cpp
red4d7c1 r1a6a6f2 4 4 #include <exception> 5 5 #include <iostream> 6 #include <iomanip> 6 7 8 using namespace std; 7 9 using namespace std::chrono; 8 10 … … 43 45 time_point<steady_clock> end_time = steady_clock::now(); 44 46 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; 46 48 } -
doc/theses/andrew_beach_MMath/code/throw-other.py
red4d7c1 r1a6a6f2 40 40 41 41 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.)) 43 43 44 44 -
doc/theses/andrew_beach_MMath/code/throw-with.py
red4d7c1 r1a6a6f2 43 43 44 44 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.)) 46 46 47 47 -
doc/theses/andrew_beach_MMath/code/try-catch.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(not_raised_exception)(); 8 9 EHM_VIRTUAL_TABLE(not_raised_exception, not_vt); 7 exception not_raised_exception; 8 vtable(not_raised_exception) not_vt; 10 9 11 10 int main(int argc, char * argv[]) { … … 13 12 volatile bool should_throw = false; 14 13 if (1 < argc) { 15 times = strto l(argv[1], 0p, 10);14 times = strto(argv[1], 0p, 10); 16 15 } 17 16 … … 28 27 } 29 28 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.); 31 30 } -
doc/theses/andrew_beach_MMath/code/try-catch.cpp
red4d7c1 r1a6a6f2 4 4 #include <exception> 5 5 #include <iostream> 6 #include <iomanip> 6 7 8 using namespace std; 7 9 using namespace std::chrono; 8 10 … … 29 31 time_point<steady_clock> end_time = steady_clock::now(); 30 32 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; 32 34 } -
doc/theses/andrew_beach_MMath/code/try-catch.py
red4d7c1 r1a6a6f2 23 23 24 24 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.)) 26 26 27 27 -
doc/theses/andrew_beach_MMath/code/try-finally.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(not_raised_exception)(); 8 9 EHM_VIRTUAL_TABLE(not_raised_exception, not_vt); 7 exception not_raised_exception; 8 vtable(not_raised_exception) not_vt; 10 9 11 10 int main(int argc, char * argv[]) { … … 13 12 volatile bool should_throw = false; 14 13 if (1 < argc) { 15 times = strto l(argv[1], 0p, 10);14 times = strto(argv[1], 0p, 10); 16 15 } 17 16 … … 28 27 } 29 28 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.); 31 30 } -
doc/theses/andrew_beach_MMath/code/try-finally.py
red4d7c1 r1a6a6f2 22 22 23 23 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.)) 25 25 26 26 -
doc/theses/andrew_beach_MMath/code/try-resume.cfa
red4d7c1 r1a6a6f2 3 3 #include <exception.hfa> 4 4 #include <fstream.hfa> 5 #include <stdlib.hfa> 5 #include <stdlib.hfa> // strto 6 6 7 EHM_EXCEPTION(not_raised_exception)();7 exception not_raised_exception; 8 8 9 9 int main(int argc, char * argv[]) { … … 11 11 unsigned int total_frames = 1; 12 12 if (1 < argc) { 13 times = strto l(argv[1], 0p, 10);13 times = strto(argv[1], 0p, 10); 14 14 } 15 15 if (2 < argc) { 16 total_frames = strto l(argv[2], 0p, 10);16 total_frames = strto(argv[2], 0p, 10); 17 17 } 18 18 … … 26 26 } 27 27 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.); 29 29 } -
doc/theses/andrew_beach_MMath/conclusion.tex
red4d7c1 r1a6a6f2 4 4 5 5 In the previous chapters this thesis presents the design and implementation 6 of \CFA's exception handling mechanism (EHM).6 of \CFA's EHM. 7 7 Both the design and implementation are based off of tools and techniques 8 8 developed 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, 10 like conditional catch. 10 11 11 12 The resulting features cover all of the major use cases of the most popular 12 13 termination EHMs of today, along with reintroducing resumption exceptions and 13 creating some new features that fix with \CFA's larger programming patterns. 14 creating some new features that fit with \CFA's larger programming patterns, 15 such as virtuals independent of traditional objects. 14 16 15 The implementation has been tested and compared to other implementations. 17 The implementation has been tested through a set of small but interesting micro-benchmarks 18 and compared to other implementations. 16 19 The results, while not cutting edge, are good enough for prototyping, which 17 is \CFA's stage of development.20 is \CFA's current stage of development. 18 21 19 This i s a valuable new feature for \CFA in its own right but also serves20 as a tool (and motivation)for other developments in the language.22 This initial EHM is a valuable new feature for \CFA in its own right but also serves 23 as a tool and motivation for other developments in the language. -
doc/theses/andrew_beach_MMath/future.tex
red4d7c1 r1a6a6f2 2 2 \label{c:future} 3 3 4 The following discussion covers both missing language features that affected my 5 work and research based improvements. 6 4 7 \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 8 9 \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 systemlargely in10 unimplemented features (including several broken components) 11 that I had to workaround while building an EHM largely in 11 12 the \CFA language (some C components). The following are a few of these 12 13 issues, and once implemented/fixed, how they would affect the exception system. … … 14 15 \item 15 16 The 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. 17 hand-crafted assembly statements for each architecture, where the 18 ARM processor was just added. 19 % The existing compilers cannot translate that for other platforms and those 20 % sections must be ported by hand to 21 Supporting more hardware architectures in a general way is important. 20 22 \item 21 23 Due to a type-system problem, the catch clause cannot bind the exception to a … … 27 29 @return@, \etc. The reason is that current code generation hoists a handler 28 30 into 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 32 in the lexical scope of the @try@ statement, but the closure does not capture 33 local control-flow points so it cannot perform non-local transfers in the 34 hoisted function. 32 35 \item 33 36 There is no detection of colliding unwinds. It is possible for clean-up code 34 37 run during an unwind to trigger another unwind that escapes the clean-up code 35 38 itself; 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 not37 even detected and the first unwind will simply beforgotten, often leaving39 cancellation. There do exist ways to handle this case, but currently there is no 40 detection and the first unwind is simply forgotten, often leaving 38 41 it in a bad state. 39 42 \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 new42 quality of life upgrades that can be made with time.43 Finally, the exception system has not have a lot programmer testing. 44 More time with encouraged usage will reveal new 45 quality of life upgrades that can be made. 43 46 \end{itemize} 44 47 … … 47 50 project, but was thrust upon it to do exception inheritance; hence, only 48 51 minimal work is done. A draft for a complete virtual system is available but 49 it isnot finalized. A future \CFA project is to complete that work and then52 not finalized. A future \CFA project is to complete that work and then 50 53 update the exception system that uses the current version. 51 54 … … 53 56 exception traits. The most important one is an assertion to check one virtual 54 57 type is a child of another. This check precisely captures many of the 55 c orrectness requirements.58 current ad-hoc correctness requirements. 56 59 57 60 The full virtual system might also include other improvement like associated 58 61 types to allow traits to refer to types not listed in their header. This 59 62 feature allows exception traits to not refer to the virtual-table type 60 explicitly , removing the need for the current interface macros.63 explicitly. %, removing the need for the current interface macros. 61 64 62 65 \section{Additional Raises} … … 93 96 Checked exceptions make exceptions part of a function's type by adding an 94 97 exception signature. An exception signature must declare all checked 95 exceptions that could propagate from the function (either because they were96 raised inside the function or came from a sub-function). This improves safety98 exceptions that could propagate from the function, either because they were 99 raised inside the function or a call to a sub-function. This improves safety 97 100 by making sure every checked exception is either handled or consciously 98 101 passed on. 99 102 100 103 However checked exceptions were never seriously considered for this project 101 because they have significant trade-offs in usab lity and code reuse in104 because they have significant trade-offs in usability and code reuse in 102 105 exchange for the increased safety. 103 106 These trade-offs are most problematic when trying to pass exceptions through … … 129 132 not support a successful-exiting stack-search without doing an unwind. 130 133 Workarounds are possible but awkward. Ideally an extension to libunwind could 131 be made, but that would either require separate maintenance or gain enough132 support to have it folded into the standard.134 be made, but that would either require separate maintenance or gaining enough 135 support to have it folded into the code base. 133 136 134 137 Also new techniques to skip previously searched parts of the stack need to be … … 158 161 to leave the handler. 159 162 Currently, mimicking this behaviour in \CFA is possible by throwing a 160 termination inside a resumption handler.163 termination exception inside a resumption handler. 161 164 162 165 % Maybe talk about the escape; and escape CONTROL_STMT; statements or how -
doc/theses/andrew_beach_MMath/performance.tex
red4d7c1 r1a6a6f2 3 3 4 4 Performance is of secondary importance for most of this project. 5 Instead, the focus is to get the features working. The only performance5 Instead, the focus was to get the features working. The only performance 6 6 requirement is to ensure the tests for correctness run in a reasonable 7 amount of time. 7 amount of time. Hence, a few basic performance tests were performed to 8 check this requirement. 8 9 9 10 \section{Test Set-Up} … … 14 15 C++ is the most comparable language because both it and \CFA use the same 15 16 framework, 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 and17 In fact, the comparison is almost entirely a quality of implementation. 18 Specifically, \CFA's EHM has had significantly less time to be optimized and 18 19 does not generate its own assembly. It does have a slight advantage in that 19 20 there are some features it handles directly instead of through utility functions, 20 but otherwise \Cpp hasa significant advantage.21 22 Java is a nother very popular language with similar termination semantics.23 It is implemented in a very different environment, a virtual machine with21 but otherwise \Cpp should have a significant advantage. 22 23 Java is a popular language with similar termination semantics, but 24 it is implemented in a very different environment, a virtual machine with 24 25 garbage collection. 25 26 It also implements the @finally@ clause on @try@ blocks allowing for a direct 26 27 feature-to-feature comparison. 27 As with \Cpp, Java's implementation is mature, optimiz ations28 As with \Cpp, Java's implementation is mature, optimized 28 29 and has extra features. 29 30 30 Python is used as an alternative point ofcomparison because of the \CFA EHM's31 Python is used as an alternative comparison because of the \CFA EHM's 31 32 current performance goals, which is not to be prohibitively slow while the 32 33 features are designed and examined. Python has similar performance goals for … … 36 37 resumption exceptions. Even the older programming languages with resumption 37 38 seem 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. 39 So instead, resumption is compared to its simulation in other programming 40 languages using fixup functions that are explicitly passed for correction or 41 logging purposes. 42 % So instead, resumption is compared to a less similar but much more familiar 43 %feature, termination exceptions. 40 44 41 45 All tests are run inside a main loop that repeatedly performs a test. 42 46 This approach avoids start-up or tear-down time from 43 47 affecting the timing results. 44 Each test is run a million times.45 The Java versions of the test run this loop an extra1000 times before46 beginning t oactual test to ``warm-up" the JVM.48 Each test is run a N times (configurable from the command line). 49 The Java tests runs the main loop 1000 times before 50 beginning the actual test to ``warm-up" the JVM. 47 51 48 52 Timing is done internally, with time measured immediately before and … … 66 70 67 71 The tests are compiled with gcc-10 for \CFA and g++-10 for \Cpp. Java is 68 compiled with 11.0.11. Python with3.8. The tests were run on:72 compiled with version 11.0.11. Python with version 3.8. The tests were run on: 69 73 \begin{itemize}[nosep] 70 74 \item … … 73 77 AMD 6380 Abu Dhabi 16-core 4$\times$socket \lstinline{@} 2.5 GHz running Linux v5.11.0-25 74 78 \end{itemize} 79 Two kinds of hardware architecture allows discriminating any implementation and 80 architectural effects. 81 75 82 76 83 % We don't use catch-alls but if we did: … … 84 91 85 92 \paragraph{Raise and Handle} 86 Th e first group measures the cost of a try statement when exceptions are raised87 and \emph{the stack is unwound}. Each test has has a repeating function like 88 the following89 \begin{ cfa}93 This group measures the cost of a try statement when exceptions are raised and 94 the stack is unwound (termination) or not unwound (resumption). Each test has 95 has a repeating function like the following 96 \begin{lstlisting}[language=CFA,{moredelim=**[is][\color{red}]{@}{@}}] 90 97 void unwind_empty(unsigned int frames) { 91 98 if (frames) { 92 unwind_empty(frames - 1);99 @unwind_empty(frames - 1);@ // AUGMENTED IN OTHER EXPERIMENTS 93 100 } else throw (empty_exception){&empty_vt}; 94 101 } 95 \end{ cfa}96 which is called M times, where each call recurses to a depth of N, an102 \end{lstlisting} 103 which is called N times, where each call recurses to a depth of R (configurable from the command line), an 97 104 exception is raised, the stack is a unwound, and the exception caught. 98 105 \begin{itemize}[nosep] 99 106 \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) 107 For termination, this test measures the cost of raising (stack walking) an 108 exception through empty stack frames from the bottom of the recursion to an 109 empty handler, and unwinding the stack. (see above code) 110 111 \medskip 112 For resumption, this test measures the same raising cost but does not unwind 113 the stack. For languages without resumption, a fixup function is to the bottom 114 of the recursion and called to simulate a fixup operation at that point. 115 \begin{cfa} 116 void 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} 125 where the passed fixup function is: 126 \begin{cfa} 127 void raised(int & fixup) { 128 fixup = 42; 129 } 130 \end{cfa} 131 For comparison, a \CFA version passing a function is also included. 102 132 \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) { 133 This test measures the cost of raising an exception through non-empty frames, 134 where each frame has an object requiring destruction, from the bottom of the 135 recursion to an empty handler. Hence, there are N destructor calls during 136 unwinding. 137 138 \medskip 139 This test is not meaningful for resumption because the stack is only unwound as 140 the recursion returns. 141 \begin{cfa} 109 142 WithDestructor object; 110 unwind_ empty(frames - 1);143 unwind_destructor(frames - 1); 111 144 \end{cfa} 112 145 \item Finally: 113 146 This 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) { 147 clause on the front side of the recursion and running the empty finally clauses 148 during stack unwinding from the bottom of the recursion to an empty handler. 149 \begin{cfa} 118 150 try { 119 151 unwind_finally(frames - 1); 120 152 } finally {} 121 153 \end{cfa} 154 155 \medskip 156 This test is not meaningful for resumption because the stack is only unwound as 157 the recursion returns. 122 158 \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) { 159 For termination, this test is like the finally test but the try block has a 160 catch clause for an exception that is not raised, so catch matching is executed 161 during stack unwinding but the match never successes until the catch at the 162 bottom of the recursion. 163 \begin{cfa} 129 164 try { 130 165 unwind_other(frames - 1); 131 166 } catch (not_raised_exception *) {} 132 167 \end{cfa} 168 169 \medskip 170 For resumption, this test measures the same raising cost but does not unwind 171 the stack. For languages without resumption, the same fixup function is passed 172 and called. 133 173 \end{itemize} 134 174 135 \paragraph{ Cross Try Statement}136 Th e nextgroup measures just the cost of executing a try statement so175 \paragraph{Try/Handle/Finally Statement} 176 This group measures just the cost of executing a try statement so 137 177 \emph{there is no stack unwinding}. Hence, the program main loops N times 138 178 around: … … 143 183 \begin{itemize}[nosep] 144 184 \item Handler: 145 The try statement has a handler .185 The try statement has a handler (catch/resume). 146 186 \item Finally: 147 The try statement replaces the handler witha finally clause.187 The try statement has a finally clause. 148 188 \end{itemize} 149 189 150 190 \paragraph{Conditional Matching} 151 This finalgroup measures the cost of conditional matching.191 This group measures the cost of conditional matching. 152 192 Only \CFA implements the language level conditional match, 153 the other languages m ust mimic with an ``unconditional" match (it still154 checks the exception's type) and conditional re-raise if it was not supposed193 the other languages mimic with an ``unconditional" match (it still 194 checks the exception's type) and conditional re-raise if it is not suppose 155 195 to handle that exception. 156 196 \begin{center} … … 180 220 The condition is always false. (Never matches or always re-raises.) 181 221 \end{itemize} 222 223 \medskip 224 \noindent 225 All omitted test code for other languages is functionally identical to the \CFA 226 tests or simulated, and available online~\cite{CforallExceptionBenchmarks}. 182 227 183 228 %\section{Cost in Size} … … 192 237 193 238 \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 } 239 One result not directly related to \CFA but important to keep in 240 mind is that, for exceptions, the standard intuition about which languages 241 should 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 243 rarely considered to be the common case, the more optimized languages 244 make that case expense. In addition, languages with high-level 245 representations have a much easier time scanning the stack as there is less 246 to decode. 247 248 Tables~\ref{t:PerformanceTermination} and~\ref{t:PerformanceResumption} show 249 the test results for termination and resumption, respectively. In cases where 250 a 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 252 effects because the JIT corrupted the test (marked N/C). No workaround was 253 possible~\cite{Dice21}. To get experiments in the range of 1--100 seconds, the 254 number of times an experiment is run (N) is varied (N is marked beside each 255 experiment, e.g., 1M $\Rightarrow$ 1 million test iterations). 256 257 An anomaly exists with gcc nested functions used as thunks for implementing 258 much of the \CFA EHM. If a nested-function closure captures local variables in 259 its lexical scope, performance dropped by a factor of 10. Specifically, in try 260 statements of the form: 261 \begin{cfa} 262 try { 263 unwind_other(frames - 1); 264 } catch (not_raised_exception *) {} 265 \end{cfa} 266 the try block is hoisted into a nested function and the variable @frames@ is 267 the local parameter to the recursive function, which triggers the anomaly. The 268 workaround is to remove the recursion parameter and make it a global variable 269 that 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} 276 To make comparisons fair, a dummy parameter is added and the dummy value passed 277 in the recursion. Note, nested functions in gcc are rarely used (if not 278 completely unknown) and must follow the C calling convention, unlike \Cpp 279 lambdas, so it is not surprising if there are performance issues efficiently 280 capturing 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. 202 285 203 286 % Raw Data: … … 235 318 % Match None & 0.0 & 0.0 & 9476060146 & 0.0 & 0.0 \\ 236 319 237 \begin{tabular}{|l|c c c c c|}238 \hline239 & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\240 \hline241 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 \hline250 \end{tabular}251 252 320 % run-plg7a-a.sat 253 321 % --------------- … … 284 352 % Match None & 0.0 & 0.0 & 7829059869 & 0.0 & 0.0 \\ 285 353 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|}} 288 359 \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} 362 N\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 365 Throw Empty (1M) & 3.4 & 2.8 & 18.3 & 23.4 & 3.7 & 3.2 & 15.5 & 14.8 \\ 366 Throw D'tor (1M) & 48.4 & 23.6 & N/A & N/A & 64.2 & 29.0 & N/A & N/A \\ 367 Throw Finally (1M) & 3.4* & N/A & 17.9 & 29.0 & 4.1* & N/A & 15.6 & 19.0 \\ 368 Throw Other (1M) & 3.6* & 23.2 & 18.2 & 32.7 & 4.0* & 24.5 & 15.5 & 21.4 \\ 369 Try/Catch (100M) & 6.0 & 0.9 & N/C & 37.4 & 10.0 & 0.8 & N/C & 32.2 \\ 370 Try/Finally (100M) & 0.9 & N/A & N/C & 44.1 & 0.8 & N/A & N/C & 37.3 \\ 371 Match All (10M) & 32.9 & 20.7 & 13.4 & 4.9 & 36.2 & 24.5 & 12.0 & 3.1 \\ 372 Match None (10M) & 32.7 & 50.3 & 11.0 & 5.1 & 36.3 & 71.9 & 12.3 & 4.2 \\ 299 373 \hline 300 374 \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} 387 N\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 390 Resume Empty (10M) & 3.8/3.5 & 14.7 & 2.3 & 176.1 & 0.3/0.1 & 8.9 & 1.2 & 119.9 \\ 391 Resume Other (10M) & 4.0*/0.1* & 21.9 & 6.2 & 381.0 & 0.3*/0.1* & 13.2 & 5.0 & 290.7 \\ 392 Try/Resume (100M) & 8.8 & N/A & N/A & N/A & 12.3 & N/A & N/A & N/A \\ 393 Match All (10M) & 0.3 & N/A & N/A & N/A & 0.3 & N/A & N/A & N/A \\ 394 Match 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 399 As stated, the performance tests are not attempting to compare exception 400 handling across languages. The only performance requirement is to ensure the 401 \CFA EHM implementation runs in a reasonable amount of time, given its 402 constraints. In general, the \CFA implement did very well. Each of the tests is 403 analysed. 404 \begin{description} 405 \item[Throw/Resume Empty] 406 For termination, \CFA is close to \Cpp, where other languages have a higher cost. 407 408 For resumption, \CFA is better than the fixup simulations in the other languages, except Java. 409 The \CFA results on the ARM computer for both resumption and function simulation are particularly low; 410 I have no explanation for this anomaly, except the optimizer has managed to remove part of the experiment. 411 Python has a high cost for passing the lambda during the recursion. 412 413 \item[Throw D'tor] 414 For termination, \CFA is twice the cost of \Cpp. 415 The 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 419 same for termination and resumption. 420 421 \item[Throw/Resume Other] 422 For termination, \CFA is better than the other languages. 423 424 For resumption, \CFA is equal to or better the other languages. 425 Again, the \CFA results on the ARM computer for both resumption and function simulation are particularly low. 426 Python has a high cost for passing the lambda during the recursion. 427 428 \item[Try/Catch/Resume] 429 For termination, installing a try statement is more expressive than \Cpp 430 because the try components are hoisted into local functions. At runtime, these 431 functions are than passed to libunwind functions to set up the try statement. 432 \Cpp zero-cost try-entry accounts for its performance advantage. 433 434 For resumption, there are similar costs to termination to set up the try 435 statement but libunwind is not used. 436 437 \item[Try/Finally] 438 Setting up a try finally is less expensive in \CFA than setting up handlers, 439 and is significantly less than other languages. 440 441 \item[Throw/Resume Match All] 442 For termination, \CFA is close to the other language simulations. 443 444 For resumption, the stack unwinding is much faster because it does not use 445 libunwind. Instead resumption is just traversing a linked list with each node 446 being the next stack frame with the try block. 447 448 \item[Throw/Resume Match None] 449 The same results as for Match All. 450 \end{description} 451 452 \begin{comment} 453 This observation means that while \CFA does not actually keep up with Python in 454 every case, it is usually no worse than roughly half the speed of \Cpp. This 455 performance is good enough for the prototyping purposes of the project. 314 456 315 457 The test case where \CFA falls short is Raise Other, the case where the 316 458 stack is unwound including a bunch of non-matching handlers. 317 459 This slowdown seems to come from missing optimizations. 318 319 Importantly, there is a huge slowdown in \Cpp's results bringing that brings320 \CFA's performance back in that roughly half speed area. However many other321 \CFA benchmarks increase their run-time by a similar amount falling far322 behind their \Cpp counter-parts.323 460 324 461 This suggests that the performance issue in Raise Other is just an … … 364 501 The difference in relative performance does show that there are savings to 365 502 be made by performing the check without catching the exception. 503 \end{comment} 504 505 506 \begin{comment} 507 From: Dave Dice <dave.dice@oracle.com> 508 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca> 509 Subject: Re: [External] : JIT 510 Date: 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 524 There's quite a bit of optimization magic behind the HotSpot curtains for 525 try-finally. (I sound like the proverbial broken record (:>)). 526 527 In many cases we can determine that the try block can't throw any exceptions, 528 so we can elide all try-finally plumbing. In other cases, we can convert the 529 try-finally to normal if-then control flow, in the case where the exception is 530 thrown into the same method. This makes exceptions _almost cost-free. If we 531 actually need to "physically" rip down stacks, then things get expensive, 532 impacting both the throw cost, and inhibiting other useful optimizations at the 533 catch point. Such "true" throws are not just expensive, they're _very 534 expensive. The extremely aggressive inlining used by the JIT helps, because we 535 can convert cases where a heavy rip-down would normally needed back into simple 536 control flow. 537 538 Other quirks involve the thrown exception object. If it's never accessed then 539 we're apply a nice set of optimizations to avoid its construction. If it's 540 accessed but never escapes the catch frame (common) then we can also cheat. 541 And if we find we're hitting lots of heavy rip-down cases, the JIT will 542 consider recompilation - better inlining -- to see if we can merge the throw 543 and catch into the same physical frame, and shift to simple branches. 544 545 In your example below, System.out.print() can throw, I believe. (I could be 546 wrong, but most IO can throw). Native calls that throw will "unwind" normally 547 in C++ code until they hit the boundary where they reenter java emitted code, 548 at which point the JIT-ed code checks for a potential pending exception. So in 549 a sense the throw point is implicitly after the call to the native method, so 550 we can usually make those cases efficient. 551 552 Also, when we're running in the interpreter and warming up, we'll notice that 553 the == 42 case never occurs, and so when we start to JIT the code, we elide the 554 call to System.out.print(), replacing it (and anything else which appears in 555 that if x == 42 block) with a bit of code we call an "uncommon trap". I'm 556 presuming we encounter 42 rarely. So if we ever hit the x == 42 case, control 557 hits the trap, which triggers synchronous recompilation of the method, this 558 time with the call to System.out.print() and, because of that, we now to adapt 559 the new code to handle any traps thrown by print(). This is tricky stuff, as 560 we may need to rebuild stack frames to reflect the newly emitted method. And 561 we have to construct a weird bit of "thunk" code that allows us to fall back 562 directly into the newly emitted "if" block. So there's a large one-time cost 563 when we bump into the uncommon trap and recompile, and subsequent execution 564 might get slightly slower as the exception could actually be generated, whereas 565 before we hit the trap, we knew the exception could never be raised. 566 567 Oh, and things also get expensive if we need to actually fill in the stack 568 trace associated with the exception object. Walking stacks is hellish. 569 570 Quite a bit of effort was put into all this as some of the specjvm benchmarks 571 showed significant benefit. 572 573 It's hard to get sensible measurements as the JIT is working against you at 574 every turn. What's good for the normal user is awful for anybody trying to 575 benchmark. Also, all the magic results in fairly noisy and less reproducible 576 results. 577 578 Regards 579 Dave 580 581 p.s., I think I've mentioned this before, but throwing in C++ is grim as 582 unrelated throws in different threads take common locks, so nothing scales as 583 you might expect. 584 \end{comment} -
doc/theses/andrew_beach_MMath/uw-ethesis.bib
red4d7c1 r1a6a6f2 2 2 % For use with BibTeX 3 3 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} 11 9 } 12 10 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}}, 19 16 } 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 }
Note: See TracChangeset
for help on using the changeset viewer.