start dataflow optimizer

cvs
Slava Pestov 2004-12-03 03:44:36 +00:00
parent ec849514bb
commit 00195a2d2b
21 changed files with 212 additions and 92 deletions

View File

@ -1,35 +1,40 @@
[error] AWT-EventQueue-0: java.lang.NullPointerException
[error] AWT-EventQueue-0: at org.gjt.sp.jedit.Buffer.markTokens(Buffer.java:2109)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.getWordAtCaret(WordPreview.java:95)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.showPreview(WordPreview.java:137)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.actionPerformed(WordPreview.java:79)
[error] AWT-EventQueue-0: at javax.swing.Timer.fireActionPerformed(Timer.java:271)
+ inference/interpreter:
[error] AWT-EventQueue-0: java.lang.NullPointerException
[error] AWT-EventQueue-0: at org.gjt.sp.jedit.Buffer.markTokens(Buffer.java:2109)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.getWordAtCaret(WordPreview.java:95)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.showPreview(WordPreview.java:137)
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.actionPerformed(WordPreview.java:79)
[error] AWT-EventQueue-0: at javax.swing.Timer.fireActionPerformed(Timer.java:271)
+ inference/dataflow:
- combinator inference
- type inference
- some way to step over a word in the stepper
- step: print NEXT word to execute, not word that JUST executed
- handle odd base cases, with code after ifte
- handle recursion with when, when* etc
- lifting
- stack ops and alien-call need special nodes
+ compiler/ffi:
+ linearizer/generator:
- compiling when*
- compiling each, etc.
- peephole optimizer
- linearize generic, 2generic
- generate conditionals
- generator needs to be aware of labels
- getenv/setenv: if literal arg, compile as a load/store
- inline words
- compiler: drop literal peephole optimization
+ compiler frontend:
- assembler opcodes dispatch on operand types
- save code in image
- compile word twice; no more 'cannot compile' error!
+ ffi:
- is signed -vs- unsigned pointers an issue?
- bitfields in C structs
- SDL_Rect** type
- struct membres that are not *
- FFI float types
- compile word twice; no more 'cannot compile' error!
- perhaps /i should work with all numbers
- assembler opcodes dispatch on operand types
- lifting
- save code in image
+ listener/plugin:
@ -57,6 +62,9 @@
+ misc:
- some way to step over a word in the stepper
- step: print NEXT word to execute, not word that JUST executed
- perhaps /i should work with all numbers
- unit test weirdness: 2 lines appears at end
- jedit ==> jedit-word, jedit takes a file name
- command line parsing cleanup

View File

@ -385,6 +385,7 @@ public class FactorPlugin extends EditPlugin
Buffer buffer = view.getBuffer();
int lastUseOffset = 0;
boolean leadingNewline = false;
boolean seenUse = false;
for(int i = 0; i < buffer.getLineCount(); i++)
{
@ -393,13 +394,14 @@ public class FactorPlugin extends EditPlugin
{
lastUseOffset = buffer.getLineEndOffset(i) - 1;
leadingNewline = true;
seenUse = true;
}
else if(text.startsWith("!"))
else if(text.startsWith("!") && !seenUse)
{
lastUseOffset = buffer.getLineEndOffset(i) - 1;
leadingNewline = true;
}
else if(text.length() == 0)
else if(text.length() == 0 && !seenUse)
{
if(i == 0)
lastUseOffset = 0;

View File

@ -113,6 +113,7 @@ USE: stdio
"/library/inference/branches.factor"
"/library/inference/stack.factor"
"/library/compiler/optimizer.factor"
"/library/compiler/linearizer.factor"
"/library/compiler/assembler.factor"
"/library/compiler/xt.factor"

View File

@ -27,12 +27,10 @@
IN: compiler
USE: combinators
USE: dataflow
USE: inference
USE: errors
USE: generator
USE: hashtables
USE: kernel
USE: linearizer
USE: lists
USE: logic
USE: math

View File

@ -25,14 +25,12 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: generator
IN: compiler
USE: alien
USE: combinators
USE: compiler
USE: dataflow
USE: inference
USE: errors
USE: kernel
USE: linearizer
USE: lists
USE: logic
USE: math

View File

@ -25,12 +25,10 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: generator
IN: compiler
USE: combinators
USE: compiler
USE: dataflow
USE: inference
USE: errors
USE: linearizer
USE: lists
USE: math
USE: namespaces

View File

@ -25,12 +25,12 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: linearizer
IN: compiler
USE: lists
USE: words
USE: stack
USE: namespaces
USE: dataflow
USE: inference
USE: combinators
! Linear IR nodes. This is in addition to the symbols already
@ -40,7 +40,6 @@ SYMBOL: #branch-t ( branch if top of stack is true )
SYMBOL: #branch ( unconditional branch )
SYMBOL: #label ( branch target )
SYMBOL: #jump ( tail-call )
SYMBOL: #return ( return to caller )
: linear, ( param op -- )
swons , ;
@ -49,12 +48,7 @@ SYMBOL: #return ( return to caller )
#! Dataflow OPs have a linearizer word property. This
#! quotation is executed to convert the node into linear
#! form.
[ node-param get node-op get ] bind
dup "linearizer" word-property dup [
nip call
] [
drop linear,
] ifte ;
"linearizer" [ drop linear, ] apply-dataflow ;
: (linearize) ( dataflow -- )
[ >linear ] each ;
@ -85,4 +79,4 @@ SYMBOL: #return ( return to caller )
swap (linearize) ( true branch )
label, ( branch target of false branch end ) ;
\ #ifte [ linearize-ifte ] "linearizer" set-word-property
#ifte [ linearize-ifte ] "linearizer" set-word-property

View File

@ -0,0 +1,77 @@
! :folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2004 Slava Pestov.
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice,
! this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice,
! this list of conditions and the following disclaimer in the documentation
! and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: compiler
USE: lists
USE: stack
USE: combinators
USE: namespaces
USE: kernel
USE: inference
USE: words
USE: prettyprint
USE: logic
! The optimizer transforms dataflow IR to dataflow IR. Currently
! it simply removes literals that are eventually dropped, and
! never arise as inputs to any other type of function. Such
! 'dead' literals arise when combinators are inlined and
! quotations are lifted to their call sites.
: scan-literal ( node -- )
"scan-literal" [ 2drop ] apply-dataflow ;
: scan-literals ( dataflow -- list )
[ [ scan-literal ] each ] make-list ;
: scan-branches ( branches -- )
[ [ scan-literal ] each ] each ;
: mentions-literal? ( literal list -- )
#! Does the given list of result objects refer to this
#! literal?
[ dup cons? [ car over = ] [ drop f ] ifte ] some? ;
: (can-kill?) ( literal node -- ? )
#! Return false if the literal appears as input to this
#! node, and this node is not a stack operation.
[
node-consume-d get mentions-literal? swap
node-consume-r get mentions-literal? nip or not
] bind ;
: can-kill? ( literal dataflow -- ? )
[ dupd (can-kill?) ] all? nip ;
: kill-set ( dataflow -- list )
#! Push a list of literals that may be killed in the IR.
dup scan-literals [ over can-kill? ] subset nip ;
#push [ , ] "scan-literal" set-word-property
#ifte [ scan-branches ] "scan-literal" set-word-property
#generic [ scan-branches ] "scan-literal" set-word-property
#2generic [ scan-branches ] "scan-literal" set-word-property

View File

@ -27,12 +27,10 @@
IN: compiler
USE: combinators
USE: dataflow
USE: inference
USE: errors
USE: generator
USE: hashtables
USE: kernel
USE: linearizer
USE: lists
USE: logic
USE: math

View File

@ -27,7 +27,6 @@
IN: inference
USE: combinators
USE: dataflow
USE: errors
USE: interpreter
USE: kernel
@ -50,7 +49,7 @@ USE: hashtables
[
copy-interpreter
dataflow-graph off
(infer)
infer-quot
branch-effect
] with-scope ;

View File

@ -25,8 +25,7 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: dataflow
USE: inference
IN: inference
USE: interpreter
USE: lists
USE: math
@ -46,6 +45,8 @@ SYMBOL: #ifte
SYMBOL: #generic
SYMBOL: #2generic
SYMBOL: #return
SYMBOL: node-consume-d
SYMBOL: node-produce-d
SYMBOL: node-consume-r
@ -60,10 +61,10 @@ SYMBOL: node-param
<namespace> [
node-op set
node-param set
{ } node-consume-d set
{ } node-produce-d set
{ } node-consume-r set
{ } node-produce-r set
[ ] node-consume-d set
[ ] node-produce-d set
[ ] node-consume-r set
[ ] node-produce-r set
] extend ;
: node-inputs ( d-count r-count -- )
@ -93,3 +94,16 @@ SYMBOL: node-param
#! Remove the top stack element and add a dataflow node
#! noting this.
\ drop #call dataflow, [ 1 0 node-inputs ] bind ;
: apply-dataflow ( dataflow name default -- )
#! For the dataflow node, look up named word property,
#! if its not defined, apply default quotation to
#! ( param op ) otherwise apply property quotation to
#! ( param ).
>r >r [ node-param get node-op get ] bind dup r>
word-property dup [
( param op property )
nip call r> drop
] [
drop r> call
] ifte ;

View File

@ -27,7 +27,6 @@
IN: inference
USE: combinators
USE: dataflow
USE: errors
USE: interpreter
USE: kernel
@ -116,7 +115,7 @@ DEFER: apply-word
#! Apply the object's stack effect to the inferencer state.
dup word? [ apply-word ] [ apply-literal ] ifte ;
: (infer) ( quot -- )
: infer-quot ( quot -- )
#! Recursive calls to this word are made for nested
#! quotations.
[ apply-object ] each ;
@ -145,16 +144,26 @@ DEFER: apply-word
2drop
] ifte ;
: return-node ( -- )
#! Add a #return node to the dataflow graph.
f #return dataflow, [
meta-d get vector>list node-consume-d set
meta-r get vector-length 0 = [
"Word leaves elements on return stack" throw
] unless
] bind ;
: (infer) ( quot -- )
f init-inference infer-quot return-node ;
: infer ( quot -- [ in | out ] )
#! Stack effect of a quotation.
[ f init-inference (infer) effect ] with-scope ;
[ (infer) effect ] with-scope ;
: try-infer ( quot -- effect/f )
#! Push f if inference fails.
[ infer ] [ [ drop f ] when ] catch ;
IN: dataflow
: dataflow ( quot -- dataflow )
#! Data flow of a quotation.
[ f init-inference (infer) get-dataflow ] with-scope ;
[ (infer) get-dataflow ] with-scope ;

View File

@ -26,7 +26,6 @@
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: inference
USE: dataflow
USE: interpreter
USE: stack
USE: words

View File

@ -27,7 +27,6 @@
IN: inference
USE: combinators
USE: dataflow
USE: errors
USE: interpreter
USE: kernel
@ -73,7 +72,7 @@ USE: prettyprint
: inline-compound ( word -- effect )
#! Infer the stack effect of a compound word in the current
#! inferencer instance.
[ word-parameter (infer) effect ] with-recursive-state ;
[ word-parameter infer-quot effect ] with-recursive-state ;
: (infer-compound) ( word -- effect )
#! Infer a word's stack effect in a separate inferencer
@ -152,7 +151,7 @@ USE: prettyprint
\ drop #call dataflow, drop
[
dataflow-graph off
pop-d uncons recursive-state set (infer)
pop-d uncons recursive-state set infer-quot
d-in get meta-d get get-dataflow
] with-scope
[ dataflow-graph cons@ ] each meta-d set d-in set ;

View File

@ -77,6 +77,3 @@ SYMBOL: list-buffer
#! Append an object to the currently constructing list, only
#! if the object does not already occur in the list.
list-buffer unique@ ;
: count ( n -- [ 0 ... n-1 ] )
[ [ , ] times* ] make-list ;

View File

@ -252,3 +252,13 @@ DEFER: tree-contains?
: vector>list ( vector -- list )
stack>list reverse ;
: project ( n quot -- list )
#! Execute the quotation n times, passing the loop counter
#! the quotation as it ranges from 0..n-1. Collect results
#! in a new list.
[ ] rot [ -rot over >r >r call r> cons r> swap ] times*
nip reverse ; inline
: count ( n -- [ 0 ... n-1 ] )
[ ] project ;

View File

@ -7,11 +7,11 @@ USE: logic
USE: combinators
USE: hashtables
USE: stack
USE: dataflow
USE: kernel
USE: vectors
USE: namespaces
USE: prettyprint
USE: words
: dataflow-contains-op? ( object list -- ? )
#! Check if some dataflow node contains a given operation.
@ -37,10 +37,10 @@ USE: prettyprint
] unit-test
: dataflow-consume-d-len ( object -- n )
[ node-consume-d get vector-length ] bind ;
[ node-consume-d get length ] bind ;
: dataflow-produce-d-len ( object -- n )
[ node-produce-d get vector-length ] bind ;
[ node-produce-d get length ] bind ;
[ t ] [ [ drop ] dataflow car dataflow-consume-d-len 1 = ] unit-test
@ -51,7 +51,7 @@ USE: prettyprint
[ t ] [
[ 2 [ swap ] [ nip "hi" ] ifte ] dataflow
dataflow-ifte-node-consume-d vector-length 1 =
dataflow-ifte-node-consume-d length 1 =
] unit-test
[ t ] [
@ -62,3 +62,23 @@ USE: prettyprint
] some?
] bind >boolean
] unit-test
SYMBOL: #test
#test f "foobar" set-word-property
[ 6 ] [
{{
[ node-op | #test ]
[ node-param | 5 ]
}} "foobar" [ drop succ ] apply-dataflow
] unit-test
#test [ sq ] "foobar" set-word-property
[ 25 ] [
{{
[ node-op | #test ]
[ node-param | 5 ]
}} "foobar" [ drop succ ] apply-dataflow
] unit-test

View File

@ -0,0 +1,9 @@
IN: scratchpad
USE: test
USE: compiler
USE: inference
USE: words
: foo 1 2 3 ;
[ [ ] ] [ \ foo word-parameter dataflow kill-set ] unit-test

View File

@ -113,6 +113,7 @@ USE: unparser
"parsing-word"
"inference"
"dataflow"
"optimizer"
"interpreter"
] [
test

View File

@ -53,9 +53,9 @@ unit-test
[ { 1 2 3 4 } { 5 6 7 8 } vector-zip ]
unit-test
[ { } ] [ 0 { } vector-tail ] unit-test
[ { } ] [ 2 { 1 2 } vector-tail ] unit-test
[ { 3 4 } ] [ 2 { 1 2 3 4 } vector-tail ] unit-test
[ 2 { } vector-tail ] unit-test-fails
[ [ ] ] [ 0 { } vector-tail ] unit-test
[ [ ] ] [ 2 { 1 2 } vector-tail ] unit-test
[ [ 3 4 ] ] [ 2 { 1 2 3 4 } vector-tail ] unit-test
[ 2 [ ] vector-tail ] unit-test-fails
[ { 3 } ] [ 1 { 1 2 3 } vector-tail* ] unit-test
[ [ 3 ] ] [ 1 { 1 2 3 } vector-tail* ] unit-test

View File

@ -74,17 +74,6 @@ DEFER: vector-map
#! Reached end?
drop vector-length number= ;
: (vector=) ( n vec vec -- ? )
3dup ?vector= [
3drop t ( reached end without any unequal elts )
] [
3dup 2vector-nth = [
>r >r succ r> r> (vector=)
] [
3drop f
] ifte
] ifte ;
: vector-length= ( vec vec -- ? )
vector-length swap vector-length number= ;
@ -97,7 +86,7 @@ DEFER: vector-map
] [
over vector? [
2dup vector-length= [
0 -rot (vector=)
swap vector>list swap vector>list =
] [
2drop f
] ifte
@ -114,14 +103,14 @@ DEFER: vector-map
over ?vector-nth hashcode rot bitxor swap
] times* drop ;
: vector-tail ( n vector -- vector )
: vector-tail ( n vector -- list )
#! Return a new vector, with all elements from the nth
#! index upwards.
2dup vector-length swap - [
pick + over vector-nth
] vector-project nip nip ;
] project nip nip ;
: vector-tail* ( n vector -- vector )
: vector-tail* ( n vector -- list )
#! Unlike vector-tail, n is an index from the end of the
#! vector. For example, if n=1, this returns a vector of
#! one element.