Changes in / [8614140:79ba50c]
- Files:
-
- 3 added
- 9 deleted
- 19 edited
-
doc/theses/mike_brooks_MMath/Makefile (modified) (3 diffs)
-
doc/theses/mike_brooks_MMath/array.tex (modified) (52 diffs)
-
doc/theses/mike_brooks_MMath/background.tex (modified) (2 diffs)
-
doc/theses/mike_brooks_MMath/pictures/ar-bchk.pdf (deleted)
-
doc/theses/mike_brooks_MMath/pictures/ar-bchk.xlsx (deleted)
-
doc/theses/mike_brooks_MMath/plots/list-zoomout-noshuf.gp (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/plots/list-zoomout-shuf.gp (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/plots/string-peq-cppemu.gp (modified) (3 diffs)
-
doc/theses/mike_brooks_MMath/plots/string-peq-sharing.gp (modified) (3 diffs)
-
doc/theses/mike_brooks_MMath/plots/string-pta-sharing.gp (modified) (3 diffs)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/Makefile (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/control.c (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/control.cc (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/control.cfa (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/treatment.c (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/treatment.cc (deleted)
-
doc/theses/mike_brooks_MMath/programs/ar-bchk/treatment.cfa (deleted)
-
doc/theses/mike_brooks_MMath/programs/array-boundcheck-removal-matmul.cfa (added)
-
doc/theses/mike_brooks_MMath/programs/array-boundcheck-removal-stdvec.cpp (added)
-
doc/theses/mike_brooks_MMath/programs/array-boundcheck-removal.cfa (added)
-
doc/theses/mike_brooks_MMath/programs/hello-accordion.cfa (modified) (2 diffs)
-
doc/theses/mike_brooks_MMath/programs/hello-array.cfa (modified) (3 diffs)
-
doc/theses/mike_brooks_MMath/programs/school1 (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/programs/school1.out (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/programs/school2 (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/programs/school2.out (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/string.tex (modified) (64 diffs)
-
doc/theses/mike_brooks_MMath/uw-ethesis-frontpgs.tex (modified) (1 diff)
-
libcfa/src/collections/array.hfa (modified) (3 diffs)
-
tests/array-collections/array-md-sbscr-cases.cfa (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mike_brooks_MMath/Makefile
r8614140 r79ba50c 11 11 BibRep = ../../bibliography 12 12 13 strip-top-dir = $(foreach p,$1,$(patsubst %/,%,$(subst $(firstword $(subst /, ,$(p)))/,, $(p))))14 15 .SUFFIXES: # disable make built-in rules16 17 13 TeXSRC = ${wildcard *.tex} 18 14 PicSRC = ${notdir ${wildcard ${Pictures}/*.png}} ${notdir ${wildcard ${Pictures}/*.fig}} … … 23 19 PgmSRC = ${notdir ${wildcard ${Programs}/*}} 24 20 RunPgmSRC = ${notdir ${wildcard ${Programs}/*.run.*}} 25 NondemoPgmSRC = ${call strip-top-dir,${wildcard ${Programs}/*/*.c*}}26 21 BibSRC = ${wildcard *.bib} 27 22 … … 62 57 # File Dependencies 63 58 64 ${DOCUMENT}: ${TeXSRC} $(RunPgmOut) ${DemoPgmOut} ${ NondemoPgmSRC} ${PlotSRC} ${PicSRC} ${BibSRC} ${BibRep}/pl.bib ${LaTMac}/common.tex Makefile | ${Build}59 ${DOCUMENT}: ${TeXSRC} $(RunPgmOut) ${DemoPgmOut} ${PlotSRC} ${PicSRC} ${BibSRC} ${BibRep}/pl.bib ${LaTMac}/common.tex Makefile | ${Build} 65 60 echo ${PicSRC} 66 61 echo ${GraphSRC_OLD} -
doc/theses/mike_brooks_MMath/array.tex
r8614140 r79ba50c 2 2 \label{c:Array} 3 3 4 Arrays in C are possibly the single most misunderstood and incorrectly used feature in the language \see{\VRef{s:Array}}, resulting in the largest proportion of runtime errors and security violations.4 Arrays in C are possibly the single most misunderstood and incorrectly used feature in the language, resulting in the largest proportion of runtime errors and security violations. 5 5 This chapter describes the new \CFA language and library features that introduce a length-checked array type, @array@, to the \CFA standard library~\cite{Cforall}. 6 6 … … 13 13 \label{s:ArrayIntro} 14 14 15 The new \CFA array is declared by instantiating the generic @array@ type, much like instantiating any other standard-library generic type (such as \CC @vector@), using a new style of generic parameter. 15 The new \CFA array is declared by instantiating the generic @array@ type, 16 much like instantiating any other standard-library generic type (such as \CC @vector@), 17 though using a new style of generic parameter. 16 18 \begin{cfa} 17 19 @array( float, 99 )@ x; $\C[2.5in]{// x contains 99 floats}$ … … 22 24 void f( @array( float, 42 )@ & p ) {} $\C{// p accepts 42 floats}$ 23 25 f( x ); $\C{// statically rejected: type lengths are different, 99 != 42}$ 24 25 26 test2.cfa:3:1 error: Invalid application of existing declaration(s) in expression. 26 27 Applying untyped: Name: f ... to: Name: x … … 36 37 g( x, 0 ); $\C{// T is float, N is 99, dynamic subscript check succeeds}$ 37 38 g( x, 1000 ); $\C{// T is float, N is 99, dynamic subscript check fails}$ 38 39 39 Cforall Runtime error: subscript 1000 exceeds dimension range [0,99) $for$ array 0x555555558020. 40 40 \end{cfa} … … 92 92 is a sufficient postcondition. 93 93 In an imperative language like C and \CFA, it is also necessary to discuss side effects, for which an even heavier formalism, like separation logic, is required. 94 Secondly : ...bash Rust.95 ...cite the crap out of these claims.94 Secondly, TODO: bash Rust. 95 % TODO: cite the crap out of these claims. 96 96 \end{comment} 97 97 … … 110 110 forall( T & | sized(T) ) 111 111 T * alloc() { 112 return @(T *)@malloc( @sizeof(T)@ ); // C malloc112 return @(T *)@malloc( @sizeof(T)@ ); 113 113 } 114 114 \end{cfa} … … 132 132 The loops follow the familiar pattern of using the variable @dim@ to iterate through the arrays. 133 133 Most importantly, the type system implicitly captures @dim@ at the call of @f@ and makes it available throughout @f@ as @N@. 134 The example shows @dim@ adapting into a type-system managed length at the declarations of @x@, @y@, and @result@ ; @N@ adapting in the same way at @f@'s loop bound;and a pass-thru use of @dim@ at @f@'s declaration of @ret@.134 The example shows @dim@ adapting into a type-system managed length at the declarations of @x@, @y@, and @result@, @N@ adapting in the same way at @f@'s loop bound, and a pass-thru use of @dim@ at @f@'s declaration of @ret@. 135 135 Except for the lifetime-management issue of @result@, \ie explicit @free@, this program has eliminated both the syntactic and semantic problems associated with C arrays and their usage. 136 136 The result is a significant improvement in safety and usability. … … 148 148 \end{itemize} 149 149 150 \VRef[Figure]{f:TemplateVsGenericType} shows @N@ is not the same as a @size_t@ declaration in a \CC \lstinline[language=C++]{template}.\footnote{ 151 The \CFA program requires a snapshot declaration for \lstinline{n} to compile, as described at the end of \Vref{s:ArrayTypingC}.} 150 \VRef[Figure]{f:TemplateVsGenericType} shows @N@ is not the same as a @size_t@ declaration in a \CC \lstinline[language=C++]{template}. 152 151 \begin{enumerate}[leftmargin=*] 153 152 \item 154 153 The \CC template @N@ can only be a compile-time value, while the \CFA @N@ may be a runtime value. 155 154 \item 156 \CC does not allow a template function to be nested, while \CFA allows polymorphic functionsbe nested.155 \CC does not allow a template function to be nested, while \CFA lets its polymorphic functions to be nested. 157 156 Hence, \CC precludes a simple form of information hiding. 158 157 \item … … 177 176 % mycode/arrr/thesis-examples/check-peter/cs-cpp.cpp, v10 178 177 \end{enumerate} 179 The \CC template @std::array@ tries to accomplish a similar mechanism to \CFA @array@. 180 It is an aggregate type with the same semantics as a @struct@ holding a C-style array \see{\VRef{s:ArraysCouldbeValues}}, which mitigates points \VRef[]{p:DimensionPassing} and \VRef[]{p:ArrayCopy}. 178 The \CC template @array@ type mitigates points \VRef[]{p:DimensionPassing} and \VRef[]{p:ArrayCopy}, but it is also trying to accomplish a similar mechanism to \CFA @array@. 181 179 182 180 \begin{figure} 183 \begin{tabular}{@{}l l@{}}181 \begin{tabular}{@{}l@{\hspace{20pt}}l@{}} 184 182 \begin{c++} 185 183 … … 189 187 } 190 188 int main() { 191 const size_t n = 10; // must be constant 192 int ret[ n], x[n];193 for ( int i = 0; i < n; i += 1 ) x[i] = i;194 @copy<int, n>( ret, x );@195 for ( int i = 0; i < n; i += 1 )189 190 int ret[10], x[10]; 191 for ( int i = 0; i < 10; i += 1 ) x[i] = i; 192 @copy<int, 10 >( ret, x );@ 193 for ( int i = 0; i < 10; i += 1 ) 196 194 cout << ret[i] << ' '; 197 195 cout << endl; … … 205 203 for ( i; N ) ret[i] = x[i]; 206 204 } 207 size_t n; 208 sin | n;205 206 const int n = promptForLength(); 209 207 array( int, n ) ret, x; 210 208 for ( i; n ) x[i] = i; … … 230 228 When the argument lengths themselves are statically unknown, 231 229 the static check is conservative and, as always, \CFA's casting lets the programmer use knowledge not shared with the type system. 232 \lstinput{90-96}{hello-array.cfa} 233 This static check's rules are presented in \VRef[Section]{s:ArrayTypingC}. 230 \begin{tabular}{@{\hspace{0.5in}}l@{\hspace{1in}}l@{}} 231 \lstinput{90-97}{hello-array.cfa} 232 & 233 \lstinput{110-117}{hello-array.cfa} 234 \end{tabular} 235 236 \noindent 237 This static check's full rules are presented in \VRef[Section]{s:ArrayTypingC}. 234 238 235 239 Orthogonally, the \CFA array type works within generic \emph{types}, \ie @forall@-on-@struct@. 236 240 The same argument safety and the associated implicit communication of array length occurs. 237 241 Preexisting \CFA allowed aggregate types to be generalized with type parameters, enabling parameterizing of element types. 238 This feature isextended to allow parameterizing by dimension.239 Doing so gives a refinement of C's ``flexible array member''~\cite[\S~6.7.2.1.18]{C11} :242 This has been extended to allow parameterizing by dimension. 243 Doing so gives a refinement of C's ``flexible array member''~\cite[\S~6.7.2.1.18]{C11}. 240 244 \begin{cfa} 241 245 struct S { … … 260 264 \end{cfa} 261 265 This ability to avoid casting and size arithmetic improves safety and usability over C flexible array members. 262 Finally, inputs and outputs are given on the rightfor different sized schools.266 Finally, inputs and outputs are given at the bottom for different sized schools. 263 267 The example program prints the courses in each student's preferred order, all using the looked-up display names. 264 268 265 269 \begin{figure} 266 \begin{lrbox}{\myboxA} 267 \begin{tabular}{@{}l@{}} 268 \lstinput{50-55}{hello-accordion.cfa} \\ 270 \begin{cquote} 271 \lstinput{50-55}{hello-accordion.cfa} 269 272 \lstinput{90-98}{hello-accordion.cfa} 270 \end{tabular} 271 \end{lrbox} 272 273 \begin{lrbox}{\myboxB} 274 \begin{tabular}{@{}l@{}} 275 @$ cat school1@ \\ 276 \lstinputlisting{school1} \\ 277 @$ ./a.out < school1@ \\ 278 \lstinputlisting{school1.out} \\ 279 @$ cat school2@ \\ 280 \lstinputlisting{school2} \\ 281 @$ ./a.out < school2@ \\ 282 \lstinputlisting{school2.out} 283 \end{tabular} 284 \end{lrbox} 285 286 \setlength{\tabcolsep}{10pt} 287 \begin{tabular}{@{}ll@{}} 288 \usebox\myboxA 289 & 290 \usebox\myboxB 291 \end{tabular} 273 \ \\ 274 @$ cat school1@ 275 \lstinput{}{school1} 276 277 @$ ./a.out < school1@ 278 \lstinput{}{school1.out} 279 280 @$ cat school2@ 281 \lstinput{}{school2} 282 283 @$ ./a.out < school2@ 284 \lstinput{}{school2.out} 285 \end{cquote} 292 286 293 287 \caption{\lstinline{School} Example, Input and Output} … … 296 290 297 291 When a function operates on a @School@ structure, the type system handles its memory layout transparently. 298 \lstinput{30-3 6}{hello-accordion.cfa}292 \lstinput{30-37}{hello-accordion.cfa} 299 293 In the example, function @getPref@ returns, for the student at position @is@, what is the position of their @pref@\textsuperscript{th}-favoured class? 300 294 … … 302 296 \section{Dimension Parameter Implementation} 303 297 304 The core of the preexisting \CFA compiler already ha sthe ``heavy equipment'' needed to provide the feature set just reviewed (up to bugs in cases not yet exercised).298 The core of the preexisting \CFA compiler already had the ``heavy equipment'' needed to provide the feature set just reviewed (up to bugs in cases not yet exercised). 305 299 To apply this equipment in tracking array lengths, I encoded a dimension (array's length) as a type. 306 300 The type in question does not describe any data that the program actually uses at runtime. … … 329 323 \begin{itemize}[leftmargin=*] 330 324 \item 331 Resolver provided values for a declaration's type-system variables, gathered from type information in scope at the usage site.332 \item 333 The box pass, encoding information about type parameters into ``extra'' regular parameters andarguments on declarations and calls.325 Resolver provided values for a used declaration's type-system variables, gathered from type information in scope at the usage site. 326 \item 327 The box pass, encoding information about type parameters into ``extra'' regular parameters/arguments on declarations and calls. 334 328 Notably, it conveys the size of a type @foo@ as a @__sizeof_foo@ parameter, and rewrites the @sizeof(foo)@ expression as @__sizeof_foo@, \ie a use of the parameter. 335 329 \end{itemize} … … 337 331 The rules for resolution had to be restricted slightly, in order to achieve important refusal cases. 338 332 This work is detailed in \VRef[Section]{s:ArrayTypingC}. 339 However, the resolution--boxing scheme, in its preexisting state, isequipped to work on (desugared) dimension parameters.333 However, the resolution--boxing scheme, in its preexisting state, was already equipped to work on (desugared) dimension parameters. 340 334 The following discussion explains the desugaring and how correctly lowered code results. 341 335 … … 363 357 \end{enumerate} 364 358 The chosen solution is to encode the value @N@ \emph{as a type}, so items 1 and 2 are immediately available for free. 365 Item 3 needs a way to recover the encoded value from a (valid) type and to reject invalid types.359 Item 3 needs a way to recover the encoded value from a (valid) type (and to reject invalid types occurring here). 366 360 Item 4 needs a way to produce a type that encodes the given value. 367 361 … … 422 416 The type @thing(N)@ is (replaced by @void *@, but thereby effectively) gone. 423 417 \item 424 The @sout...@ expression has a regular variable (parameter) usage for its second argument.418 The @sout...@ expression (being an application of the @?|?@ operator) has a regular variable (parameter) usage for its second argument. 425 419 \item 426 420 Information about the particular @thing@ instantiation (value 10) is moved, from the type, to a regular function-call argument. … … 461 455 \begin{cfa} 462 456 enum { n = 42 }; 463 float x[@n@]; $\C{// or just 42}$464 float (*xp1)[@42@] = &x; $\C{// accept}$465 float (*xp2)[@999@] = &x; $\C{// reject}$457 float x[@n@]; // or just 42 458 float (*xp1)[@42@] = &x; // accept 459 float (*xp2)[@999@] = &x; // reject 466 460 warning: initialization of 'float (*)[999]' from incompatible pointer type 'float (*)[42]' 467 461 \end{cfa} 468 462 When a variable is involved, C and \CFA take two different approaches. 469 Today's C compilers accept the following without awarning.463 Today's C compilers accept the following without warning. 470 464 \begin{cfa} 471 465 static const int n = 42; … … 488 482 The way the \CFA array is implemented, the type analysis for this case reduces to a case similar to the earlier C version. 489 483 The \CFA compiler's compatibility analysis proceeds as: 490 \begin{itemize}[ leftmargin=*,parsep=0pt]484 \begin{itemize}[parsep=0pt] 491 485 \item 492 486 Is @array( float, 999 )@ type-compatible with @array( float, n )@? … … 516 510 in order to preserve the length information that powers runtime bound-checking.} 517 511 Therefore, the need to upgrade legacy C code is low. 518 Finally, if this incompatibility is a problem onboarding C programs to \CFA, it should be possible to change the C type check to a warning rather than an error, acting as a \emph{lint} of the original code for a missing type annotation.512 Finally, if this incompatibility is a problem onboarding C programs to \CFA, it is should be possible to change the C type check to a warning rather than an error, acting as a \emph{lint} of the original code for a missing type annotation. 519 513 520 514 To handle two occurrences of the same variable, more information is needed, \eg, this is fine, … … 522 516 int n = 42; 523 517 float x[@n@]; 524 float (*xp)[@n@] = x; $\C{// accept}$518 float (*xp)[@n@] = x; // accept 525 519 \end{cfa} 526 520 where @n@ remains fixed across a contiguous declaration context. 527 However, intervening dynamic statement s cancause failures.521 However, intervening dynamic statement cause failures. 528 522 \begin{cfa} 529 523 int n = 42; 530 524 float x[@n@]; 531 @n@ = 999; $\C{// dynamic change}$532 float (*xp)[@n@] = x; $\C{// reject}$533 \end{cfa} 534 As well, side-effects can even occur in a contiguous declaration context.525 @n@ = 999; // dynamic change 526 float (*xp)[@n@] = x; // reject 527 \end{cfa} 528 However, side-effects can occur in a contiguous declaration context. 535 529 \begin{cquote} 536 530 \setlength{\tabcolsep}{20pt} … … 542 536 void f() { 543 537 float x[@n@] = { g() }; 544 float (*xp)[@n@] = x; // reject538 float (*xp)[@n@] = x; // reject 545 539 } 546 540 \end{cfa} … … 550 544 int @n@ = 42; 551 545 void g() { 552 @n@ = 99 9; // accept546 @n@ = 99; 553 547 } 554 548 … … 559 553 The issue here is that knowledge needed to make a correct decision is hidden by separate compilation. 560 554 Even within a translation unit, static analysis might not be able to provide all the information. 561 However, if the example uses @const@, the check is possible even though the value is unknown.555 However, if the example uses @const@, the check is possible. 562 556 \begin{cquote} 563 557 \setlength{\tabcolsep}{20pt} … … 569 563 void f() { 570 564 float x[n] = { g() }; 571 float (*xp)[n] = x; // accept565 float (*xp)[n] = x; // reject 572 566 } 573 567 \end{cfa} … … 577 571 @const@ int n = 42; 578 572 void g() { 579 @n = 99 9@; // reject573 @n = 99@; // allowed 580 574 } 581 575 … … 698 692 An expression-compatibility question is a new addition to the \CFA compiler, and occurs in the context of dimension expressions, and possibly enumerations assigns, which must be unique. 699 693 700 % ...ensure these compiler implementation matters are treated under \CFA compiler background: type unification, cost calculation, GenPoly.694 % TODO: ensure these compiler implementation matters are treated under \CFA compiler background: type unification, cost calculation, GenPoly. 701 695 702 696 The relevant technical component of the \CFA compiler is the standard type-unification within the type resolver. … … 732 726 \end{cfa} 733 727 when resolving a function call to @g@, the first unification stage compares the type @T@ of the parameter with @array( float, n + 1 )@, of the argument. 728 \PAB{TODO: finish.} 734 729 735 730 The actual rules for comparing two dimension expressions are conservative. … … 737 732 is to imply, ``all else being equal, allow an array with length calculated by $e_1$ 738 733 to be passed to a function expecting a length-$e_2$ array.''\footnote{ 739 ...Deal with directionality, that I'm doing exact-match, no ``at least as long as,'' no subtyping.734 TODO: Deal with directionality, that I'm doing exact-match, no ``at least as long as,'' no subtyping. 740 735 Should it be an earlier scoping principle? Feels like it should matter in more places than here.} 741 736 So, a ``yes'' answer must represent a guarantee that both expressions evaluate the … … 751 746 So, a variable and a literal can never match. 752 747 753 ...Discuss the interaction of this dimension hoisting with the challenge of extra unification for cost calculation748 TODO: Discuss the interaction of this dimension hoisting with the challenge of extra unification for cost calculation 754 749 \end{comment} 755 750 756 The conservatism of the new rule set can leave a programmer requiring a recourse, when needing to use a dimension expression whose stability argument is more subtle than current-state analysis.751 The conservatism of the new rule set can leave a programmer needing a recourse, when needing to use a dimension expression whose stability argument is more subtle than current-state analysis. 757 752 This recourse is to declare an explicit constant for the dimension value. 758 753 Consider these two dimension expressions, whose uses are rejected by the blunt current-state rules: … … 760 755 void f( int @&@ nr, @const@ int nv ) { 761 756 float x[@nr@]; 762 float (*xp)[@nr@] = &x; // reject: nr varying (no references)757 float (*xp)[@nr@] = &x; // reject: nr varying (no references) 763 758 float y[@nv + 1@]; 764 float (*yp)[@nv + 1@] = &y; // reject: ?+? unpredictable (no functions)759 float (*yp)[@nv + 1@] = &y; // reject: ?+? unpredictable (no functions) 765 760 } 766 761 \end{cfa} 767 762 Yet, both dimension expressions are reused safely. 768 The @nr@ reference is never written, no implicit code (load) between declarations, and control does not leave the function between the uses.763 The @nr@ reference is never written, not volatile meaning no implicit code (load) between declarations, and control does not leave the function between the uses. 769 764 As well, the build-in @?+?@ function is predictable. 770 765 To make these cases work, the programmer must add the follow constant declarations (cast does not work): … … 773 768 @const int nx@ = nr; 774 769 float x[nx]; 775 float (*xp)[nx] = & x; // accept770 float (*xp)[nx] = & x; // accept 776 771 @const int ny@ = nv + 1; 777 772 float y[ny]; 778 float (*yp)[ny] = & y; // accept773 float (*yp)[ny] = & y; // accept 779 774 } 780 775 \end{cfa} … … 813 808 \end{cfa} 814 809 Dimension hoisting already existed in the \CFA compiler. 815 However, itwas buggy, particularly with determining, ``Can hoisting the expression be skipped here?'', for skipping this hoisting is clearly desirable in some cases.810 But its was buggy, particularly with determining, ``Can hoisting the expression be skipped here?'', for skipping this hoisting is clearly desirable in some cases. 816 811 For example, when a programmer has already hoisted to perform an optimization to prelude duplicate code (expression) and/or expression evaluation. 817 812 In the new implementation, these cases are correct, harmonized with the accept/reject criteria. … … 825 820 \item 826 821 Flexible-stride memory: 827 this model has complete independence between subscript ordering and memory layout, offering the ability to slice by (provide an index for) any dimension, \eg slice a row, column, or plane, \eg @c[3][4][*]@, @c[3][*][5]@, @c[3][*][*]@.822 this model has complete independence between subscripting ordering and memory layout, offering the ability to slice by (provide an index for) any dimension, \eg slice a plane, row, or column, \eg @c[3][*][*]@, @c[3][4][*]@, @c[3][*][5]@. 828 823 \item 829 824 Fixed-stride memory: … … 844 839 Style 3 is the inevitable target of any array implementation. 845 840 The hardware offers this model to the C compiler, with bytes as the unit of displacement. 846 C offers this model to programmersas pointer arithmetic, with arbitrary sizes as the unit.841 C offers this model to its programmer as pointer arithmetic, with arbitrary sizes as the unit. 847 842 Casting a multidimensional array as a single-dimensional array/pointer, then using @x[i]@ syntax to access its elements, is still a form of pointer arithmetic. 848 843 849 To step into the implementation of \CFA's new type-1 multidimensional arrays in terms of C's existing type-2 multidimensional arrays, it helps to clarify that the interface is low-level, \ie a C/\CFA array interface includes the resulting memory layout. 850 Specifically, the defining requirement of a type-2 system is the ability to slice a column from a column-finest matrix. 851 Hence, the required memory shape of such a slice is fixed, before any discussion of implementation. 852 The implementation presented here is how the \CFA array-library wrangles the C type system to make it do memory steps that are consistent with this layout while not affecting legacy C programs. 844 Now stepping into the implementation of \CFA's new type-1 multidimensional arrays in terms of C's existing type-2 multidimensional arrays, it helps to clarify that even the interface is quite low-level. 845 A C/\CFA array interface includes the resulting memory layout. 846 The defining requirement of a type-2 system is the ability to slice a column from a column-finest matrix. 847 The required memory shape of such a slice is fixed, before any discussion of implementation. 848 The implementation presented here is how the \CFA array-library wrangles the C type system, to make it do memory steps that are consistent with this layout while not affecting legacy C programs. 853 849 % TODO: do I have/need a presentation of just this layout, just the semantics of -[all]? 854 850 … … 878 874 \lstinput[aboveskip=0pt]{145-145}{hello-md.cfa} 879 875 The nontrivial slicing in this example now allows passing a \emph{noncontiguous} slice to @print1d@, where the new-array library provides a ``subscript by all'' operation for this purpose. 880 In a multi-dimensional subscript operation, any dimension given as @all@ is a placeholder, \ie ``not yet subscripted by a value'', waiting for a valueimplementing the @ar@ trait.876 In a multi-dimensional subscript operation, any dimension given as @all@ is a placeholder, \ie ``not yet subscripted by a value'', waiting for such a value, implementing the @ar@ trait. 881 877 \lstinput{150-151}{hello-md.cfa} 882 878 … … 952 948 A column is almost ready to be arranged into a matrix; 953 949 it is the \emph{contained value} of the next-level building block, but another lie about size is required. 954 At first, an atom needs to be arranged as if it isbigger, but now a column needs to be arranged as if it is smaller (the left diagonal above it, shrinking upward).950 At first, an atom needs to be arranged as if it were bigger, but now a column needs to be arranged as if it is smaller (the left diagonal above it, shrinking upward). 955 951 These lying columns, arranged contiguously according to their size (as announced) form the matrix @x[all]@. 956 952 Because @x[all]@ takes indices, first for the fine stride, then for the coarse stride, it achieves the requirement of representing the transpose of @x@. … … 1024 1020 1025 1021 1026 \section{Zero Overhead} 1027 1028 At runtime, the \CFA array is exactly a C array. 1022 \section{Bound Checks, Added and Removed} 1023 1029 1024 \CFA array subscripting is protected with runtime bound checks. 1030 The array dependent-typing provides information to the C optimizer, allowing it remove many of the bound checks. 1031 This section provides a demonstration of these effects. 1032 1033 The experiment compares the \CFA array system with the simple-safety system most typically exemplified by Java arrays (\VRef[Section]{JavaCompare}), but also reflected in the \CC pattern where restricted vector usage models a checked array (\VRef[Section]{CppCompare}). 1034 The essential feature of this simple system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. 1035 The experiment uses the \CC version to simplify access to generated assembly code. 1036 While ``\CC'' labels a participant, it is really the simple-safety system (of @vector@ with @.at@) whose limitations are being explained, and not limitations of \CC optimization. 1025 The array dependent-typing provides information to the C optimizer allowing it remove many of the bound checks. 1026 This section provides a demonstration of the effect. 1027 1028 The experiment compares the \CFA array system with the padded-room system [TODO:xref] most typically exemplified by Java arrays, but also reflected in the \CC pattern where restricted vector usage models a checked array. 1029 The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. 1030 The experiment compares with the \CC version to keep access to generated assembly code simple. 1037 1031 1038 1032 As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and \CC versions. 1039 Firstly, when the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. 1040 But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch a mistake. 1041 1042 \VRef[Figure]{f:ovhd-ctl} gives a control-case example of summing values in an array, where each column shows the program in languages C (a,~d,~g), \CFA (b,~e,~h), and \CC (c,~f,~i). 1043 The C code has no bounds checking, while the \CFA and \CC can have bounds checking. 1044 The source-code functions in (a, b, c) can be compiled to have either correct or incorrect uses of bounds. 1045 When compiling for correct bound use, the @BND@ macro passes its argument through, so the loops cover exactly the passed array sizes. 1046 When compiling for possible incorrect bound use (a programming error), the @BND@ macro hardcodes the loops for 100 iterations, which implies out-of-bound access attempts when the passed array has fewer than 100 elements. 1047 The assembly code excerpts show optimized translations for correct-bound mode in (d, e, f) and incorrect-bound mode in (g, h, i). 1048 Because incorrect-bound mode hardcodes 100 iterations, the loop always executes a first time, so this mode does not have the @n == 0@ branch seen in correct-bound mode. 1049 For C, this difference is the only (d--g) difference. 1050 For correct bounds, the \CFA translation equals the C translation, \ie~there is no (d--e) difference, while \CC has an additional indirection to dereference the vector's auxiliary allocation. 1051 1052 \begin{figure} 1053 \setlength{\tabcolsep}{10pt} 1054 \begin{tabular}{llll@{}} 1055 \multicolumn{1}{c}{C} & 1056 \multicolumn{1}{c}{\CFA} & 1057 \multicolumn{1}{c}{\CC (nested vector)} 1058 \\[1em] 1059 \lstinput{20-28}{ar-bchk/control.c} & 1060 \lstinput{20-28}{ar-bchk/control.cfa} & 1061 \lstinput{20-28}{ar-bchk/control.cc} 1062 \\ 1063 \multicolumn{1}{c}{(a)} & 1064 \multicolumn{1}{c}{(b)} & 1065 \multicolumn{1}{c}{(c)} 1066 \\[1em] 1067 \multicolumn{4}{l}{ 1068 \includegraphics[page=1,trim=0 9.125in 2in 0,clip]{ar-bchk} 1069 } 1070 \\ 1071 \multicolumn{1}{c}{(d)} & 1072 \multicolumn{1}{c}{(e)} & 1073 \multicolumn{1}{c}{(f)} 1074 \\[1em] 1075 \multicolumn{4}{l}{ 1076 \includegraphics[page=2,trim=0 8.75in 2in 0,clip]{ar-bchk} 1077 } 1078 \\ 1079 \multicolumn{1}{c}{(g)} & 1080 \multicolumn{1}{c}{(h)} & 1081 \multicolumn{1}{c}{(i)} 1082 \end{tabular} 1083 \caption{Overhead comparison, control case. 1084 All three programs/compilers generate equally performant code when the programmer ``self-checks'' bounds via a loop's condition. 1085 Yet both \CFA and \CC versions generate code that is slower and safer than C's when the programmer might overrun the bounds.} 1086 \label{f:ovhd-ctl} 1087 \end{figure} 1088 1089 Differences arise when the bound-incorrect programs are passed an array shorter than 100. 1090 The C version, (g), proceeds with undefined behaviour, reading past the end of the array. 1091 The \CFA and \CC versions, (h, i), flag the mistake with the runtime check, the @i >= n@ branch. 1092 This check is provided implicitly by the library types @array@ and @vector@, respectively. 1093 The significant result is the \emph{absence} of runtime checks from the bound-correct translations, (e, f). 1094 The code optimizer has removed them because, at the point where they would occur (immediately past @.L28@/@.L3@), it knows from the surrounding control flow either @i == 0 && 0 < n@ or @i < n@ (directly), \ie @i < n@ either way. 1095 So any repeated checks, \ie the branch and its consequent code (raise error), are removable. 1096 1097 % Progressing from the control case, a deliberately bound-incorrect mode is no longer informative. 1098 % Rather, given a (well-typed) program that does good work on good data, the issue is whether it is (determinably) bound-correct on all data. 1099 1100 When dimension sizes get reused, \CFA has an advantage over \CC-vector at getting simply written programs well optimized. 1101 The example case of \VRef[Figures]{f:ovhd-treat-src} and \VRef[]{f:ovhd-treat-asm} is a simple matrix multiplication over a row-major encoding. 1102 Simple means coding directly to the intuition of the mathematical definition without trying to optimize for memory layout. 1103 In the assembly code of \VRef[Figure]{f:ovhd-treat-asm}, the looping pattern of \VRef[Figure]{f:ovhd-ctl} (d, e, f), ``Skip ahead on zero; loop back for next,'' occurs with three nesting levels. 1104 Simultaneously, the dynamic bound-check pattern of \VRef[Figure]{f:ovhd-ctl} (h,~i), ``Get out on invalid,'' occurs, targeting @.L7@, @.L9@ and @.L8@ (bottom right). 1105 Here, \VRef[Figures]{f:ovhd-treat-asm} shows the \CFA solution optimizing into practically the C solution, while the \CC solution shows added runtime bound checks. 1106 Like in \VRef[Figure]{f:ovhd-ctl} (e), the significance is the \emph{absence} of library-imposed runtime checks, even though the source code is working through the the \CFA @array@ library. 1107 The optimizer removed the library-imposed checks because the data structure @array@-of-@array@ is constrained by its type to be shaped correctly for the intuitive looping. 1108 In \CC, the same constraint does not apply to @vector@-of-@vector@. 1109 Because every individual @vector@ carries its own size, two types of bound mistakes are possible. 1110 1111 \begin{figure} 1112 \setlength{\tabcolsep}{10pt} 1113 \begin{tabular}{llll@{}} 1114 \multicolumn{1}{c}{C} & 1115 \multicolumn{1}{c}{\CFA} & 1116 \multicolumn{1}{c}{\CC (nested vector)} 1117 \\ 1118 \lstinput{20-37}{ar-bchk/treatment.c} & 1119 \lstinput{20-37}{ar-bchk/treatment.cfa} & 1120 \lstinput{20-37}{ar-bchk/treatment.cc} 1121 \end{tabular} 1122 \caption{Overhead comparison, differentiation case, source.} 1123 \label{f:ovhd-treat-src} 1124 \end{figure} 1125 1126 \begin{figure} 1127 \newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}} 1128 \begin{tabular}{C{1.5in}C{1.5in}C{1.5in}p{1in}} 1129 C & 1130 \CFA & 1131 \CC (nested vector) 1132 \\[1em] 1133 \multicolumn{4}{l}{ 1134 \includegraphics[page=3,trim=0 4in 2in 0,clip]{ar-bchk} 1135 } 1136 \end{tabular} 1137 \caption{Overhead comparison, differentiation case, assembly. 1138 } 1139 \label{f:ovhd-treat-asm} 1140 \end{figure} 1141 1142 In detail, the three structures received may not be matrices at all, per the obvious/dense/total interpretation; rather, any one might be ragged-right in its rows. 1143 The \CFA solution guards against this possibility by encoding the minor length (number of columns) in the major element (row) type. 1144 In @res@, for example, each of the @M@ rows is @array(float, N)@, guaranteeing @N@ cells within it. 1145 Or more technically, guaranteeing @N@ as the basis for the imposed bound check \emph{of every row.} 1146 As well, the \CC type does not impose the mathematically familiar constraint of $(M \times P) (P \times N) \rightarrow (M \times N)$. 1147 Even assuming away the first issue, \eg that in @lhs@, all minor/cell counts agree, the data format allows the @rhs@ major/row count to disagree. 1148 Or, the possibility that the row count @res.size()@ disagrees with the row count @lhs.size()@ illustrates this bound-mistake type in isolation. 1149 The \CFA solution guards against this possibility by keeping length information separate from the array data, and therefore eligible for sharing. 1150 This capability lets \CFA escape the one-to-one correspondence between array instances and symbolic bounds, where this correspondence leaves a \CC-vector programmer stuck with a matrix representation that repeats itself. 1151 1152 It is important to clarify that the \CFA solution does not become unsafe (like C) in losing its dynamic checks, even though it becomes fast (as C) in losing them. 1153 The dynamic checks are dismissed as unnecessary \emph{because} the program is safe to begin with. 1154 To achieve the same performance, a \CC programmer must state appropriate assertions or assumptions, to allow the optimizer to dismiss the runtime checks. 1155 % Especially considering that two of them are in the inner-most loop. 1156 The solution requires doing the work of the inner-loop checks as a \emph{preflight step}. 1157 But this step requires looping and doing it upfront gives too much separation for the optimizer to see ``has been checked already'' in the deep loop. 1158 So, the programmer must restate the preflight observation within the deep loop, but this time as an unchecked assumption. 1159 Such assumptions are risky because they introduce further undefined behaviour when misused. 1160 Only the programmer's discipline remains to ensure this work is done without error. 1161 1162 In summary, the \CFA solution lets a simply stated program have dynamic guards that catch bugs, while letting a simply stated bug-free program run as fast as the unguarded C equivalent. 1163 1164 \begin{comment} 1165 The ragged-right issue brings with it a source-of-truth difficulty: Where, in the \CC version, is one to find the value of $N$? $M$ can come from either @res@'s or @lhs@'s major/row count, and checking these for equality is straightforward. $P$ can come from @rhs@'s major/row count. But $N$ is only available from columns, \ie minor/cell counts, which are ragged. So any choice of initial source of truth, \eg 1166 \end{comment} 1033 When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. 1034 But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch an occurrence the mistake. 1035 1036 TODO: paste source and assembly codes 1037 1038 Incorporating reuse among dimension sizes is seen to give \CFA an advantage at being optimized. 1039 The case is naive matrix multiplication over a row-major encoding. 1040 1041 TODO: paste source codes 1167 1042 1168 1043 … … 1334 1209 However, it only needs @float@'s default constructor, as the other operations are never used. 1335 1210 Current work by the \CFA team aims to improve this situation. 1211 Therefore, I had to construct a workaround. 1212 1336 1213 My workaround moves from otype (value) to dtype (pointer) with a default-constructor assertion, where dtype does not generate any constructors but the assertion claws back the default otype constructor. 1337 1214 \begin{cquote} … … 1531 1408 1532 1409 \subsection{Java} 1533 \label{JavaCompare}1534 1410 1535 1411 Java arrays are references, so multi-dimension arrays are arrays-of-arrays \see{\VRef{toc:mdimpl}}. … … 1620 1496 1621 1497 \subsection{\CC} 1622 \label{CppCompare}1623 1498 1624 1499 Because C arrays are difficult and dangerous, the mantra for \CC programmers is to use @std::vector@ in place of the C array. 1625 While the vector size can grow and shrink dynamically, \vs an unchanging dynamic size with VLAs, the cost of this extra feature is mitigated by preallocating the maximum size (like the VLA) at the declaration. 1626 So, it costs one upfront dynamic allocation and avoids growing the array through pushing. 1500 While the vector size can grow and shrink dynamically, \vs a fixed-size dynamic size with VLAs, the cost of this extra feature is mitigated by preallocating the maximum size (like the VLA) at the declaration (one dynamic call) to avoid using @push_back@. 1627 1501 \begin{c++} 1628 1502 vector< vector< int > > m( 5, vector<int>(8) ); // initialize size of 5 x 8 with 6 dynamic allocations 1629 1503 \end{c++} 1630 1504 Multidimensional arrays are arrays-of-arrays with associated costs. 1631 Each @vector@ array has an array descriptor containing the dimension, which allows bound checked using @x.at(i)@ in place of @x[i]@. 1632 Used with these restrictions, out-of-bound accesses are caught, and in-bound accesses never exercise the vector's ability to grow, preventing costly reallocate-and-copy, and never invalidating references to contained values. 1633 1634 This scheme matches a Java array's safety and expressiveness exactly, with the same inherent costs. 1635 Notably, a \CC vector of vectors does not provide contiguous element storage (even when upfront allocation is done carefully) because a vector puts its elements in an auxiliary allocation. 1636 So, in spite of @vector< vector< int > >@ appearing to be ``everything by value,'' it is still a first array whose elements include pointers to further arrays. 1637 1638 \CC has options for working with memory-adjacent data in desirable ways, particularly in recent revisions. 1639 But none makes an allocation with a dynamically given fixed size less awkward than the vector arrangement just described. 1640 1641 \CC~26 adds @std::inplace_vector@, which provides an interesting vector--array hybrid,\footnote{ 1642 Like a vector, it lets a user construct elements in a loop, rather than imposing uniform construction. 1643 Yet it preserves \lstinline{std::array}'s ability to be entirely stack-allocated, by avoiding an auxiliary elements' allocation. 1644 } but does not change the fundamental limit of \lstinline{std::array}, that the length, being a template parameter, must be a static value. 1645 1646 \CC~20's @std::span@ is a view that unifies true arrays, vectors, static sizes and dynamic sizes, under a common API that adds bounds checking. 1647 When wrapping a vector, bounds checking occurs on regular subscripting, \ie one need not remember to use @.at@. 1648 When wrapping a locally declared fixed-size array, bound communication is implicit. 1649 But it has a soundness gap by offering construction from pointer and user-given length. 1650 1651 \CC~23's @std::mdspan@ adds multidimensional indexing and reshaping capabilities analogous to those built into \CFA's @array@. 1652 Like @span@, it works over multiple underlying container types. 1653 But neither @span@ nor @mdspan@ augments the available allocation options. 1654 1655 Thus, these options do not offer an allocation with a dynamically given fixed size. 1656 And furthermore, they do not provide any improvement to the C flexible array member pattern, for making a dynamic amount of storage contiguous with its header, as do \CFA's accordions. 1657 1658 1659 \begin{comment} 1505 Each @vector@ array has an array descriptor contain the dimension, which allows bound checked using @x.at(i)@ in place of @x[i]@. 1506 Used with these restrictions, out-of-bound accesses are caught, and in-bound accesses never exercise the vector's ability to grow, preventing costly reallocate and copy, and never invalidate references to contained values. 1507 This scheme matches Java's safety and expressiveness exactly, but with the inherent costs. 1508 1509 1660 1510 \subsection{Levels of Dependently Typed Arrays} 1661 1511 1662 TODO: fix the position; checked c does not do linear types1663 1512 \CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C. 1664 1513 Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly-typed ownership-system, which further helps guarantee statically the validity of every pointer deference. … … 1694 1543 it can also do these other cool checks, but watch how I can mess with its conservativeness and termination 1695 1544 1696 Two c ontemporary array-centric languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, contributesimilar, restricted dependent types for tracking array length.1545 Two current, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer novel contributions concerning similar, restricted dependent types for tracking array length. 1697 1546 Unlike \CFA, both are garbage-collected functional languages. 1698 1547 Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary. … … 1705 1554 There is a particular emphasis on an existential type, enabling callee-determined return shapes. 1706 1555 1707 Dex uses an Ada-style conception of size, embedding quantitative information completely into an ordinary type. 1708 1709 Futhark and full-strength dependently typed languages treat array sizes as ordinary values. 1556 1557 Dex uses a novel conception of size, embedding its quantitative information completely into an ordinary type. 1558 1559 Futhark and full-strength dependently typed languages treat array sizes are ordinary values. 1710 1560 Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not. 1711 1561 1712 \CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet no objects of type @[N]@ occur.1562 \CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet has no instances. 1713 1563 Belonging to the type system means it is inferred at a call site and communicated implicitly, like in Dex and unlike in Futhark. 1714 1564 Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark. … … 1719 1569 1720 1570 In Ada and Dex, an array is conceived as a function whose domain must satisfy only certain structural assumptions, while in C, \CC, Java, Futhark and \CFA today, the domain is a prefix of the natural numbers. 1721 The Ada--Dex generality has aesthetic benefits for certain programmers. For those working on scheduling resources to weekdays: 1722 For those who prefer to count from an initial number of their own choosing: 1571 The generality has obvious aesthetic benefits for programmers working on scheduling resources to weekdays, and for programmers who prefer to count from an initial number of their own choosing. 1723 1572 1724 1573 This change of perspective also lets us remove ubiquitous dynamic bound checks. … … 1756 1605 (unsafe_from_ordinal a (idiv o bs), unsafe_from_ordinal b (rem o bs)) 1757 1606 \end{cfa} 1758 % fix mike's syntax highlighter1759 1607 and by a user-provided adapter expression at the call site that shows how to indexing with a tuple is backed by indexing each dimension at a time 1760 1608 \begin{cfa} … … 1768 1616 1769 1617 \subsection{Static Safety in C Extensions} 1770 \end{comment}1771 1618 1772 1619 1773 1620 \section{Future Work} 1774 1621 1775 %\subsection{Array Syntax}1776 1777 An important goal is to recast \CFA-style @array(...)@ syntax into C-style array syntax.1778 The proposal (which is partially implemented) is an alternate dimension and subscript syntax for multi-dimension arrays.1779 C multi-dimension and subscripting syntax uses multiple bracket ed constants/expressions.1780 \begin{cfa} 1781 int m@[2][3]@; // dimension1782 m@[0][1]@ = 3; // subscript1783 \end{cfa} 1784 The alternative \CFA syntax is a comma separated list: 1785 \begin{cfa} 1786 int m@[2, 3]@; // dimension1787 m@[0, 1]@ = 3; // subscript1788 \end{cfa} 1789 which should be intuitive to C programmers and is used in mathematics $M_{i,j}$ and other programing languages, \eg PL/I, Fortran.1790 With respect to the dimension expressions, C only allows an assignment expression, not a comma expression.1791 \begin{cfa} 1792 a[i, j]; 1793 test.c:3:16: error: expected ']' before ',' token 1794 \end{cfa} 1795 However, there is an ambiguity for a single dimension array, where the syntax for old and new arrays are the same, @int ar[10]@. 1796 The solution is to use a terminating comma to denote a \CFA-style single-dimension array. 1797 \begin{cfa} 1798 int ar[2$\Huge\color{red},$]; // single dimension new array 1799 \end{cfa} 1800 This syntactic form is also used for the (rare) singleton tuple @[y@{\ Large\color{red},}@]@.1622 \subsection{Array Syntax} 1623 1624 An important goal is to recast @array(...)@ syntax into C-style @[]@. 1625 The proposal (which is partially implemented) is an alternate dimension and subscript syntax. 1626 C multi-dimension and subscripting syntax uses multiple brackets. 1627 \begin{cfa} 1628 int m@[2][3]@; // dimension 1629 m@[0][1]@ = 3; // subscript 1630 \end{cfa} 1631 Leveraging this syntax, the following (simpler) syntax should be intuitive to C programmers with only a small backwards compatibility issue. 1632 \begin{cfa} 1633 int m@[2, 3]@; // dimension 1634 m@[0, 1]@ = 3; // subscript 1635 \end{cfa} 1636 However, the new subscript syntax is not backwards compatible, as @0, 1@ is a comma expression. 1637 Interestingly, disallowed the comma expression in this context eliminates an unreported error: subscripting a matrix with @m[i, j]@ instead of @m[i][j]@, which selects the @j@th row not the @i, j@ element. 1638 Hence, a comma expression in this context is rare. 1639 Finally, it is possible to write @m[(i, j)]@ in the new syntax to achieve the equivalent of the old @m[i, j]@. 1640 Note, the new subscript syntax can easily be internally lowered to @[-][-]...@ and handled as regular subscripting. 1641 The only ambiguity with C syntax is for a single dimension array, where the syntax for old and new are the same. 1642 \begin{cfa} 1643 int m[2@,@]; // single dimension 1644 m[0] = 3; // subscript 1645 \end{cfa} 1646 The solution for the dimension is to use a terminating comma to denote a new single-dimension array. 1647 This syntactic form is also used for the (rare) singleton tuple @[y@{\color{red},}@]@. 1801 1648 The extra comma in the dimension is only mildly annoying, and acts as eye-candy differentiating old and new arrays. 1802 Hence, \CFA can repurpose the comma expression in this context for a list of dimensions. 1803 The ultimate goal is to replace all C arrays with \CFA arrays, establishing a higher level of safety in C programs, and eliminating the need for the terminating comma. 1804 With respect to the subscript expression, the comma expression is allowed. 1805 However, a comma expression in this context is rare, and is most commonly a (silent) mistake: subscripting a matrix with @m[i, j]@ instead of @m[i][j]@ selects the @j@th row not the @i, j@ element. 1806 It is still possible to write @m[(i, j)]@ in the new syntax to achieve the equivalent of the old @m[i, j]@. 1807 Internally, the compiler must de-sugar @[i, j, k]@ into @[i][j][k]@ to match with three calls to subscript operators. 1808 Note, there is no ambiguity for subscripting a single dimensional array, as the subscript operator selects the correct form from the array type. 1809 Currently, @array@ supports the old and new subscript syntax \see{\VRef[Figure]{f:ovhd-treat-src}}, including combinations of new and old, @arr[1, 2][3]@. 1810 The new subscript syntax can be extended to C arrays for uniformity, but requires the non-compatible removal of the (rare) comma-expression as a subscript. 1649 The subscript operator is not an issue as overloading selects the correct single-dimension operation for old/new array types. 1650 The ultimately goal is to replace all C arrays with \CFA arrays, establishing a higher level of safety in C programs, and eliminating the need for the terminating comma. 1651 1652 1653 \subsection{Range Slicing} 1654 1655 \subsection{With a Module System} 1656 1657 1658 \subsection{Retire Pointer Arithmetic} 1811 1659 1812 1660 1813 1661 \begin{comment} 1814 \subsection{Range Slicing}1815 1816 \subsection{With a Module System}1817 1818 1819 \subsection{Retire Pointer Arithmetic}1820 1821 1822 1662 \section{\texorpdfstring{\CFA}{Cforall}} 1823 1663 … … 1857 1697 Using a compiler-produced value eliminates an opportunity for user error. 1858 1698 1859 ...someday...fix in following: even the alloc call gives bad code gen: verify it was always this way; walk back the wording about things just working here; assignment (rebind) seems to offer workaround, as in bkgd-cfa-arrayinteract.cfa1699 TODO: fix in following: even the alloc call gives bad code gen: verify it was always this way; walk back the wording about things just working here; assignment (rebind) seems to offer workaround, as in bkgd-cfa-arrayinteract.cfa 1860 1700 1861 1701 Bringing in another \CFA feature, reference types, both resolves a sore spot of the last example, and gives a first example of an array-interaction bug. … … 1866 1706 (*ar2)[5]; 1867 1707 \end{cfa} 1868 Using ``reference to array'' works at resolving this issue. ...someday...discuss connection with Doug-Lea \CC proposal.1708 Using ``reference to array'' works at resolving this issue. TODO: discuss connection with Doug-Lea \CC proposal. 1869 1709 \begin{cfa} 1870 1710 tm (&ar3)[10] = *alloc(); … … 1874 1714 1875 1715 Using proper array types (@ar2@ and @ar3@) addresses a concern about using raw element pointers (@ar1@), albeit a theoretical one. 1876 ...someday...xref C standard does not claim that @ar1@ may be subscripted,1716 TODO xref C standard does not claim that @ar1@ may be subscripted, 1877 1717 because no stage of interpreting the construction of @ar1@ has it be that ``there is an \emph{array object} here.'' 1878 1718 But both @*ar2@ and the referent of @ar3@ are the results of \emph{typed} @alloc@ calls, … … 1880 1720 1881 1721 The ``reference to array'' type has its sore spots too. 1882 ...someday...see also @dimexpr-match-c/REFPARAM_CALL@ (under @TRY_BUG_1@)1883 1884 ...someday...I fixed a bug associated with using an array as a T. I think. Did I really? What was the bug?1722 TODO see also @dimexpr-match-c/REFPARAM_CALL@ (under @TRY_BUG_1@) 1723 1724 TODO: I fixed a bug associated with using an array as a T. I think. Did I really? What was the bug? 1885 1725 \end{comment} -
doc/theses/mike_brooks_MMath/background.tex
r8614140 r79ba50c 626 626 void f( int n, float[][n] ); $\C{// array of VLAs}$ 627 627 \end{cfa} 628 without an error about conflicting types for @f@.629 Yet, entirely different stride calculations occur in the function body for each of the two parameterstyles.628 as a repeat, without an error about conflicting types for @f@. 629 Yet, entirely different stride calculations would occur in a function body whose parameters were declared in each of the two styles. 630 630 631 631 \begin{figure} … … 794 794 795 795 \subsection{Arrays Could be Values} 796 \label{s:ArraysCouldbeValues}797 796 798 797 All arrays have a know runtime size at their point of declaration. -
doc/theses/mike_brooks_MMath/plots/list-zoomout-noshuf.gp
r8614140 r79ba50c 10 10 set key top left 11 11 set logscale x 12 #set logscale y13 #set yrange [1:1000];12 set logscale y 13 set yrange [1:1000]; 14 14 set xlabel "List length (item count)" offset 2,0 15 15 set ylabel "Duration (ns)" -
doc/theses/mike_brooks_MMath/plots/list-zoomout-shuf.gp
r8614140 r79ba50c 11 11 set logscale x 12 12 set logscale y 13 #set yrange [1:1000];13 set yrange [1:1000]; 14 14 set xlabel "List length (item count)" offset 2,0 15 set ylabel "Duration (ns) , log scale"15 set ylabel "Duration (ns)" 16 16 set linetype 3 dashtype 2 17 17 set linetype 4 dashtype 2 -
doc/theses/mike_brooks_MMath/plots/string-peq-cppemu.gp
r8614140 r79ba50c 1 set terminal pdf color enhanced size 6. 5in,3.5in font "Times,17"1 set terminal pdf color enhanced size 6.0in,3.0in font "Times,17" 2 2 #set terminal postscript portrait enhanced size 7.5, 10. color solid 9.5; 3 3 #set terminal wxt size 950,1250 … … 11 11 set grid 12 12 set key top left 13 set xrange [1:500]14 13 set xtics (1,2,5,10,20,50,100,200,500) 15 14 set logscale x … … 21 20 set linetype 4 dashtype 2 22 21 plot INDIR."/plot-string-peq-cppemu.dat" \ 23 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 24 '' i 0 using 1:2 notitle smooth sbezier lt rgb "red" dashtype 1, \ 25 '' i 1 using 1:2 title columnheader(1) with points lt rgb "red" pt 1 ps 1, \ 26 '' i 1 using 1:2 notitle smooth sbezier lt rgb "red" dashtype 4, \ 27 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 28 '' i 2 using 1:2 notitle smooth sbezier lt rgb "blue" dashtype 1, \ 29 '' i 3 using 1:2 title columnheader(1) with points lt rgb "blue" pt 8 ps 1, \ 30 '' i 3 using 1:2 notitle smooth sbezier lt rgb "blue" dashtype 4 \ 22 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 23 '' i 1 using 1:2 title columnheader(1) with points lt rgb "red" pt 1 ps 1, \ 24 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 25 '' i 3 using 1:2 title columnheader(1) with points lt rgb "blue" pt 8 ps 1 -
doc/theses/mike_brooks_MMath/plots/string-peq-sharing.gp
r8614140 r79ba50c 1 set terminal pdf color enhanced size 6. 5in,3.5in font "Times,17"1 set terminal pdf color enhanced size 6.0in,3.0in font "Times,17" 2 2 #set terminal postscript portrait enhanced size 7.5, 10. color solid 9.5; 3 3 #set terminal wxt size 950,1250 … … 11 11 set grid 12 12 set key top left 13 set xrange [1:500]14 13 set xtics (1,2,5,10,20,50,100,200,500) 15 14 set logscale x … … 21 20 set linetype 4 dashtype 2 22 21 plot INDIR."/plot-string-peq-sharing.dat" \ 23 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 24 '' i 0 using 1:2 notitle smooth sbezier lt rgb "red" dashtype 1, \ 25 '' i 1 using 1:2 title columnheader(1) with points lt rgb "red" pt 1 ps 1, \ 26 '' i 1 using 1:2 notitle smooth sbezier lt rgb "red" dashtype 4, \ 27 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 28 '' i 2 using 1:2 notitle smooth sbezier lt rgb "blue" dashtype 1, \ 29 '' i 3 using 1:2 title columnheader(1) with points lt rgb "blue" pt 8 ps 1, \ 30 '' i 3 using 1:2 notitle smooth sbezier lt rgb "blue" dashtype 4 \ 31 22 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 23 '' i 1 using 1:2 title columnheader(1) with points lt rgb "red" pt 1 ps 1, \ 24 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 25 '' i 3 using 1:2 title columnheader(1) with points lt rgb "blue" pt 8 ps 1 -
doc/theses/mike_brooks_MMath/plots/string-pta-sharing.gp
r8614140 r79ba50c 1 set terminal pdf color enhanced size 6. 5in,3.5in font "Times,17"1 set terminal pdf color enhanced size 6.0in,3.0in font "Times,17" 2 2 #set terminal postscript portrait enhanced size 7.5, 10. color solid 9.5; 3 3 #set terminal wxt size 950,1250 … … 11 11 set grid 12 12 set key top left 13 set xrange [1:500]14 13 set xtics (1,2,5,10,20,50,100,200,500) 15 14 set logscale x … … 18 17 set xlabel "String Length being appended (mean, geo. dist.), log scale" offset 2,0 19 18 set ylabel "Time per append (ns, mean), log_{2} scale" 19 #show colornames 20 20 plot INDIR."/plot-string-pta-sharing.dat" \ 21 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 22 '' i 0 using 1:2 notitle smooth sbezier lt rgb "red" dashtype 1, \ 23 '' i 1 using 1:2 title columnheader(1) with points lt rgb "dark-green" pt 4 ps 1, \ 24 '' i 1 using 1:2 notitle smooth sbezier lt rgb "dark-green" dashtype 4, \ 25 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 26 '' i 2 using 1:2 notitle smooth sbezier lt rgb "blue" dashtype 1, \ 27 '' i 3 using 1:2 title columnheader(1) with points lt rgb "dark-green" pt 12 ps 1, \ 28 '' i 3 using 1:2 notitle smooth sbezier lt rgb "dark-green" dashtype 4 \ 29 21 i 0 using 1:2 title columnheader(1) with points lt rgb "red" pt 2 ps 1, \ 22 '' i 1 using 1:2 title columnheader(1) with points lt rgb "dark-green" pt 4 ps 1, \ 23 '' i 2 using 1:2 title columnheader(1) with points lt rgb "blue" pt 6 ps 1, \ 24 '' i 3 using 1:2 title columnheader(1) with points lt rgb "dark-green" pt 12 ps 1 -
doc/theses/mike_brooks_MMath/programs/hello-accordion.cfa
r8614140 r79ba50c 31 31 int getPref( @School( C, S ) & school@, int is, int pref ) { 32 32 for ( ic; C ) { 33 if ( pref == @school.preferences@[ic][is] ) return ic; $\C{// offset calculation implicit}$33 if ( pref == @school.preferences@[ic][is]; ) return ic; $\C{// offset calculation implicit}$ 34 34 } 35 assert( false ); // must find a match35 assert( false ); 36 36 } 37 37 … … 89 89 90 90 for ( is; ns ) { 91 sout | school.student_ids[is] | ": " ;91 sout | school.student_ids[is] | ": " | nonl; 92 92 for ( pref; 1 ~= nc ) { 93 93 int ic = getPref( school, is, pref ); -
doc/theses/mike_brooks_MMath/programs/hello-array.cfa
r8614140 r79ba50c 89 89 90 90 forall( [M], [N] ) 91 void f( array(float, M) &x, array(float, N) &y ) { 91 void bad( array(float, M) &x, 92 array(float, N) &y ) { 92 93 f( x, x ); $\C[0.5in]{// ok}$ 93 94 f( y, y ); $\C{// ok}$ 95 94 96 f( x, y ); $\C{// error}\CRT$ 95 if ( M == N ) f( x, @(array( float, M ) &)@y ); $\C{// ok}\CRT$96 97 } 98 97 99 #endif 98 100 … … 107 109 108 110 forall( [M], [N] ) 109 void f( array( float, M ) & x, array( float, N ) & y ) { 111 void bad_fixed( array( float, M ) & x, 112 array( float, N ) & y ) { 110 113 f( x, x ); $\C[0.5in]{// ok}$ 111 114 f( y, y ); $\C{// ok}$ 112 if ( M == N ) f( x, @(array( float, M ) &)@y ); $\C{// ok}\CRT$ 115 if ( M == N ) 116 f( x, @(array( float, M ) &)@y ); $\C{// ok}\CRT$ 113 117 } 114 118 … … 128 132 129 133 forall( [M], [N] ) 130 void bad_ok_only( array(float, M) &x, array(float, N) &y ) { 134 void bad_ok_only( array(float, M) &x, 135 array(float, N) &y ) { 131 136 f( x, x ); 132 137 f( y, y ); -
doc/theses/mike_brooks_MMath/programs/school1
r8614140 r79ba50c 1 1 3 courses, 2 students 2 c\s 90111111 902222223 ENGL101 324 PHYS101 135 CHEM101 212 c\s 90111111 90222222 3 ENGL101 3 2 4 PHYS101 1 3 5 CHEM101 2 1 -
doc/theses/mike_brooks_MMath/programs/school1.out
r8614140 r79ba50c 1 90111111: 2 PHYS101 CHEM101 ENGL101 3 90222222: 4 CHEM101 ENGL101 PHYS101 1 90111111: PHYS101 CHEM101 ENGL101 2 90222222: CHEM101 ENGL101 PHYS101 -
doc/theses/mike_brooks_MMath/programs/school2
r8614140 r79ba50c 1 1 5 courses, 3 students 2 c\s 90111111 90222222 903333333 ENGL101 3 234 PHYS101 1 345 CHEM101 2 156 PHIL101 4 527 MATH499 5 412 c\s 90111111 90222222 90333333 3 ENGL101 3 2 3 4 PHYS101 1 3 4 5 CHEM101 2 1 5 6 PHIL101 4 5 2 7 MATH499 5 4 1 -
doc/theses/mike_brooks_MMath/programs/school2.out
r8614140 r79ba50c 1 90111111: 2 PHYS101 CHEM101 ENGL101 PHIL101 MATH499 3 90222222: 4 CHEM101 ENGL101 PHYS101 MATH499 PHIL101 5 90333333: 6 MATH499 PHIL101 ENGL101 PHYS101 CHEM101 1 90111111: PHYS101 CHEM101 ENGL101 PHIL101 MATH499 2 90222222: CHEM101 ENGL101 PHYS101 MATH499 PHIL101 3 90333333: MATH499 PHIL101 ENGL101 PHYS101 CHEM101 -
doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa
r8614140 r79ba50c 300 300 open( outfile, "build/sharing10.tex" ); 301 301 outfile | "\\begin{cquote}"; 302 outfile | "\\setlength{\\tabcolsep}{10pt}";303 302 outfile | "\\begin{tabular}{@{}rlllll@{}}"; 304 303 outfile | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_crs@\t& @s1_mid@\t& @s1_end@\t\\\\"; -
doc/theses/mike_brooks_MMath/string.tex
r8614140 r79ba50c 17 17 \begin{cquote} 18 18 \begin{tabular}{@{}l|l|l|l@{}} 19 C @char [ ]@ & \CC @string@ & Java @String@ & \CFA @string@ \\19 C @char [ ]@ & \CC @string@ & Java @String@ & \CFA @string@ \\ 20 20 \hline 21 21 @strcpy@, @strncpy@ & @=@ & @=@ & @=@ \\ … … 60 60 As a result, a @string@ declaration does not specify a maximum length, where a C string array does. 61 61 For \CFA, as a @string@ dynamically grows and shrinks in size, so does its underlying storage. 62 For C, as a string dynamically grows and shrinks in size, its underlying storage does not.62 For C, as a string dynamically grows and shrinks in size, but its underlying storage does not. 63 63 The maximum storage for a \CFA @string@ value is @size_t@ characters, which is $2^{32}$ or $2^{64}$ respectively. 64 64 A \CFA string manages its length separately from the string, so there is no null (@'\0'@) terminating value at the end of a string value. … … 88 88 Hence, the basic types @char@, @char *@, @int@, @double@, @_Complex@, including any signness and size variations, implicitly convert to type @string@ (as in Java). 89 89 \begin{cquote} 90 \setlength{\tabcolsep}{10pt} 91 \begin{tabular}{@{}llll@{}} 90 \begin{tabular}{@{}l|ll|l@{}} 92 91 \begin{cfa} 93 92 string s = 5; … … 129 128 Conversions can be explicitly specified using a compound literal. 130 129 \begin{cfa} 131 s = (string){ 5 }; s = (string){ "abc" }; s = (string){ 5.5 };130 s = (string){ 5 }; s = (string){ "abc" }; s = (string){ 5.5 }; 132 131 \end{cfa} 133 132 134 133 Conversions from @string@ to @char *@ attempt to be safe. 135 The overloaded @strncpy@ function is safe, if the length of the C string is correct.134 The @strncpy@ conversion requires the maximum length for the pointer's target buffer. 136 135 The assignment operator and constructor both allocate the buffer and return its address, meaning the programmer must free it. 137 136 Note, a C string is always null terminated, implying storage is always necessary for the null. 138 137 \begin{cquote} 139 \begin{tabular}{@{}l l@{}}138 \begin{tabular}{@{}l|l@{}} 140 139 \begin{cfa} 141 140 string s = "abcde"; 142 141 char cs[4]; 143 142 strncpy( cs, s, sizeof(cs) ); 144 char * cp = s; // ownership143 char * cp = s; // ownership 145 144 delete( cp ); 146 145 cp = s + ' ' + s; // ownership … … 163 162 \subsection{Length} 164 163 165 The @len@ operation (short for @strlen@) returns the length of a C (not including the terminating null)or \CFA string.166 For compatibility, an overloaded @strlen@works with \CFA strings.167 \begin{cquote} 168 \begin{tabular}{@{}l l@{}}164 The @len@ operation (short for @strlen@) returns the length of a C or \CFA string. 165 For compatibility, @strlen@ also works with \CFA strings. 166 \begin{cquote} 167 \begin{tabular}{@{}l|l@{}} 169 168 \begin{cfa} 170 169 i = len( "" ); … … 193 192 In C, these operators compare the C string pointer not its value, which does not match programmer expectation. 194 193 C strings use function @strcmp@ to lexicographically compare the string value. 195 Java has the same issue with @==@ (reference) and @.equals@ (value) comparison.194 Java has the same issue with @==@ and @.equals@. 196 195 197 196 … … 200 199 The binary operators @+@ and @+=@ concatenate C @char@, @char *@ and \CFA strings, creating the sum of the characters. 201 200 \begin{cquote} 202 \setlength{\tabcolsep}{5pt} 203 \begin{tabular}{@{}ll|ll|ll@{}} 201 \begin{tabular}{@{}l|l@{\hspace{15pt}}l|l@{\hspace{15pt}}l|l@{}} 204 202 \begin{cfa} 205 203 s = ""; … … 266 264 Similarly, it is impossible to restrict or remove addition on type @char *@ because (unfortunately) it is subscripting: @cs + 'a'@ implies @cs['a']@ or @'a'[cs]@. 267 265 268 The prior \CFA concatenation examples show complex mixed-mode interactions among @char@, @char *@, and @string@ constants work correctly ( @string@variables are the same).266 The prior \CFA concatenation examples show complex mixed-mode interactions among @char@, @char *@, and @string@ constants work correctly (variables are the same). 269 267 The reason is that the \CFA type-system handles this kind of overloading well using the left-hand assignment-type and complex conversion costs. 270 268 Hence, the type system correctly handles all uses of addition (explicit or implicit) for @char *@. … … 301 299 If $N = 0$, a zero length string, @""@, is returned. 302 300 \begin{cquote} 303 \begin{tabular}{@{}l l@{}}301 \begin{tabular}{@{}l|l@{}} 304 302 \begin{cfa} 305 303 s = 'x' * 0; … … 320 318 multiplication of pointers does not exist in C. 321 319 \begin{cfa} 322 ch = ch * 3; $\C[2in]{// LHS disambiguate, multiply character value }$320 ch = ch * 3; $\C[2in]{// LHS disambiguate, multiply character values}$ 323 321 s = 'a' * 3; $\C{// LHS disambiguate, concatenate characters}$ 324 322 printf( "%c\n", @'a' * 3@ ); $\C{// no LHS information, ambiguous}$ … … 332 330 The substring operation returns a subset of a string starting at a position in the string and traversing a length, or matching a pattern string. 333 331 \begin{cquote} 334 \setlength{\tabcolsep}{ 8pt}335 \begin{tabular}{@{}l l|ll@{}}332 \setlength{\tabcolsep}{10pt} 333 \begin{tabular}{@{}l|ll|l@{}} 336 334 \multicolumn{2}{@{}c}{\textbf{length}} & \multicolumn{2}{c@{}}{\textbf{pattern}} \\ 337 335 \multicolumn{4}{@{}l}{\lstinline{string name = "PETER"}} \\ … … 352 350 "TER" // clip length to 3 353 351 "ER" 354 "" // clip, beyond right355 "" // clip, beyond left352 "" // beyond string to right, clip to null 353 "" // beyond string to left, clip to null 356 354 "ER" 357 355 "TER" // to end of string … … 392 390 Hence, the left string may decrease, stay the same, or increase in length. 393 391 \begin{cquote} 394 \begin{tabular}{@{}l l@{}}392 \begin{tabular}{@{}l|l@{}} 395 393 \begin{cfa}[escapechar={}] 396 394 digit( 3, 3 ) = ""; … … 410 408 \end{tabular} 411 409 \end{cquote} 412 Here,substring pattern matching is useful on the left-hand side of assignment.413 \begin{cquote} 414 \begin{tabular}{@{}l l@{}}410 Now substring pattern matching is useful on the left-hand side of assignment. 411 \begin{cquote} 412 \begin{tabular}{@{}l|l@{}} 415 413 \begin{cfa}[escapechar={}] 416 414 digit( "$$" ) = "345"; … … 424 422 \end{tabular} 425 423 \end{cquote} 426 Supporting a regular-expression pattern is a possible extension.424 Extending the pattern to a regular expression is a possible extension. 427 425 428 426 The replace operation extends substring to substitute all occurrences. 429 427 \begin{cquote} 430 \begin{tabular}{@{}l l@{}}428 \begin{tabular}{@{}l|l@{}} 431 429 \begin{cfa} 432 430 s = replace( "PETER", "E", "XX" ); … … 450 448 If the key does not appear in the string, the length of the string is returned. 451 449 \begin{cquote} 452 \begin{tabular}{@{}l l@{}}450 \begin{tabular}{@{}l|l@{}} 453 451 \begin{cfa} 454 452 i = find( digit, '3' ); … … 467 465 A character-class operation indicates if a string is composed completely of a particular class of characters, \eg, alphabetic, numeric, vowels, \etc. 468 466 \begin{cquote} 469 \begin{tabular}{@{}l l@{}}467 \begin{tabular}{@{}l|l@{}} 470 468 \begin{cfa} 471 469 charclass vowels{ "aeiouy" }; … … 486 484 Function @exclude@ is the reverse of @include@, checking if all characters in the string are excluded from the class (compliance). 487 485 \begin{cquote} 488 \begin{tabular}{@{}l l@{}}486 \begin{tabular}{@{}l|l@{}} 489 487 \begin{cfa} 490 488 i = exclude( "cdbfghmk", vowels ); … … 500 498 Both forms can return the longest substring of compliant characters. 501 499 \begin{cquote} 502 \begin{tabular}{@{}l l@{}}500 \begin{tabular}{@{}l|l@{}} 503 501 \begin{cfa} 504 502 s = include( "aaeiuyoo", vowels ); … … 519 517 There are also versions of @include@ and @exclude@, returning a position or string, taking a validation function, like one of the C character-class functions.\footnote{It is part of the hereditary of C that these function take and return an \lstinline{int} rather than a \lstinline{bool}, which affects the function type.} 520 518 \begin{cquote} 521 \begin{tabular}{@{}l l@{}}519 \begin{tabular}{@{}l|l@{}} 522 520 \begin{cfa} 523 521 i = include( "1FeC34aB", @isxdigit@ ); … … 538 536 The translate operation returns a string with each character transformed by one of the C character transformation functions. 539 537 \begin{cquote} 540 \begin{tabular}{@{}l l@{}}538 \begin{tabular}{@{}l|l@{}} 541 539 \begin{cfa} 542 540 s = translate( "abc", @toupper@ ); … … 561 559 However, string search can fail, which is reported as an alternate search outcome, possibly an exception. 562 560 Many string libraries use a return code to indicate search failure, with a failure value of @0@ or @-1@ (PL/I~\cite{PLI} returns @0@). 563 This semantics leads to anawkward pattern, which can appear many times in a string library or user code.561 This semantics leads to the awkward pattern, which can appear many times in a string library or user code. 564 562 \begin{cfa} 565 563 i = exclude( s, alpha ); … … 567 565 else return ""; 568 566 \end{cfa} 569 The problem is that substring does the wrong thing or fails with the failure return-code in most string libraries, so it has to be special cased.570 567 571 568 \CFA adopts a return code but the failure value is taken from the index-of function in APL~\cite{apl}, which returns the length of the target string $N$ (or $N+1$ for 1 origin). … … 585 582 \begin{figure} 586 583 \begin{cquote} 587 \begin{tabular}{@{}l l@{}}584 \begin{tabular}{@{}l|l@{}} 588 585 \multicolumn{1}{c}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{\CFA}} \\ 589 586 \begin{cfa} … … 631 628 \begin{cquote} 632 629 \begin{tabular}{@{}ll@{}} 633 \ multicolumn{2}{@{}l@{}}{\lstinline{char s[32]; // changing s's type to string works}} \\634 \begin{cfa} 630 \begin{cfa} 631 char s[32]; // string s; 635 632 strlen( s ); 636 633 strnlen( s, 3 ); … … 640 637 & 641 638 \begin{cfa} 639 642 640 strcpy( s, "abc" ); 643 641 strncpy( s, "abcdef", 3 ); … … 653 651 \subsection{I/O Operators} 654 652 655 The ability to input and output a stringis as essential as for any other type.656 The goal for character I/O is to work with groups rather than individual characters.653 The ability to input and output strings is as essential as for any other type. 654 The goal for character I/O is to also work with groups rather than individual characters. 657 655 A comparison with \CC string I/O is presented as a counterpoint to \CFA string I/O. 658 656 … … 661 659 The \CC manipulators are @setw@, and its associated width controls @left@, @right@ and @setfill@. 662 660 \begin{cquote} 663 \begin{tabular}{@{}l l@{}}661 \begin{tabular}{@{}l|l@{}} 664 662 \begin{c++} 665 663 string s = "abc"; … … 678 676 The \CFA manipulators are @bin@, @oct@, @hex@, @wd@, and its associated width control and @left@. 679 677 \begin{cquote} 680 \begin{tabular}{@{}l l@{}}678 \begin{tabular}{@{}l|l@{}} 681 679 \begin{cfa} 682 680 string s = "abc"; … … 706 704 Reading into a @char@ is safe as the size is 1, @char *@ is unsafe without using @setw@ to constraint the length (which includes @'\0'@), @string@ is safe as its grows dynamically as characters are read. 707 705 \begin{cquote} 708 \begin{tabular}{@{}l l@{}}706 \begin{tabular}{@{}l|l@{}} 709 707 \begin{c++} 710 708 char ch, c[10]; … … 723 721 \end{cquote} 724 722 Input text can be \emph{gulped}, including whitespace, from the current point to an arbitrary delimiter character using @getline@. 725 \begin{cquote}726 \setlength{\tabcolsep}{10pt}727 \begin{tabular}{@{}ll@{}}728 \multicolumn{1}{c}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{\CFA}} \\729 \begin{cfa}730 string s1, s2, s3;731 getline( cin, s1, 'a' );732 getline( cin, s2, 'w' );733 getline( cin, s3 );734 cout << s1 << ' ' << s2 << ' ' << s3 << endl;735 @bbbad ddwxyz@736 \end{cfa}737 &738 \begin{cfa}739 740 sin | getline( s1, 'a' )741 | getline( s2, 'w' )742 | getline( s3 );743 sout | s1 | s2 | s3; "bbb" "d dd" "xyz"744 745 \end{cfa}746 \end{tabular}747 748 \end{cquote}749 723 750 724 The \CFA philosophy for input is that, for every constant type in C, these constants should be usable as input. … … 756 730 \begin{cquote} 757 731 \setlength{\tabcolsep}{10pt} 758 \begin{tabular}{@{}l l@{}}732 \begin{tabular}{@{}l|l@{}} 759 733 \begin{c++} 760 734 char ch, c[10]; … … 762 736 sin | ch | wdi( 5, c ) | s; 763 737 @abcde fg@ 764 sin | @quote@( ch ) | @quote@( wdi( sizeof(c), c ) ) | @quote@( s, '[', ']' ) | nl;765 @'a' "bcde"[fg]@738 sin | quote( ch ) | quote( wdi( sizeof(c), c ) ) | quote( s, '[', ']' ) | nl; 739 @'a' "bcde" [fg]@ 766 740 sin | incl( "a-zA-Z0-9 ?!&\n", s ) | nl; 767 741 @x?&000xyz TOM !.@ … … 793 767 For example, the \CC @replace@ function selects a substring in the target and substitutes it with the source string, which can be smaller or larger than the substring. 794 768 \CC modifies the mutable receiver object, replacing by position (zero origin) and length. 769 \begin{cquote} 770 \begin{tabular}{@{}l|l@{}} 795 771 \begin{c++} 796 772 string s1 = "abcde"; 797 s1.replace( 2, 3, "xy" ); "abxy"773 s1.replace( 2, 3, "xy" ); 798 774 \end{c++} 775 & 776 \begin{c++} 777 778 "abxy" 779 \end{c++} 780 \end{tabular} 781 \end{cquote} 799 782 Java cannot modify the receiver (immutable strings) so it returns a new string, replacing by text. 800 783 \label{p:JavaReplace} 784 \begin{cquote} 785 \begin{tabular}{@{}l|l@{}} 801 786 \begin{java} 802 787 String s = "abcde"; 803 String r = s.replace( "cde", "xy" ); "abxy"788 String r = s.replace( "cde", "xy" ); 804 789 \end{java} 790 & 791 \begin{java} 792 793 "abxy" 794 \end{java} 795 \end{tabular} 796 \end{cquote} 805 797 Java also provides a mutable @StringBuffer@, replacing by position (zero origin) and length. 798 \begin{cquote} 799 \begin{tabular}{@{}l|l@{}} 806 800 \begin{java} 807 801 StringBuffer sb = new StringBuffer( "abcde" ); 808 sb.replace( 2, 5, "xy" ); "abxy"802 sb.replace( 2, 5, "xy" ); 809 803 \end{java} 804 & 805 \begin{java} 806 807 "abxy" 808 \end{java} 809 \end{tabular} 810 \end{cquote} 810 811 However, there are anomalies. 811 812 @StringBuffer@'s @substring@ returns a @String@ copy that is immutable rather than modifying the receiver. … … 817 818 \begin{figure} 818 819 \setlength{\extrarowheight}{2pt} 819 \setlength{\tabcolsep}{5pt} 820 \begin{tabularx}{\textwidth}{@{}p{0.8in}XXcccc@{}} 820 \begin{tabularx}{\textwidth}{@{}p{0.6in}XXcccc@{}} 821 821 & & & \multicolumn{4}{@{}c@{}}{\underline{Supports Helpful?}} \\ 822 822 & Required & Helpful & C & \CC & Java & \CFA \\ 823 823 \hline 824 Type Abstraction824 Type abst'n 825 825 & Low-level: The string type is a varying amount of text communicated via a parameter or return. 826 826 & High-level: The string-typed relieves the user of managing memory for the text. … … 913 913 String s3 = s2.substring( 1, 2 ); $\C{// snapshot state (possible), strict symmetry, fragment referent}\CRT$ 914 914 System.out.println( s + ' ' + s1 + ' ' + s2 + ' ' + s3 ); 915 System.out.println( (s == s1) + " " + (s == s2) + " " + (s2 == s3) ); 915 916 $\texttt{\small abcde abcde bc c}$ 916 System.out.println( (s == s1) + " " + (s == s2) + " " + (s2 == s3) );917 917 $\texttt{\small true false false}$ 918 918 \end{java} … … 939 939 string s3 = s`share; $\C{// alias state, strict symmetry, variable-constrained referent}$ 940 940 string s4 = s( 1, 2 ); $\C{// snapshot state, strict symmetry, fragment referent}$ 941 string s5 = s4( 1, 1 )`share ; $\C{// alias state, strict symmetry, fragment referent}\CRT$941 string s5 = s4( 1, 1 )`share'; $\C{// alias state, strict symmetry, fragment referent}\CRT$ 942 942 sout | s | s1 | s2 | s3 | s4 | s5; 943 943 $\texttt{\small abcde abcde abcde abcde bc c}$ … … 995 995 996 996 String sharing is expressed using the @`share@ marker to indicate aliasing (mutations shared) \vs snapshot (not quite an immutable result, but one with subsequent mutations isolated). 997 This aliasing relationship is a \newterm{sticky property}established at initialization.997 This aliasing relationship is a sticky property established at initialization. 998 998 For example, here strings @s1@ and @s1a@ are in an aliasing relationship, while @s2@ is in a copy relationship. 999 999 \input{sharing1.tex} … … 1030 1030 When changes happen on an aliasing substring that overlap. 1031 1031 \input{sharing10.tex} 1032 Strings @s1_crs@ and @s1_mid@ overlap at character 4, @ 'j'@, because the substrings are 3,2 and 4,2.1032 Strings @s1_crs@ and @s1_mid@ overlap at character 4, @j@, because the substrings are 3,2 and 4,2. 1033 1033 When @s1_crs@'s size increases by 1, @s1_mid@'s starting location moves from 4 to 5, but the overlapping character remains, changing to @'+'@. 1034 1034 … … 1136 1136 Normally, one global context is appropriate for an entire program; 1137 1137 concurrency is discussed in \VRef{s:ControllingImplicitSharing}. 1138 A string is a handle to a node in a linked list containing information about a string text in the buffer.1138 A string is a handle to a node in a linked list containing a information about a string text in the buffer. 1139 1139 The list is doubly linked for $O(1)$ insertion and removal at any location. 1140 1140 Strings are ordered in the list by text start address. … … 1151 1151 The linked handles define all live strings in the buffer, which indirectly defines the allocated and free space in the buffer. 1152 1152 The string handles are maintained in sorted order, so the handle list can be traversed, copying the first live text to the start of the buffer, and subsequent strings after each other. 1153 After compaction, if free storage is still less than the new string allocation, a larger text buffer is heap-allocated, the current buffer is copied into the new buffer, and the original buffer is freed.1153 After compaction, if free storage is still be less than the new string allocation, a larger text buffer is heap-allocated, the current buffer is copied into the new buffer, and the original buffer is freed. 1154 1154 Note, the list of string handles is structurally unaffected during a compaction; 1155 1155 only the text pointers in the handles are modified to new buffer locations. … … 1158 1158 There are two fundamental string-creation functions: importing external text like a C-string or reading a string, and initialization from an existing \CFA string. 1159 1159 When importing, storage comes from the end of the buffer, into which the text is copied. 1160 T o maintain sorted order, the new string handle is inserted at the end of the handle list because the new text is at the end of the buffer.1160 The new string handle is inserted at the end of the handle list because the new text is at the end of the buffer. 1161 1161 When initializing from text already in the buffer, the new handle is a second reference into the original run of characters. 1162 To maintain sorted order, the new handle's linked-list position is after the original handle.1162 In this case, the new handle's linked-list position is after the original handle. 1163 1163 Both string initialization styles preserve the string module's internal invariant that the linked-list order matches the buffer order. 1164 1164 For string destruction, handles are removed from the list. … … 1177 1177 Favourable conditions allow for in-place editing: where there is room for the resulting value in the original buffer location, and where all handles referring to the original buffer location see the new value. 1178 1178 One notable example of favourable conditions occurs because the most recently written string is often the last in the buffer, after which a large amount of free space occurs. 1179 Now, repeated appends (reading) can occur without copying previously accumulated characters.1179 So, repeated appends often occur without copying previously accumulated characters. 1180 1180 However, the general case requires a new buffer allocation: where the new value does not fit in the old place, or if other handles are still using the old value. 1181 1181 … … 1194 1194 Both \CC and \CFA RAII systems are powerful enough to achieve reference counting. 1195 1195 1196 In general, a lifecycle function has access to an object by location, \ie constructors and destructors receive a parameter providing an object's memory address.\footnote{ 1197 Historically in \CC, the type of \lstinline[language=C++]{this} is a pointer versus a reference; 1198 in \CFA, the first parameter of a constructor or destructor must be a reference.} 1196 In general, a lifecycle function has access to an object by location, \ie constructors and destructors receive a @this@ parameter providing an object's memory address. 1199 1197 \begin{cfa} 1200 1198 struct S { int * ip; }; 1201 1199 void ?{}( S & @this@ ) { this.ip = new(); } $\C[3in]{// default constructor}$ 1202 void ?{}( S & @this@, int i ) { this{}; *this.ip = i; } $\C{// initializing constructor}$1203 void ?{}( S & @this@, S s ) { this{ *s.ip}; } $\C{// copy constructor}$1200 void ?{}( S & @this@, int i ) { (this){}; *this.ip = i; } $\C{// initializing constructor}$ 1201 void ?{}( S & @this@, S s ) { (this){*s.ip}; } $\C{// copy constructor}$ 1204 1202 void ^?{}( S & @this@ ) { delete( this.ip ); } $\C{// destructor}\CRT$ 1205 1203 \end{cfa} 1206 1204 Such basic examples use the @this@ address only to gain access to the values being managed. 1207 But lifecycle logic can use the address, too, \eg add the @this@ object to a collection at creation and remove it at destruction. 1208 \begin{cfa} 1209 // header (.hfa) 1210 struct N { $\C[3in]{// list node}$ 1205 But the lifecycle logic can use the pointer generally, too. 1206 For example, they can add @this@ object to a collection at creation and remove it at destruction. 1207 \begin{cfa} 1208 // header 1209 struct T { 1211 1210 // private 1212 inline dlink( N);1211 inline dlink(T); 1213 1212 }; 1214 void ?{}( N & ); $\C{// default constructor}$1215 void ^?{}( N& ); $\C{// destructor}\CRT$1216 // implementation (.cfa)1217 static dlist( N ) @list_N@;1218 void ?{}( N & this ) { insert_last( list_N, @this@) }1219 void ^?{}( N & this ) { remove( this); }1220 \end{cfa} 1221 A module providing the @ N@ (node) type can traverse @list_N@ to manipulate the objects.1222 Hence, declaring a @ N@ not only ensures that it begins with an initially ``good'' value, but it also provides an implicit subscription to a service that keeps the value ``good'' during its lifetime.1213 void ?{}( T & ); $\C[3in]{// default constructor}$ 1214 void ^?{}( T & ); $\C{// destructor}\CRT$ 1215 // implementation 1216 static dlist(T) @all_T@; 1217 void ?{}( T & this ) { insert_last(all_T, @this@) } 1218 void ^?{}( T & this ) { remove(this); } 1219 \end{cfa} 1220 A module providing the @T@ type can traverse @all_T@ at relevant times, to keep the objects ``good.'' 1221 Hence, declaring a @T@ not only ensures that it begins with an initially ``good'' value, but it also provides an implicit subscription to a service that keeps the value ``good'' during its lifetime. 1223 1222 Again, both \CFA and \CC support this usage style. 1224 1223 … … 1227 1226 In the parameter direction, the language's function-call handling must arrange for a copy-constructor call to happen, at a time near the control transfer into the callee. %, with the source as the caller's (sender's) version and the target as the callee's (receiver's) version. 1228 1227 In the return direction, the roles are reversed and the copy-constructor call happens near the return of control. 1229 \CC supports this capability. % without qualification.1228 \CC supports this capability.% without qualification. 1230 1229 \CFA offers limited support; 1231 simple examples work, but implicit copying does not combine successfully with other RAII capabilities.1230 simple examples work, but implicit copying does not combine successfully with the other RAII capabilities discussed. 1232 1231 1233 1232 \CC also offers move constructors and return-value optimization~\cite{RVO20}. … … 1240 1239 \begin{enumerate} 1241 1240 \item 1242 \label{p:feature1}1243 1241 Object provider implements lifecycle functions to manage a resource outside of the object. 1244 1242 \item 1245 \label{p:feature2} 1246 Object provider implements lifecycle functions to store references to the object, often originating from outside of it. 1243 Object provider implements lifecycle functions to store references back to the object, often originating from outside of it. 1247 1244 \item 1248 \label{p:feature3}1249 1245 Object user expects to pass (in either direction) an object by value for function calls. 1250 1246 \end{enumerate} 1251 \CC supports all three simultaneously. 1252 \CFA does not currently support \ref{p:feature2} and \ref{p:feature3} on the same object, though \ref{p:feature1} works along with either one of \ref{p:feature2} or \ref{p:feature3}. 1253 \CFA needs to be fixed to support all three simultaneously. 1254 1255 The reason \CFA does not support \ref{p:feature2} with \ref{p:feature3} is a holdover from how \CFA lowered function calls to C, before \CFA got references and RAII. 1256 At that time, adhering to a principal of minimal intervention, this code was treated as a passthrough: 1247 \CC supports all three simultaneously. \CFA does not currently support \#2 and \#3 on the same object, though \#1 works along with either one of \#2 or \#3. \CFA needs to be fixed to support all three simultaneously. 1248 1249 The reason that \CFA does not support \#2 with \#3 is a holdover from how \CFA function calls lowered to C, before \CFA got references and RAII. 1250 At that time, adhering to a principal of minimal intervention, this code could always be treated as passthrough: 1257 1251 \begin{cfa} 1258 1252 struct U { ... }; 1259 1253 // RAII to go here 1260 void f( U u ) { F_BODY( u) }1254 void f( U u ) { F_BODY(u) } 1261 1255 U x; 1262 1256 f( x ); 1263 1257 \end{cfa} 1264 However, adding custom RAII (at ``...go here'') changes things. 1265 1266 \VRef[Figure]{f:CodeLoweringRAII} shows the common \CC lowering~\cite[Sec. 3.1.2.3]{cxx:raii-abi} (right) proceeds differently than the present \CFA lowering (left). 1267 The current \CFA scheme is still using a by-value C call. 1268 C does a @memcpy@ on structures passed by value. 1269 And so, @F_BODY@ sees the bits of @__u_for_f@ occurring at an address that has never been presented to the @U@ lifecycle functions. 1270 If @U@ is trying to have a style- \ref{p:feature2} invariant, it shows up broken in @F_BODY@: references supposedly to @u@ are actually to @__u_for_f@. 1271 The \CC scheme does not have this problem because it constructs the @u@ copy in the correct location within @f@. 1272 Yet, the current \CFA scheme is sufficient to deliver style-\ref{p:feature1} invariants (in this style-\ref{p:feature3} use case) because this scheme still does the correct number of lifecycle calls, using correct values, at correct times. 1273 So, reference-counting or simple ownership applications get their invariants respected under call/return-by-value. 1274 1275 \begin{figure} 1276 \centering 1277 \begin{tabular}{@{}l|l@{}} 1278 \multicolumn{1}{@{}c|}{\CFA today} & \multicolumn{1}{c@{}}{\CC, \CFA future} \\ 1279 \begin{cfa} 1258 But adding custom RAII (at ``...go here'') changes things. 1259 The common \CC lowering~\cite[Sec. 3.1.2.3]{cxx:raii-abi} proceeds differently than the present \CFA lowering. 1260 \begin{cquote} 1261 \begin{tabular}{@{}l|l@{}} 1262 \begin{cfa} 1263 $\C[0.0in]{// \CC, \CFA future}\CRT$ 1264 struct U {...}; 1265 // RAII elided 1266 void f( U * __u_orig ) { 1267 U u = * __u_orig; // call copy ctor 1268 F_BODY( u ); 1269 // call dtor, u 1270 } 1271 U x; // call default ctor 1272 1273 1274 f( &x ) ; 1275 1276 1277 // call dtor, x 1278 \end{cfa} 1279 & 1280 \begin{cfa} 1281 $\C[0.0in]{// \CFA today}\CRT$ 1280 1282 struct U {...}; 1281 1283 // RAII elided … … 1287 1289 U x; // call default ctor 1288 1290 { 1289 @U __u_for_f = x;@// call copy ctor1291 U __u_for_f = x; // call copy ctor 1290 1292 f( __u_for_f ); 1291 1293 // call dtor, __u_for_f … … 1293 1295 // call dtor, x 1294 1296 \end{cfa} 1295 & 1296 \begin{cfa} 1297 struct U {...}; 1298 // RAII elided 1299 void f( U * __u_orig ) { 1300 @U u = * __u_orig;@ // call copy ctor 1301 F_BODY( u ); 1302 // call dtor, u 1303 } 1304 U x; // call default ctor 1305 1306 1307 f( &x ) ; 1308 1309 1310 // call dtor, x 1311 \end{cfa} 1312 \end{tabular} 1313 1314 \caption{Code Lowering for RAII} 1315 \label{f:CodeLoweringRAII} 1316 \end{figure} 1297 \end{tabular} 1298 \end{cquote} 1299 The current \CFA scheme is still using a by-value C call. 1300 C does a @memcpy@ on structures passed by value. 1301 And so, @F_BODY@ sees the bits of @__u_for_f@ occurring at an address that has never been presented to the @U@ lifecycle functions. 1302 If @U@ is trying to have a style-\#2 invariant, it shows up broken in @F_BODY@: references supposedly to @u@ are actually to @__u_for_f@. 1303 The \CC scheme does not have this problem because it constructs the for @f@ copy in the correct location within @f@. 1304 1305 Yet, the current \CFA scheme is sufficient to deliver style-\#1 invariants (in this style-\#3 use case) because this scheme still does the correct number of lifecycle calls, using correct values, at correct times. 1306 So, reference-counting or simple ownership applications get their invariants respected under call/return-by-value. 1317 1307 1318 1308 % [Mike is not currently seeing how distinguishing initialization from assignment is relevant] … … 1348 1338 % The following discusses the consequences of this semantics with respect to lifetime management of \CFA strings. 1349 1339 1350 The string API offers style \ ref{p:feature3}'s pass-by-value, \eg in the return of @"a" + "b"@.1351 Its implementation uses the style-\ ref{p:feature2}invariant of the string handles being linked to each other, helping to achieve high performance.1340 The string API offers style \#3's pass-by-value in, \eg in the return of @"a" + "b"@. 1341 Its implementation uses the style-\#2 invariant of the string handles being linked to each other, helping to achieve high performance. 1352 1342 Since these two RAII styles cannot coexist, a workaround splits the API into two layers: one that provides pass-by-value, built upon the other with inter-linked handles. 1353 1343 The layer with pass-by-value incurs a performance penalty, while the layer without delivers the desired runtime performance. … … 1355 1345 Both APIs present the same features, up to return-by-value operations being unavailable in LL and implemented via the workaround in HL. 1356 1346 The intention is for most future code to target HL. 1357 When the RAII issue is fixed, the full HL feature set is achievable using the LL-style lifetime management. 1358 Then, HL can be removed, LL's type renamed to @string@, and programs generated with the current HL will run faster. 1347 When the RAII issue is fixed, the full HL feature set will be achievable using the LL-style lifetime management. 1348 Then, HL will be removed; 1349 LL's type will be renamed @string@ and programs written for current HL will run faster. 1359 1350 In the meantime, performance-critical sections of applications must use LL. 1360 1351 Subsequent performance experiments \see{\VRef{s:PerformanceAssessment}} use the LL API when comparing \CFA to other languages. 1361 1352 This measurement gives a fair estimate of the goal state for \CFA. 1362 1353 A separate measure of the HL overhead is also included. 1363 Hence, \VRef[Section]{string-general-impl} is describing the goal state for \CFA.1364 In present state, the internal type @string_res@ replaces @string@ for aninter-linked handle.1354 hence, \VRef[Section]{string-general-impl} us describing the goal state for \CFA. 1355 In present state, the type @string_res@ replaces its mention of @string@ as inter-linked handle. 1365 1356 1366 1357 To use LL, a programmer rewrites invocations using pass-by-value APIs into invocations where resourcing is more explicit. 1367 1358 Many invocations are unaffected, notably assignment and comparison. 1368 \VRef[Figure]{f:HL_LL_Lowering} shows, of the capabilities listed in \VRef[Figure]{f:StrApiCompare}, only three cases need revisions. 1369 The actual HL workaround wraps @string@ as a pointer to a uniquely owned, heap-allocated @string_res@. 1370 This arrangement has @string@ using style-\ref{p:feature1} RAII, which is compatible with pass-by-value. 1371 1372 \begin{figure} 1373 \centering 1374 \begin{tabular}{@{}ll@{}} 1359 Of the capabilities listed in \VRef[Figure]{f:StrApiCompare}, only the following three cases need revisions. 1360 \begin{cquote} 1361 \begin{tabular}{ll} 1375 1362 HL & LL \\ 1376 1363 \hline … … 1388 1375 \begin{cfa} 1389 1376 string s = "abcde"; 1390 string s2 = s(2, 3); // s2 == "cde"1391 1392 s(2,3) = "x"; // s == "abx" && s2 == "cde"1377 string s2 = s(2, 3); // s2 == "cde" 1378 1379 s(2,3) = "x"; // s == "abx" && s2 == "cde" 1393 1380 \end{cfa} 1394 1381 & 1395 1382 \begin{cfa} 1396 1383 string_res sr = "abcde"; 1397 string_res sr2 = {sr, 2, 3}; // sr2 == "cde"1384 string_res sr2 = {sr, 2, 3}; // sr2 == "cde" 1398 1385 string_res sr_mid = { sr, 2, 3, SHARE }; 1399 sr_mid = "x"; // sr == "abx" && sr2 == "cde"1386 sr_mid = "x"; // sr == "abx" && sr2 == "cde" 1400 1387 \end{cfa} 1401 1388 \\ … … 1404 1391 string s = "abcde"; 1405 1392 1406 s[2] = "xxx"; // s == "abxxxde"1393 s[2] = "xxx"; // s == "abxxxde" 1407 1394 \end{cfa} 1408 1395 & … … 1410 1397 string_res sr = "abcde"; 1411 1398 string_res sr_mid = { sr, 2, 1, SHARE }; 1412 mid = "xxx"; // sr == "abxxxde" 1413 \end{cfa} 1414 \end{tabular} 1415 1416 \caption{HL to LL Lowering} 1417 \label{f:HL_LL_Lowering} 1418 \end{figure} 1399 mid = "xxx"; // sr == "abxxxde" 1400 \end{cfa} 1401 \end{tabular} 1402 \end{cquote} 1403 The actual HL workaround is having @string@ wrap a pointer to a uniquely owned, heap-allocated @string_res@. This arrangement has @string@ being style-\#1 RAII, which is compatible with pass-by-value. 1419 1404 1420 1405 … … 1520 1505 It might be possible to pack 16- or 32-bit Unicode characters within the same string buffer as 8-bit characters. 1521 1506 Again, locations for identification flags must be found and checked along the fast path to select the correct actions. 1522 Handling utf8 (variable length) is more problematic because simple pointer arithmetic cannot be used to stride through the variable-length characters.1507 Handling utf8 (variable length), is more problematic because simple pointer arithmetic cannot be used to stride through the variable-length characters. 1523 1508 Trying to use a secondary array of fixed-sized pointers/offsets to the characters is possible, but raises the question of storage management for the utf8 characters themselves. 1524 1509 … … 1528 1513 1529 1514 I assessed the \CFA string library's speed and memory usage against strings in \CC STL. 1530 Overall, this analysis shows that features common to both APIs comes at no substantial cost in the performance. 1531 Moreover, the comparison shows that \CFA's high-level string features simplify text processing because the STL requires users to think more about memory management. 1515 Overall, this analysis shows that adding support for the features shown earlier in the chapter comes at no substantial cost in the performance of features common to both APIs. 1516 1517 Moreover, the results support the \CFA string's position as a high-level enabler of simplified text processing. 1518 STL makes its user think about memory management. 1532 1519 When the user does, and is successful, STL's performance can be very good. 1533 But if a user does understandthe consequences of the STL representation, performance becomes poor.1520 But when the user fails to think through the consequences of the STL representation, performance becomes poor. 1534 1521 The \CFA string lets the user work at the level of just putting the right text into the right variables, with corresponding performance degradations reduced or eliminated. 1535 1522 … … 1542 1529 These tests use a \emph{corpus} of strings. 1543 1530 Their lengths are important; the specific characters occurring in them are immaterial. 1544 In a result graph, a corpus's mean string-length is often the independent variable on the x-axis. 1531 In a result graph, a corpus's mean string length is often the independent variable shown on the X axis. 1532 1545 1533 When a corpus contains strings of different lengths, the lengths are drawn from a lognormal distribution. 1546 1534 Therefore, strings much longer than the mean occur less often and strings slightly shorter than the mean occur most often. … … 1556 1544 To ensure comparable results, a common memory allocator is used for \CFA and \CC. 1557 1545 \CFA runs the llheap allocator~\cite{Zulfiqar22}, which is also plugged into \CC. 1558 The llheap allocator is significantly better than the standard @glibc@ allocator.1559 1546 1560 1547 The operations being measured take dozens of nanoseconds, so a succession of many invocations is run and timed as a group. … … 1649 1636 1650 1637 \VRef[Figure]{fig:string-graph-peq-cppemu} shows the resulting performance. 1651 The two fresh (solid spline lines) and the two reuse (dash spline lines)are identical, except for lengths $\le$10, where the \CC SSO has a 40\% average and minimally 24\% advantage.1638 The two fresh (solid) lines and the two reuse (dash) lines are identical, except for lengths $\le$10, where the \CC SSO has a 40\% average and minimally 24\% advantage. 1652 1639 The gap between the fresh and reuse lines is the removal of the dynamic memory allocates and reuse of prior storage, \eg 100M allocations for fresh \vs 100 allocations for reuse across all experiments. 1653 1640 While allocation reduction is huge, data copying dominates the cost, so the lines are still reasonably close together. … … 1704 1691 In earlier experiments, the choice of \CFA API among HL and LL had no impact on the functionality being tested. 1705 1692 Here, however, the @+@ operation, which returns its result by value, is only available in HL. 1706 The \CFA @+=@ is obtained by inlining the HL implementation of @+@, which is done using LL's @+=@, into the test harness, while omitting the HL-inherent extra dynamic allocation. The HL-upon-LL @+@ implementation, is: 1707 \begin{cquote} 1708 \setlength{\tabcolsep}{20pt} 1709 \begin{tabular}{@{}ll@{}} 1710 \begin{cfa} 1711 struct string { // simple ownership 1712 string_res * inner; // RAII manages malloc/free 1693 The \CFA @+@ number was obtained by inlining the HL implementation of @+@, which is done using LL's @+=@, into the test harness, while omitting the HL-inherent extra dynamic allocation. The HL-upon-LL @+@ implementation, is: 1694 \begin{cfa} 1695 struct string { 1696 string_res * inner; // RAII manages malloc/free, simple ownership 1713 1697 }; 1714 1698 void ?+=?( string & s, string s2 ) { 1715 1699 (*s.inner) += (*s2.inner); 1716 1700 } 1717 \end{cfa}1718 &1719 \begin{cfa}1720 1701 string @?+?@( string lhs, string rhs ) { 1721 1702 string ret = lhs; … … 1723 1704 return ret; 1724 1705 } 1725 1726 \end{cfa} 1727 \end{tabular} 1728 \end{cquote} 1706 \end{cfa} 1729 1707 This @+@ implementation is also the goal implementation of @+@ once the HL/LL workaround is no longer needed. Inlining the induced LL steps into the test harness gives: 1730 1708 \begin{cquote} … … 1772 1750 So again, \CFA helps users who just want to treat strings as values, and not think about the resource management under the covers. 1773 1751 1774 \PAB{Something is wrong with these sentences:While not a design goal, and not graphed, \CFA in STL-emulation mode outperformed STL in this case.1775 User-managed allocation reuse did not affect either implementation in this case; only ``fresh'' results are shown. }1752 While not a design goal, and not graphed, \CFA in STL-emulation mode outperformed STL in this case. 1753 User-managed allocation reuse did not affect either implementation in this case; only ``fresh'' results are shown. 1776 1754 1777 1755 … … 1790 1768 \end{cfa} 1791 1769 With implicit sharing active, \CFA treats this operation as normal and supported. 1792 Again, an HL-LL difference requires a mockup as LL does not directly support pass-by-value. 1770 1771 Again, an HL-LL difference requires an LL mockup. This time, the fact to integrate into the test harness is that LL does not directly support pass-by-value. 1793 1772 \begin{cquote} 1794 1773 \setlength{\tabcolsep}{20pt} … … 1818 1797 The goal (HL) version gives the modified test harness, with a single loop. 1819 1798 Each iteration uses a corpus item as the argument to the function call. 1820 These corpus items are imported to the string heap before beginning the timed run.1799 These corpus items were imported to the string heap before beginning the timed run. 1821 1800 1822 1801 \begin{figure} … … 1832 1811 1833 1812 \VRef[Figure]{fig:string-graph-pbv} shows the costs for calling a function that receives a string argument by value. 1834 STL's performance worsens uniformly as string length increases, except for short strings due to SSO, while \CFA has the same performance at all sizes. 1813 STL's performance worsens uniformly as string length increases, while \CFA has the same performance at all sizes. 1814 Although the STL is better than \CFA until string length 10 because of the SSO. 1835 1815 While improved, the \CFA cost to pass a string is still nontrivial. 1836 1816 The contributor is adding and removing the callee's string handle from the global list. -
doc/theses/mike_brooks_MMath/uw-ethesis-frontpgs.tex
r8614140 r79ba50c 139 139 Often, the array is part of the programming language, while linked lists are built from (recursive) pointer types, and strings from arrays and/or linked lists. 140 140 For all three types, languages and/or their libraries supply varying degrees of high-level mechanisms for manipulating these objects at the bulk and component levels, such as copying, slicing, extracting, and iterating among elements. 141 Unfortunately, typical solutions for the the se key types in C cause 60\%--70\% of the reported software vulnerabilities involving memory errors; 70\%--80\% of hacker attack-vectors target these types.141 Unfortunately, typical solutions for the the key types in C cause 60\%--70\% of the reported software vulnerabilities involving memory errors; 70\%--80\% of hacker attack vectors target these types. 142 142 Therefore, hardening these three C types goes a long way to make the majority of C programs safer. 143 143 -
libcfa/src/collections/array.hfa
r8614140 r79ba50c 69 69 // types like size_t. So trying to overload on ptrdiff_t vs int works in 64-bit mode 70 70 // but not in 32-bit mode. 71 // 72 // cfa -m32 (and gcc) cfa -m64 (and gcc) 73 // ptrdiff_t int long int 74 // size_t unsigned int unsigned long int 75 // typeof( sizeof(42) ) unsigned int unsigned long int 76 // int int int 71 // - Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it 72 // should give them type size_t. 73 // 74 // gcc -m32 cfa -m32 given bug gcc -m64 (and cfa) 75 // ptrdiff_t int int long int 76 // size_t unsigned int unsigned int unsigned long int 77 // typeof( sizeof(42) ) unsigned int unsigned long int unsigned long int 78 // int int int int 77 79 // 78 80 // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int} … … 81 83 // because assertion satisfaction requires types to match exacly. Both higher-dimensional 82 84 // subscripting and operations on slices use asserted subscript operators. The test case 83 // array-co llections/array-sbscr-types covers the combinations. Mike beleives that commenting out85 // array-container/array-sbscr-cases covers the combinations. Mike beleives that commenting out 84 86 // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit. 85 87 // Mike is open to being shown a smaller set of overloads that still passes the test. 86 87 88 88 89 static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, zero_t ) { … … 241 242 return this[[ab0,ab1,ab2]][bc]; 242 243 } 243 244 // Further form of -[-,-,-] that avoids using the trait system.245 // Above overloads work for any type with (recursively valid) subscript operator,246 // provided said subscript is passed as an assertion.247 // Below works only on arpk variations but never passes its subscript though an assertion.248 //249 // When arpk implements the trait used above,250 // the critical assertion is backed by a nontrivial thunk.251 // There is no "thunk problem" (lifetime) issue, when used as shown in the test suite.252 // But the optimizer has shown difficulty removing these thunks in cases where "it should,"253 // i.e. when all user code is in one compilation unit.254 // Not that every attempt at removing such a thunk fails; cases have been found going both ways.255 // Cases have been found with unnecessary bound-checks removed successfully,256 // on user code written against the overloads below,257 // but where these bound checks (which occur within `call`ed thunks) are not removed,258 // on user code written against the overloads above.259 //260 // The overloads below provide specializations of the above261 // that are a little harder to use than the ones above,262 // but where array API erasure has been seen to be more effective.263 // Note that the style below does not appeal to a case where thunk inlining is more effective;264 // rather, it simply does not rely on thunks in the first place.265 //266 // Both usage styles are shown in test array-md-sbscr-cases#numSubscrTypeCompatibility,267 // with the more general one above being "high abstraction,"268 // and the more performant one below being "mid abstraction" and "low abstraction."269 //270 // A breadth of index types is not given here (providing -[size_t,size_t,...] only)271 // because these declarations are not feeding a trait, so safe implicit arithmetic conversion kiks in.272 // Even so, there may still be an un-met need for accepting273 // either ptrdiff_t or size_t (signed or unsigned)274 // because Mike has seen the optimizer resist removing bound checks when sign-conversion is in play.275 // "Only size_t" is meeting today's need276 // and no solution is known that avoids 2^D overloads for D dimensions277 // while offering multiple subscript types and staying assertion-free.278 //279 // This approach, of avoiding traits entirely, is likely incompatible with the original desire280 // to have one recursive multidimensional subscript operator (TRY_BROKEN_DESIRED_MD_SUBSCRIPT).281 // To make a single declaration work,282 // we would probably have to get better at coaxing the optimizer into inlining thunks.283 284 forall( [N2], S2*, [N1], S1*, Timmed1, Tbase )285 static inline Timmed1 & ?[?]( arpk( N2, S2, arpk( N1, S1, Timmed1, Tbase ), Tbase ) & this, size_t ix2, size_t ix1 ) {286 return this[ix2][ix1];287 }288 289 forall( [N3], S3*, [N2], S2*, [N1], S1*, Timmed1, Tbase )290 static inline Timmed1 & ?[?]( arpk( N3, S3, arpk( N2, S2, arpk( N1, S1, Timmed1, Tbase ), Tbase ), Tbase ) & this, size_t ix3, size_t ix2, size_t ix1 ) {291 return this[ix3][ix2][ix1];292 }293 294 forall( [N4], S4*, [N3], S3*, [N2], S2*, [N1], S1*, Timmed1, Tbase )295 static inline Timmed1 & ?[?]( arpk( N4, S4, arpk( N3, S3, arpk( N2, S2, arpk( N1, S1, Timmed1, Tbase ), Tbase ), Tbase ), Tbase ) & this, size_t ix4, size_t ix3, size_t ix2, size_t ix1 ) {296 return this[ix4][ix3][ix2][ix1];297 }298 299 300 244 301 245 #endif -
tests/array-collections/array-md-sbscr-cases.cfa
r8614140 r79ba50c 231 231 } 232 232 233 // common function body, working on parameter wxyz, but for wxyz being different types234 #define CHECK_NUM_SUBSCR_TYPE_COMPAT \235 valExpected = getMagicNumber(2, 3, 4, 5); \236 assert(( wxyz[2] [3] [4] [5] == valExpected )); \237 assert(( wxyz[2, 3] [4] [5] == valExpected )); \238 assert(( wxyz[2] [3, 4] [5] == valExpected )); \239 assert(( wxyz[2] [3] [4, 5] == valExpected )); \240 assert(( wxyz[2, 3, 4] [5] == valExpected )); \241 assert(( wxyz[2] [3, 4, 5] == valExpected )); \242 assert(( wxyz[2, 3, 4, 5] == valExpected )); \243 for ( i; Nw ) { \244 assert(( wxyz[ i, 3, 4, 5 ] == getMagicNumber(i, 3, 4, 5) )); \245 } \246 for ( i; Nx ) { \247 assert(( wxyz[ 2, i, 4, 5 ] == getMagicNumber(2, i, 4, 5) )); \248 } \249 for ( i; Ny ) { \250 assert(( wxyz[ 2, 3, i, 5 ] == getMagicNumber(2, 3, i, 5) )); \251 } \252 for ( i; Nz ) { \253 assert(( wxyz[ 2, 3, 4, i ] == getMagicNumber(2, 3, 4, i) )); \254 }255 #define CHECK_NUM_SUBSCR_TYPE_COMPAT_ADDENDUM_RESHAPE \256 for ( i; Nw ) { \257 assert(( wxyz[ i, all, 4, 5 ][3] == getMagicNumber(i, 3, 4, 5) )); \258 } \259 for ( i; Nw ) { \260 assert(( wxyz[ all, 3, 4, 5 ][i] == getMagicNumber(i, 3, 4, 5) )); \261 }262 263 // Low abstraction: simple declaration, cannot send a slice, can make a slice, runs fast264 forall( [Nw], [Nx], [Ny], [Nz] )265 void test_numSubscrTypeCompatibility_lo( array( float, Nw, Nx, Ny, Nz ) & wxyz ) {266 CHECK_NUM_SUBSCR_TYPE_COMPAT267 CHECK_NUM_SUBSCR_TYPE_COMPAT_ADDENDUM_RESHAPE268 }269 270 // Medium abstraction: complex declaration, can send or make a slice, runs fast271 forall( [Nw], Sw*272 , [Nx], Sx*273 , [Ny], Sy*274 , [Nz], Sz* )275 void test_numSubscrTypeCompatibility_mid(276 arpk( Nw, Sw,277 arpk( Nx, Sx,278 arpk( Ny, Sy,279 arpk( Nz, Sz, float, float)280 , float)281 , float)282 , float) & wxyz283 ) {284 CHECK_NUM_SUBSCR_TYPE_COMPAT285 CHECK_NUM_SUBSCR_TYPE_COMPAT_ADDENDUM_RESHAPE286 }287 288 // High abstraction: mid-complexity declaration, can send a slice or a non-arpk, cannot make a slice, may not run fast289 forall( [Nw], Awxyz &290 , [Nx], Axyz &291 , [Ny], Ayz &292 , [Nz], Az &293 | ar( Awxyz, Axyz, Nw )294 | ar( Axyz, Ayz, Nx )295 | ar( Ayz, Az, Ny )296 | ar( Az, float, Nz ) )297 void test_numSubscrTypeCompatibility_hi( Awxyz & wxyz ) {298 CHECK_NUM_SUBSCR_TYPE_COMPAT299 }300 301 233 forall( [Nw], [Nx], [Ny], [Nz] ) 302 234 void test_numSubscrTypeCompatibility( tag(Nw), tag(Nx), tag(Ny), tag(Nz) ) { … … 305 237 fillHelloData(wxyz); 306 238 307 test_numSubscrTypeCompatibility_lo ( wxyz ); 308 test_numSubscrTypeCompatibility_mid( wxyz ); 309 test_numSubscrTypeCompatibility_hi ( wxyz ); 239 valExpected = getMagicNumber(2, 3, 4, 5); 240 assert(( wxyz [2] [3] [4] [5] == valExpected )); 241 assert(( wxyz[2, 3][4] [5] == valExpected )); 242 assert(( wxyz [2][3, 4][5] == valExpected )); 243 assert(( wxyz [2] [3][4, 5] == valExpected )); 244 assert(( wxyz[2, 3, 4][5] == valExpected )); 245 assert(( wxyz [2][3, 4, 5] == valExpected )); 246 assert(( wxyz[2, 3, 4, 5] == valExpected )); 247 248 for ( i; Nw ) { 249 assert(( wxyz[ i, 3, 4, 5 ] == getMagicNumber(i, 3, 4, 5) )); 250 } 251 252 for ( i; Nx ) { 253 assert(( wxyz[ 2, i, 4, 5 ] == getMagicNumber(2, i, 4, 5) )); 254 } 255 256 for ( i; Ny ) { 257 assert(( wxyz[ 2, 3, i, 5 ] == getMagicNumber(2, 3, i, 5) )); 258 } 259 260 for ( i; Nz ) { 261 assert(( wxyz[ 2, 3, 4, i ] == getMagicNumber(2, 3, 4, i) )); 262 } 263 264 for ( i; Nw ) { 265 assert(( wxyz[ i, all, 4, 5 ][3] == getMagicNumber(i, 3, 4, 5) )); 266 } 267 268 for ( i; Nw ) { 269 assert(( wxyz[ all, 3, 4, 5 ][i] == getMagicNumber(i, 3, 4, 5) )); 270 } 310 271 } 311 272
Note:
See TracChangeset
for help on using the changeset viewer.