From cf46a832e72ba6533e31734c42f196743fd48931 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 8 Oct 2008 23:42:53 -0500
Subject: [PATCH] Debugging register allocator and inline allocation

---
 basis/compiler/cfg/builder/builder.factor     |  6 +--
 .../linear-scan/allocation/allocation.factor  | 33 +++++++++--------
 .../cfg/linear-scan/linear-scan-tests.factor  | 16 ++++++++
 .../cfg/linear-scan/linear-scan.factor        | 10 ++---
 basis/compiler/cfg/stacks/stacks.factor       | 30 +++++++--------
 basis/cpu/architecture/architecture.factor    |  4 +-
 basis/cpu/x86/allot/allot.factor              | 37 ++++++++++---------
 7 files changed, 78 insertions(+), 58 deletions(-)

diff --git a/basis/compiler/cfg/builder/builder.factor b/basis/compiler/cfg/builder/builder.factor
index 1a8eae0643..50101c3cdf 100755
--- a/basis/compiler/cfg/builder/builder.factor
+++ b/basis/compiler/cfg/builder/builder.factor
@@ -250,9 +250,9 @@ M: #dispatch emit-node
 
 : emit-intrinsic ( word -- next )
     {
-        { \ (tuple) [ allot-size 2 cells + tuple tuple emit-allot ] }
-        { \ (array) [ allot-size 2 cells + array object emit-allot ] }
-        { \ (byte-array) [ allot-size cells 2 + byte-array object emit-allot ] }
+        { \ (tuple) [ allot-size 2 + cells tuple tuple emit-allot ] }
+        { \ (array) [ allot-size 2 + cells array object emit-allot ] }
+        { \ (byte-array) [ allot-size 2 cells + byte-array object emit-allot ] }
         { \ (complex) [ 3 cells complex complex emit-allot ] }
         { \ (ratio) [ 3 cells ratio ratio emit-allot ] }
         { \ (wrapper) [ 2 cells wrapper object emit-allot ] }
diff --git a/basis/compiler/cfg/linear-scan/allocation/allocation.factor b/basis/compiler/cfg/linear-scan/allocation/allocation.factor
index 4d1d8543bf..5433908768 100644
--- a/basis/compiler/cfg/linear-scan/allocation/allocation.factor
+++ b/basis/compiler/cfg/linear-scan/allocation/allocation.factor
@@ -24,15 +24,21 @@ SYMBOL: active-intervals
 : delete-active ( live-interval -- )
     active-intervals get delete ;
 
+: expired-interval? ( n interval -- ? )
+    [ end>> ] [ start>> ] bi or > ;
+
 : expire-old-intervals ( n -- )
     active-intervals get
-    swap '[ end>> _ < ] partition
-    active-intervals set
-    [ deallocate-register ] each ;
+    [ expired-interval? ] with partition
+    [ [ deallocate-register ] each ] [ active-intervals set ] bi* ;
 
 : expire-old-uses ( n -- )
     active-intervals get
-    swap '[ uses>> dup peek _ < [ pop* ] [ drop ] if ] each ;
+    swap '[
+        uses>> [
+            dup peek _ < [ pop* ] [ drop ] if
+        ] unless-empty
+    ] each ;
 
 : update-state ( live-interval -- )
     start>> [ expire-old-intervals ] [ expire-old-uses ] bi ;
@@ -59,13 +65,7 @@ SYMBOL: progress
     unhandled-intervals get heap-push-all ;
 
 : assign-free-register ( live-interval registers -- )
-    #! If the live interval does not have any uses, it means it
-    #! will be spilled immediately, so it still needs a register
-    #! to compute the new value, but we don't add the interval
-    #! to the active set and we don't remove the register from
-    #! the free list.
-    over uses>> empty?
-    [ peek >>reg drop ] [ pop >>reg add-active ] if ;
+    pop >>reg add-active ;
 
 ! Spilling
 SYMBOL: spill-counts
@@ -75,7 +75,9 @@ SYMBOL: spill-counts
 
 : interval-to-spill ( -- live-interval )
     #! We spill the interval with the most distant use location.
-    active-intervals get unclip-slice [
+    active-intervals get
+    [ uses>> empty? not ] filter
+    unclip-slice [
         [ [ uses>> peek ] bi@ > ] most
     ] reduce ;
 
@@ -95,15 +97,16 @@ SYMBOL: spill-counts
 
 : assign-spill ( before after -- before after )
     #! If it has been spilled already, reuse spill location.
-    over reload-from>> [ next-spill-location ] unless*
+    USE: cpu.architecture ! XXX
+    over reload-from>>
+    [ int-regs next-spill-location ] unless*
     tuck [ >>spill-to ] [ >>reload-from ] 2bi* ;
 
 : split-and-spill ( live-interval -- before after )
     dup split-interval [ record-split ] [ assign-spill ] 2bi ;
 
 : reuse-register ( new existing -- )
-    reg>> >>reg
-    dup uses>> empty? [ deallocate-register ] [ add-active ] if ;
+    reg>> >>reg add-active ;
 
 : spill-existing ( new existing -- )
     #! Our new interval will be used before the active interval
diff --git a/basis/compiler/cfg/linear-scan/linear-scan-tests.factor b/basis/compiler/cfg/linear-scan/linear-scan-tests.factor
index 8f1378755d..f64534227e 100644
--- a/basis/compiler/cfg/linear-scan/linear-scan-tests.factor
+++ b/basis/compiler/cfg/linear-scan/linear-scan-tests.factor
@@ -2,6 +2,8 @@ IN: compiler.cfg.linear-scan.tests
 USING: tools.test random sorting sequences sets hashtables assocs
 kernel fry arrays splitting namespaces math accessors vectors
 math.order
+cpu.architecture
+compiler.cfg.instructions
 compiler.cfg.registers
 compiler.cfg.linear-scan
 compiler.cfg.linear-scan.live-intervals
@@ -103,3 +105,17 @@ SYMBOL: max-uses
 USING: math.private compiler.cfg.debugger ;
 
 [ ] [ [ float+ float>fixnum 3 fixnum*fast ] test-mr first linear-scan drop ] unit-test
+
+[ f ] [
+    T{ ##allot
+        f
+        T{ vreg f int-regs 1 }
+        40
+        array
+        object
+        T{ vreg f int-regs 2 }
+        T{ vreg f int-regs 3 }
+        f
+    } clone
+    1array (linear-scan) first regs>> values all-equal?
+] unit-test
diff --git a/basis/compiler/cfg/linear-scan/linear-scan.factor b/basis/compiler/cfg/linear-scan/linear-scan.factor
index 046f2a7eff..4628728299 100644
--- a/basis/compiler/cfg/linear-scan/linear-scan.factor
+++ b/basis/compiler/cfg/linear-scan/linear-scan.factor
@@ -22,12 +22,12 @@ IN: compiler.cfg.linear-scan
 ! by Omri Traub, Glenn Holloway, Michael D. Smith
 ! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.8435
 
+: (linear-scan) ( insns -- insns' )
+    dup compute-live-intervals
+    machine-registers allocate-registers assign-registers ;
+
 : linear-scan ( mr -- mr' )
     [
-        [
-            dup compute-live-intervals
-            machine-registers allocate-registers
-            assign-registers
-        ] change-instructions
+        [ (linear-scan) ] change-instructions
         ! spill-counts get >>spill-counts
     ] with-scope ;
diff --git a/basis/compiler/cfg/stacks/stacks.factor b/basis/compiler/cfg/stacks/stacks.factor
index 62663bdad0..94557c9320 100755
--- a/basis/compiler/cfg/stacks/stacks.factor
+++ b/basis/compiler/cfg/stacks/stacks.factor
@@ -24,7 +24,7 @@ GENERIC: lazy-store ( dst src -- )
 GENERIC: minimal-ds-loc* ( min obj -- min )
 
 ! This will be a multimethod soon
-DEFER: %move
+DEFER: ##move
 
 PRIVATE>
 
@@ -62,7 +62,7 @@ M: cached (lazy-load) >r vreg>> r> (lazy-load) ;
 M: cached (eager-load) >r vreg>> r> (eager-load) ;
 M: cached lazy-store
     2dup loc>> live-loc?
-    [ "live-locs" get at %move ] [ 2drop ] if ;
+    [ "live-locs" get at ##move ] [ 2drop ] if ;
 M: cached minimal-ds-loc* loc>> minimal-ds-loc* ;
 
 M: tagged move-spec drop f ;
@@ -78,9 +78,9 @@ M: unboxed-c-ptr move-spec class ;
 M: constant move-spec class ;
 
 ! Moving values between locations and registers
-: %move-bug ( -- * ) "Bug in generator.registers" throw ;
+: ##move-bug ( -- * ) "Bug in generator.registers" throw ;
 
-: %unbox-c-ptr ( dst src -- )
+: ##unbox-c-ptr ( dst src -- )
     dup value-class {
         { [ dup \ f class<= ] [ drop ##unbox-f ] }
         { [ dup simple-alien class<= ] [ drop ##unbox-alien ] }
@@ -88,15 +88,15 @@ M: constant move-spec class ;
         [ drop ##unbox-any-c-ptr ]
     } cond ; inline
 
-: %move-via-temp ( dst src -- )
+: ##move-via-temp ( dst src -- )
     #! For many transfers, such as loc to unboxed-alien, we
     #! don't have an intrinsic, so we transfer the source to
     #! temp then temp to the destination.
-    int-regs next-vreg [ over %move value-class ] keep
+    int-regs next-vreg [ over ##move value-class ] keep
     tagged new
         swap >>vreg
         swap >>class
-    %move ;
+    ##move ;
 
 ! Operands holding pointers to freshly-allocated objects which
 ! are guaranteed to be in the nursery
@@ -106,7 +106,7 @@ SYMBOL: fresh-objects
 
 : fresh-object? ( vreg -- ? ) fresh-objects get memq? ;
 
-: %move ( dst src -- )
+: ##move ( dst src -- )
     2dup [ move-spec ] bi@ 2array {
         { { f f } [ ##copy ] }
         { { unboxed-alien unboxed-alien } [ ##copy ] }
@@ -115,8 +115,8 @@ SYMBOL: fresh-objects
         { { unboxed-c-ptr unboxed-c-ptr } [ ##copy ] }
         { { float float } [ ##copy-float ] }
 
-        { { f unboxed-c-ptr } [ %move-bug ] }
-        { { f unboxed-byte-array } [ %move-bug ] }
+        { { f unboxed-c-ptr } [ ##move-bug ] }
+        { { f unboxed-byte-array } [ ##move-bug ] }
 
         { { f constant } [ value>> ##load-literal ] }
 
@@ -128,10 +128,10 @@ SYMBOL: fresh-objects
         { { unboxed-alien f } [ ##unbox-alien ] }
         { { unboxed-byte-array f } [ ##unbox-byte-array ] }
         { { unboxed-f f } [ ##unbox-f ] }
-        { { unboxed-c-ptr f } [ %unbox-c-ptr ] }
+        { { unboxed-c-ptr f } [ ##unbox-c-ptr ] }
         { { loc f } [ swap ##replace ] }
 
-        [ drop %move-via-temp ]
+        [ drop ##move-via-temp ]
     } case ;
 
 ! A compile-time stack
@@ -264,10 +264,10 @@ M: value (lazy-load)
 
 M: value (eager-load) ( value spec -- vreg )
     [ alloc-vreg-for ] [ drop ] 2bi
-    [ %move ] [ drop ] 2bi ;
+    [ ##move ] [ drop ] 2bi ;
 
 M: loc lazy-store
-    2dup live-loc? [ "live-locs" get at %move ] [ 2drop ] if ;
+    2dup live-loc? [ "live-locs" get at ##move ] [ 2drop ] if ;
 
 : finalize-locs ( -- )
     #! Perform any deferred stack shuffling.
@@ -279,7 +279,7 @@ M: loc lazy-store
 : finalize-vregs ( -- )
     #! Store any vregs to their final stack locations.
     [
-        dup loc? over cached? or [ 2drop ] [ %move ] if
+        dup loc? over cached? or [ 2drop ] [ ##move ] if
     ] each-loc ;
 
 : clear-phantoms ( -- )
diff --git a/basis/cpu/architecture/architecture.factor b/basis/cpu/architecture/architecture.factor
index deed160cc3..230cc18814 100644
--- a/basis/cpu/architecture/architecture.factor
+++ b/basis/cpu/architecture/architecture.factor
@@ -88,7 +88,7 @@ HOOK: %copy-float cpu ( dst src -- )
 
 ! Box and unbox floats
 HOOK: %unbox-float cpu ( dst src -- )
-HOOK: %box-float cpu ( dst src -- )
+HOOK: %box-float cpu ( dst src temp -- )
 
 ! FFI stuff
 
@@ -184,7 +184,7 @@ HOOK: %unbox-f cpu ( dst src -- )
 
 HOOK: %unbox-any-c-ptr cpu ( dst src -- )
 
-HOOK: %box-alien cpu ( dst src -- )
+HOOK: %box-alien cpu ( dst src temp1 temp2 -- )
 
 ! Allocation
 HOOK: %allot cpu ( dst size type tag temp -- )
diff --git a/basis/cpu/x86/allot/allot.factor b/basis/cpu/x86/allot/allot.factor
index 7dfd1f4096..659f55af41 100644
--- a/basis/cpu/x86/allot/allot.factor
+++ b/basis/cpu/x86/allot/allot.factor
@@ -12,34 +12,34 @@ M:: x86 %write-barrier ( src temp -- )
     ! Mark the card
     src card-bits SHR
     "cards_offset" f temp %alien-global
-    temp temp [+] card-mark <byte> MOV
+    temp src [+] card-mark <byte> MOV
 
     ! Mark the card deck
-    temp deck-bits card-bits - SHR
+    src deck-bits card-bits - SHR
     "decks_offset" f temp %alien-global
-    temp temp [+] card-mark <byte> MOV ;
+    temp src [+] card-mark <byte> MOV ;
 
 : load-zone-ptr ( reg -- )
     #! Load pointer to start of zone array
     0 MOV "nursery" f rc-absolute-cell rel-dlsym ;
 
-: load-allot-ptr ( temp -- )
-    [ load-zone-ptr ] [ PUSH ] [ dup cell [+] MOV ] tri ;
+: load-allot-ptr ( nursery-ptr allot-ptr -- )
+    [ drop load-zone-ptr ] [ swap cell [+] MOV ] 2bi ;
 
-: inc-allot-ptr ( n temp -- )
-    [ POP ] [ cell [+] swap 8 align ADD ] bi ;
+: inc-allot-ptr ( nursery-ptr n -- )
+    [ cell [+] ] dip 8 align ADD ;
 
 : store-header ( temp type -- )
-    [ 0 [+] ] [ type-number tag-fixnum ] bi* MOV ;
+    [ [] ] [ type-number tag-fixnum ] bi* MOV ;
 
-: store-tagged ( dst temp tag -- )
-    dupd tag-number OR MOV ;
+: store-tagged ( dst tag -- )
+    tag-number OR ;
 
-M:: x86 %allot ( dst size type tag temp -- )
-    temp load-allot-ptr
-    temp type store-header
-    temp size inc-allot-ptr
-    dst temp store-tagged ;
+M:: x86 %allot ( dst size type tag nursery-ptr -- )
+    nursery-ptr dst load-allot-ptr
+    dst type store-header
+    dst tag store-tagged
+    nursery-ptr size inc-allot-ptr ;
 
 M: x86 %gc ( -- )
     "end" define-label
@@ -130,10 +130,11 @@ M:: x86 %box-alien ( dst src temp -- )
 
 \ fixnum>bignum [
     "x" operand %untag-fixnum
-    "x" operand dup "scratch" operand %allot-bignum-signed-1
+    "y" operand "x" operand "scratch" operand %allot-bignum-signed-1
 ] T{ template
     { input { { f "x" } } }
-    { scratch { { f "scratch" } } }
-    { output { "x" } }
+    { scratch { { f "y" } { f "scratch" } } }
+    { output { "y" } }
+    { clobber { "x" } }
     { gc t }
 } define-intrinsic