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 7600a3b5a2..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
-stack-checker.state compiler.tree.copy-equiv ;
+USING: assocs namespaces sequences kernel math combinators sets
+fry stack-checker.state compiler.tree.copy-equiv
+compiler.tree.escape-analysis.graph ;
 IN: compiler.tree.escape-analysis.allocations
 
 SYMBOL: escaping
@@ -13,7 +14,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 ;
@@ -21,8 +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 )
-    <value> [ introduce-value ] [ slot-merging get set-at ] [ ] tri ;
+    dup [ ] contains? [
+        <value>
+        [ introduce-value ]
+        [ slot-graph get add-edges ]
+        [ ] tri
+    ] [ drop f ] if ;
+
+! 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 -- )
+    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 -- ? )
+    escaping-allocations get key? ;
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..83cdfd980b
--- /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 classes.tuple.private ;
+
+\ escape-analysis must-infer
+
+: count-unboxed-allocations ( quot -- sizes )
+    build-tree
+    normalize
+    compute-copy-equiv
+    propagate
+    cleanup
+    escape-analysis
+    0 swap [
+        dup #call?
+        [
+            dup word>> \ <tuple-boa> = [
+                out-d>> first escaping-allocation? [ 1+ ] unless
+            ] [ drop ] 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..c41627005b 100644
--- a/unfinished/compiler/tree/escape-analysis/escape-analysis.factor
+++ b/unfinished/compiler/tree/escape-analysis/escape-analysis.factor
@@ -3,16 +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
-    <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 cc6ac57a5e..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
 
@@ -24,6 +23,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 ] }
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 ;