From d14efabed37ce9c9727924fbf8be34aa72db18db Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 2 Aug 2008 20:21:25 -0500 Subject: [PATCH 1/2] Working on escape analysis --- .../allocations/allocations.factor | 26 +++- .../escape-analysis/branches/branches.factor | 10 +- .../escape-analysis-tests.factor | 130 ++++++++++++++++++ .../escape-analysis/escape-analysis.factor | 1 + .../tree/escape-analysis/simple/simple.factor | 3 + 5 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor diff --git a/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor b/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor index 7600a3b5a2..59febb3801 100644 --- a/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor +++ b/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor @@ -1,6 +1,6 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: assocs namespaces sequences kernel math +USING: assocs namespaces sequences kernel math combinators sets stack-checker.state compiler.tree.copy-equiv ; IN: compiler.tree.escape-analysis.allocations @@ -13,7 +13,11 @@ SYMBOL: allocations resolve-copy allocations get at ; : record-allocation ( allocation value -- ) - allocations get set-at ; + { + { [ dup not ] [ 2drop ] } + { [ over not ] [ allocations get delete-at drop ] } + [ allocations get set-at ] + } cond ; : record-allocations ( allocations values -- ) [ record-allocation ] 2each ; @@ -25,4 +29,20 @@ SYMBOL: allocations SYMBOL: slot-merging : merge-slots ( values -- value ) - <value> [ introduce-value ] [ slot-merging get set-at ] [ ] tri ; + dup [ ] contains? [ + <value> + [ introduce-value ] + [ slot-merging get set-at ] + [ ] tri + ] [ drop f ] if ; + +! If an allocation's slot appears in this set, the allocation +! is disqualified from unboxing. +SYMBOL: disqualified + +: disqualify ( slot-value -- ) + [ disqualified get conjoin ] + [ slot-merging get at [ disqualify ] each ] bi ; + +: escaping-allocation? ( value -- ? ) + allocation [ [ disqualified get key? ] contains? ] [ t ] if* ; diff --git a/unfinished/compiler/tree/escape-analysis/branches/branches.factor b/unfinished/compiler/tree/escape-analysis/branches/branches.factor index 23e53fd4fe..1bd6973369 100644 --- a/unfinished/compiler/tree/escape-analysis/branches/branches.factor +++ b/unfinished/compiler/tree/escape-analysis/branches/branches.factor @@ -1,6 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors kernel namespaces sequences +USING: accessors kernel namespaces sequences sets +stack-checker.branches compiler.tree compiler.tree.propagation.branches compiler.tree.escape-analysis.nodes @@ -12,6 +13,9 @@ SYMBOL: children-escape-data M: #branch escape-analysis* live-children sift [ (escape-analysis) ] each ; +: disqualify-allocations ( allocations -- ) + [ [ disqualify ] each ] each ; + : (merge-allocations) ( values -- allocation ) [ [ allocation ] map dup [ ] all? [ @@ -19,8 +23,8 @@ M: #branch escape-analysis* flip [ (merge-allocations) ] [ [ merge-slots ] map ] bi [ record-allocations ] keep - ] [ drop f ] if - ] [ drop f ] if + ] [ disqualify-allocations f ] if + ] [ disqualify-allocations f ] if ] map ; : merge-allocations ( in-values out-values -- ) diff --git a/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor b/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor new file mode 100644 index 0000000000..34ecc74813 --- /dev/null +++ b/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor @@ -0,0 +1,130 @@ +IN: compiler.tree.escape-analysis.tests +USING: compiler.tree.escape-analysis +compiler.tree.escape-analysis.allocations compiler.tree.builder +compiler.tree.normalization compiler.tree.copy-equiv +compiler.tree.propagation compiler.tree.cleanup +compiler.tree.combinators compiler.tree sequences math +kernel tools.test accessors slots.private quotations.private +prettyprint ; + +\ escape-analysis must-infer + +: count-unboxed-allocations ( quot -- sizes ) + build-tree + normalize + compute-copy-equiv + propagate + cleanup + escape-analysis + 0 swap [ + dup #call? + [ + out-d>> dup empty? [ drop ] [ + first escaping-allocation? [ 1+ ] unless + ] if + ] [ drop ] if + ] each-node ; + +[ 0 ] [ [ [ + ] curry ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry drop ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry 3 slot ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry 3 slot drop ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry uncurry ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry call ] count-unboxed-allocations ] unit-test + +[ 1 ] [ [ [ + ] curry call ] count-unboxed-allocations ] unit-test + +[ 0 ] [ [ [ [ + ] curry ] [ drop [ ] ] if ] count-unboxed-allocations ] unit-test + +[ 2 ] [ + [ [ [ + ] curry ] [ [ * ] curry ] if uncurry ] count-unboxed-allocations +] unit-test + +[ 0 ] [ + [ [ [ + ] curry ] [ [ * ] curry ] if ] count-unboxed-allocations +] unit-test + +[ 3 ] [ + [ [ [ + ] curry ] [ dup [ [ * ] curry ] [ [ / ] curry ] if ] if uncurry ] count-unboxed-allocations +] unit-test + +[ 2 ] [ + [ [ [ + ] curry 4 ] [ dup [ [ * ] curry ] [ [ / ] curry ] if uncurry ] if ] count-unboxed-allocations +] unit-test + +[ 0 ] [ + [ [ [ + ] curry ] [ dup [ [ * ] curry ] [ [ / ] curry ] if ] if ] count-unboxed-allocations +] unit-test + +TUPLE: cons { car read-only } { cdr read-only } ; + +[ 0 ] [ + [ + dup 0 = [ + 2 cons boa + ] [ + dup 1 = [ + 3 cons boa + ] when + ] if car>> + ] count-unboxed-allocations +] unit-test + +[ 3 ] [ + [ + dup 0 = [ + 2 cons boa + ] [ + dup 1 = [ + 3 cons boa + ] [ + 4 cons boa + ] if + ] if car>> + ] count-unboxed-allocations +] unit-test + +[ 0 ] [ + [ + dup 0 = [ + dup 1 = [ + 3 cons boa + ] [ + 4 cons boa + ] if + ] unless car>> + ] count-unboxed-allocations +] unit-test + +[ 2 ] [ + [ + dup 0 = [ + 2 cons boa + ] [ + dup 1 = [ + 3 cons boa + ] [ + 4 cons boa + ] if car>> + ] if + ] count-unboxed-allocations +] unit-test + +[ 0 ] [ + [ + dup 0 = [ + 2 cons boa + ] [ + dup 1 = [ + 3 cons boa dup . + ] [ + 4 cons boa + ] if + ] if drop + ] count-unboxed-allocations +] unit-test diff --git a/unfinished/compiler/tree/escape-analysis/escape-analysis.factor b/unfinished/compiler/tree/escape-analysis/escape-analysis.factor index 490fff82ec..e8c02046f2 100644 --- a/unfinished/compiler/tree/escape-analysis/escape-analysis.factor +++ b/unfinished/compiler/tree/escape-analysis/escape-analysis.factor @@ -14,5 +14,6 @@ IN: compiler.tree.escape-analysis : escape-analysis ( node -- node ) H{ } clone slot-merging set H{ } clone allocations set + H{ } clone disqualified set <hashed-dlist> work-list set dup (escape-analysis) ; diff --git a/unfinished/compiler/tree/escape-analysis/simple/simple.factor b/unfinished/compiler/tree/escape-analysis/simple/simple.factor index cc6ac57a5e..93d0b28be3 100644 --- a/unfinished/compiler/tree/escape-analysis/simple/simple.factor +++ b/unfinished/compiler/tree/escape-analysis/simple/simple.factor @@ -24,6 +24,9 @@ IN: compiler.tree.escape-analysis.simple [ in-d>> first ] tri over fixnum? [ [ 3 - ] dip record-slot-access ] [ 3drop ] if ; +: add-escaping-values ( values -- ) + [ allocation [ disqualify ] each ] each ; + M: #call escape-analysis* dup word>> { { \ <tuple-boa> [ record-tuple-allocation ] } From d41bc716bfb26d79a579dfc669baed7026c06c70 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sun, 3 Aug 2008 05:01:05 -0500 Subject: [PATCH 2/2] More escape analysis work --- .../dataflow-analysis.factor | 6 +-- .../allocations/allocations.factor | 30 ++++++++++----- .../escape-analysis-tests.factor | 8 ++-- .../escape-analysis/escape-analysis.factor | 11 +++--- .../escape-analysis/graph/graph-tests.factor | 19 ++++++++++ .../tree/escape-analysis/graph/graph.factor | 38 +++++++++++++++++++ .../tree/escape-analysis/simple/simple.factor | 1 - .../work-list/work-list.factor | 9 ----- 8 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 unfinished/compiler/tree/escape-analysis/graph/graph-tests.factor create mode 100644 unfinished/compiler/tree/escape-analysis/graph/graph.factor delete mode 100644 unfinished/compiler/tree/escape-analysis/work-list/work-list.factor diff --git a/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor b/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor index b6772650b6..c7d558f4bf 100644 --- a/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor +++ b/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor @@ -8,11 +8,9 @@ IN: compiler.tree.dataflow-analysis ! Dataflow analysis SYMBOL: work-list -: look-at-value ( values -- ) - work-list get push-front ; +: look-at-value ( values -- ) work-list get push-front ; -: look-at-values ( values -- ) - work-list get '[ , push-front ] each ; +: look-at-values ( values -- ) work-list get push-all-front ; : look-at-inputs ( node -- ) in-d>> look-at-values ; diff --git a/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor b/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor index 59febb3801..09c20a93dc 100644 --- a/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor +++ b/unfinished/compiler/tree/escape-analysis/allocations/allocations.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: assocs namespaces sequences kernel math combinators sets -stack-checker.state compiler.tree.copy-equiv ; +fry stack-checker.state compiler.tree.copy-equiv +compiler.tree.escape-analysis.graph ; IN: compiler.tree.escape-analysis.allocations SYMBOL: escaping @@ -25,24 +26,33 @@ SYMBOL: allocations : record-slot-access ( out slot# in -- ) over zero? [ 3drop ] [ allocation ?nth swap is-copy-of ] if ; -! A map from values to sequences of values -SYMBOL: slot-merging +! We track available values +SYMBOL: slot-graph : merge-slots ( values -- value ) dup [ ] contains? [ <value> [ introduce-value ] - [ slot-merging get set-at ] + [ slot-graph get add-edges ] [ ] tri ] [ drop f ] if ; -! If an allocation's slot appears in this set, the allocation -! is disqualified from unboxing. -SYMBOL: disqualified +! A disqualified slot value is not available for unboxing. A +! tuple may be unboxed if none of its slots have been +! disqualified. : disqualify ( slot-value -- ) - [ disqualified get conjoin ] - [ slot-merging get at [ disqualify ] each ] bi ; + slot-graph get mark-vertex ; + +SYMBOL: escaping-allocations + +: compute-escaping-allocations ( -- ) + #! Any allocations involving unavailable slots are + #! potentially escaping, and cannot be unboxed. + allocations get + slot-graph get marked-components + '[ [ , key? ] contains? nip ] assoc-filter + escaping-allocations set ; : escaping-allocation? ( value -- ? ) - allocation [ [ disqualified get key? ] contains? ] [ t ] if* ; + escaping-allocations get key? ; diff --git a/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor b/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor index 34ecc74813..83cdfd980b 100644 --- a/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor +++ b/unfinished/compiler/tree/escape-analysis/escape-analysis-tests.factor @@ -5,7 +5,7 @@ compiler.tree.normalization compiler.tree.copy-equiv compiler.tree.propagation compiler.tree.cleanup compiler.tree.combinators compiler.tree sequences math kernel tools.test accessors slots.private quotations.private -prettyprint ; +prettyprint classes.tuple.private ; \ escape-analysis must-infer @@ -19,9 +19,9 @@ prettyprint ; 0 swap [ dup #call? [ - out-d>> dup empty? [ drop ] [ - first escaping-allocation? [ 1+ ] unless - ] if + dup word>> \ <tuple-boa> = [ + out-d>> first escaping-allocation? [ 1+ ] unless + ] [ drop ] if ] [ drop ] if ] each-node ; diff --git a/unfinished/compiler/tree/escape-analysis/escape-analysis.factor b/unfinished/compiler/tree/escape-analysis/escape-analysis.factor index e8c02046f2..c41627005b 100644 --- a/unfinished/compiler/tree/escape-analysis/escape-analysis.factor +++ b/unfinished/compiler/tree/escape-analysis/escape-analysis.factor @@ -3,17 +3,16 @@ USING: kernel namespaces search-dequeues compiler.tree compiler.tree.def-use +compiler.tree.escape-analysis.graph compiler.tree.escape-analysis.allocations compiler.tree.escape-analysis.recursive compiler.tree.escape-analysis.branches compiler.tree.escape-analysis.nodes -compiler.tree.escape-analysis.simple -compiler.tree.escape-analysis.work-list ; +compiler.tree.escape-analysis.simple ; IN: compiler.tree.escape-analysis : escape-analysis ( node -- node ) - H{ } clone slot-merging set H{ } clone allocations set - H{ } clone disqualified set - <hashed-dlist> work-list set - dup (escape-analysis) ; + <graph> slot-graph set + dup (escape-analysis) + compute-escaping-allocations ; diff --git a/unfinished/compiler/tree/escape-analysis/graph/graph-tests.factor b/unfinished/compiler/tree/escape-analysis/graph/graph-tests.factor new file mode 100644 index 0000000000..3a7dee58a9 --- /dev/null +++ b/unfinished/compiler/tree/escape-analysis/graph/graph-tests.factor @@ -0,0 +1,19 @@ +IN: compiler.tree.escape-analysis.graph.tests +USING: compiler.tree.escape-analysis.graph tools.test namespaces +accessors ; + +<graph> "graph" set + +[ ] [ { 2 3 4 } 1 "graph" get add-edges ] unit-test +[ ] [ { 5 6 } 2 "graph" get add-edges ] unit-test +[ ] [ { 7 8 } 9 "graph" get add-edges ] unit-test +[ ] [ { 6 10 } 4 "graph" get add-edges ] unit-test + +[ ] [ 3 "graph" get mark-vertex ] unit-test + +[ H{ { 1 1 } { 2 2 } { 3 3 } { 4 4 } { 5 5 } { 6 6 } { 10 10 } } ] +[ "graph" get marked>> ] unit-test + +[ ] [ { 1 11 } 12 "graph" get add-edges ] unit-test + +[ t ] [ 11 "graph" get marked-vertex? ] unit-test diff --git a/unfinished/compiler/tree/escape-analysis/graph/graph.factor b/unfinished/compiler/tree/escape-analysis/graph/graph.factor new file mode 100644 index 0000000000..59ba51d99e --- /dev/null +++ b/unfinished/compiler/tree/escape-analysis/graph/graph.factor @@ -0,0 +1,38 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel accessors assocs fry sequences sets +dequeues search-dequeues namespaces ; +IN: compiler.tree.escape-analysis.graph + +TUPLE: graph edges work-list ; + +: <graph> ( -- graph ) + H{ } clone <hashed-dlist> graph boa ; + +: mark-vertex ( vertex graph -- ) work-list>> push-front ; + +: add-edge ( out in graph -- ) + [ edges>> push-at ] [ swapd edges>> push-at ] 3bi ; + +: add-edges ( out-seq in graph -- ) + '[ , , add-edge ] each ; + +<PRIVATE + +SYMBOL: marked + +: (mark-vertex) ( vertex graph -- ) + over marked get key? [ 2drop ] [ + [ drop marked get conjoin ] + [ [ edges>> at ] [ work-list>> ] bi push-all-front ] + 2bi + ] if ; + +PRIVATE> + +: marked-components ( graph -- vertices ) + #! All vertices in connected components of marked vertices. + H{ } clone marked [ + [ work-list>> ] keep + '[ , (mark-vertex) ] slurp-dequeue + ] with-variable ; diff --git a/unfinished/compiler/tree/escape-analysis/simple/simple.factor b/unfinished/compiler/tree/escape-analysis/simple/simple.factor index 93d0b28be3..8329a04a61 100644 --- a/unfinished/compiler/tree/escape-analysis/simple/simple.factor +++ b/unfinished/compiler/tree/escape-analysis/simple/simple.factor @@ -6,7 +6,6 @@ combinators dequeues search-dequeues namespaces fry compiler.tree compiler.tree.propagation.info compiler.tree.escape-analysis.nodes -compiler.tree.escape-analysis.work-list compiler.tree.escape-analysis.allocations ; IN: compiler.tree.escape-analysis.simple diff --git a/unfinished/compiler/tree/escape-analysis/work-list/work-list.factor b/unfinished/compiler/tree/escape-analysis/work-list/work-list.factor deleted file mode 100644 index 8378ee43ae..0000000000 --- a/unfinished/compiler/tree/escape-analysis/work-list/work-list.factor +++ /dev/null @@ -1,9 +0,0 @@ -! Copyright (C) 2008 Slava Pestov. -! See http://factorcode.org/license.txt for BSD license. -USING: dequeues namespaces sequences fry ; -IN: compiler.tree.escape-analysis.work-list - -SYMBOL: work-list - -: add-escaping-values ( values -- ) - work-list get '[ , push-front ] each ;