Merge branch 'master' of git://factorcode.org/git/factor

db4
Anton Gorenko 2010-09-28 18:23:36 +06:00
commit 4e6fc292b9
60 changed files with 795 additions and 216 deletions

View File

@ -4,7 +4,7 @@ USING: http.client checksums checksums.md5 splitting assocs
kernel io.files bootstrap.image sequences io urls ;
IN: bootstrap.image.download
CONSTANT: url URL" http://factorcode.org/images/latest/"
CONSTANT: url URL" http://downloads.factorcode.org/images/latest/"
: download-checksums ( -- alist )
url "checksums.txt" >url derive-url http-get nip

View File

@ -10,7 +10,7 @@ SYMBOL: upload-images-destination
: destination ( -- dest )
upload-images-destination get
"slava@factorcode.org:/var/www/factorcode.org/newsite/images/latest/"
"slava_pestov@downloads.factorcode.org:downloads.factorcode.org/images/latest/"
or ;
: checksums ( -- temp ) "checksums.txt" temp-file ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2007 Chris Double.
! See http://factorcode.org/license.txt for BSD license.
USING: channels concurrency.distributed help.markup help.syntax
io.servers.connection ;
io.servers ;
IN: channels.remote
HELP: <remote-channel>

View File

@ -14,7 +14,8 @@ compiler.cfg.representations.preferred ;
FROM: namespaces => set ;
IN: compiler.cfg.alias-analysis
! We try to eliminate redundant slot operations using some simple heuristics.
! We try to eliminate redundant slot operations using some
! simple heuristics.
!
! All heap-allocated objects which are loaded from the stack, or
! other object slots are pessimistically assumed to belong to
@ -108,7 +109,7 @@ SYMBOL: heap-ac
2dup eq? [ 2drop ] [
[ ac>vregs ] dip
[ vregs>acs get '[ [ _ ] dip _ set-at ] each ]
[ acs>vregs get at push-all ]
[ ac>vregs push-all ]
2bi
] if ;
@ -129,7 +130,7 @@ ERROR: vreg-not-new vreg ;
#! Set alias class of newly-seen vreg.
vreg vregs>acs get key? [ vreg vreg-not-new ] when
ac vreg vregs>acs get set-at
vreg ac acs>vregs get push-at ;
vreg ac ac>vregs push ;
: live-slot ( slot#/f vreg -- vreg' )
#! If the slot number is unknown, we never reuse a previous

View File

@ -830,13 +830,16 @@ UNION: conditional-branch-insn
UNION: ##read ##slot ##slot-imm ##vm-field ##alien-global ;
UNION: ##write ##set-slot ##set-slot-imm ##set-vm-field ;
! Instructions that contain subroutine calls to functions which
! can callback arbitrary Factor code
UNION: factor-call-insn
UNION: alien-call-insn
##alien-invoke
##alien-indirect
##alien-assembly ;
! Instructions that contain subroutine calls to functions which
! can callback arbitrary Factor code
UNION: factor-call-insn
alien-call-insn ;
! Instructions that contain subroutine calls to functions which
! allocate memory
UNION: gc-map-insn
@ -848,15 +851,10 @@ factor-call-insn ;
M: gc-map-insn clone call-next-method [ clone ] change-gc-map ;
! Each one has a gc-map slot
TUPLE: gc-map scrub-d scrub-r gc-roots ;
TUPLE: gc-map scrub-d scrub-r gc-roots derived-roots ;
: <gc-map> ( -- gc-map ) gc-map new ;
UNION: alien-call-insn
##alien-invoke
##alien-indirect
##alien-assembly ;
! Instructions that clobber registers. They receive inputs and
! produce outputs in spill slots.
UNION: hairy-clobber-insn

View File

@ -146,9 +146,15 @@ RENAMING: assign [ vreg>reg ] [ vreg>reg ] [ vreg>reg ]
M: vreg-insn assign-registers-in-insn
[ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ;
: assign-gc-roots ( gc-map -- )
[ [ vreg>spill-slot ] map ] change-gc-roots drop ;
: assign-derived-roots ( gc-map -- )
[ [ [ vreg>spill-slot ] bi@ ] assoc-map ] change-derived-roots drop ;
M: gc-map-insn assign-registers-in-insn
[ [ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ]
[ gc-map>> [ [ vreg>spill-slot ] map ] change-gc-roots drop ]
[ gc-map>> [ assign-gc-roots ] [ assign-derived-roots ] bi ]
bi ;
M: insn assign-registers-in-insn drop ;

View File

@ -205,4 +205,43 @@ V{
[ H{ { 0 0 } } ] [ 2 get 4 get edge-live-in ] unit-test
[ H{ { 1 1 } } ] [ 3 get 4 get edge-live-in ] unit-test
[ H{ { 1 1 } } ] [ 3 get 4 get edge-live-in ] unit-test
V{
T{ ##prologue }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f 0 D 0 }
T{ ##tagged>integer f 1 0 }
T{ ##call-gc f T{ gc-map } }
T{ ##replace f 0 D 0 }
T{ ##call-gc f T{ gc-map } }
T{ ##replace f 1 D 0 }
T{ ##branch }
} 1 test-bb
V{
T{ ##epilogue }
T{ ##return }
} 2 test-bb
0 1 edge
1 2 edge
H{
{ 0 tagged-rep }
{ 1 int-rep }
} representations set
[ ] [ cfg new 0 get >>entry dup cfg set compute-live-sets ] unit-test
[ V{ { 1 0 } } ] [ 1 get instructions>> 2 swap nth gc-map>> derived-roots>> ] unit-test
[ { 0 } ] [ 1 get instructions>> 2 swap nth gc-map>> gc-roots>> ] unit-test
[ V{ { 1 0 } } ] [ 1 get instructions>> 4 swap nth gc-map>> derived-roots>> ] unit-test
[ { 0 } ] [ 1 get instructions>> 4 swap nth gc-map>> gc-roots>> ] unit-test

View File

@ -1,15 +1,28 @@
! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors assocs fry deques dlists namespaces
sequences sets compiler.cfg compiler.cfg.def-use
compiler.cfg.instructions compiler.cfg.registers
compiler.cfg.utilities compiler.cfg.predecessors
compiler.cfg.rpo cpu.architecture ;
USING: arrays kernel accessors assocs fry locals combinators
deques dlists namespaces sequences sets compiler.cfg
compiler.cfg.def-use compiler.cfg.instructions
compiler.cfg.registers compiler.cfg.utilities
compiler.cfg.predecessors compiler.cfg.rpo cpu.architecture ;
FROM: namespaces => set ;
IN: compiler.cfg.liveness
! See http://en.wikipedia.org/wiki/Liveness_analysis
! Similar to http://en.wikipedia.org/wiki/Liveness_analysis,
! with three additions:
! 1) With SSA, it is not sufficient to have a single live-in set
! per block. There is also there is an edge-live-in set per
! edge, consisting of phi inputs from each predecessor.
! 2) Liveness analysis annotates call sites with GC maps
! indicating the spill slots in the stack frame that contain
! tagged pointers, and thus have to be visited if a GC occurs
! inside the call.
! 3) GC maps can contain derived pointers. A derived pointer is
! a pointer into the middle of a data heap object. Each derived
! pointer has a base pointer, to keep it up to date when objects
! are moved by the garbage collector. This extends live
! intervals and inserts new ##phi instructions.
SYMBOL: live-ins
: live-in ( bb -- set )
@ -27,6 +40,8 @@ SYMBOL: edge-live-ins
: edge-live-in ( predecessor basic-block -- set )
edge-live-ins get at at ;
SYMBOL: base-pointers
GENERIC: visit-insn ( live-set insn -- live-set )
: kill-defs ( live-set insn -- live-set )
@ -35,20 +50,64 @@ GENERIC: visit-insn ( live-set insn -- live-set )
: gen-uses ( live-set insn -- live-set )
uses-vregs [ over conjoin ] each ; inline
M: vreg-insn visit-insn [ kill-defs ] [ gen-uses ] bi ;
M: vreg-insn visit-insn
[ kill-defs ] [ gen-uses ] bi ;
! Our liveness analysis annotates call sites with GC maps
! indicating the spill slots in the stack frame that contain
! tagged pointers, and thus have to be visited if a GC occurs
! inside the call.
DEFER: lookup-base-pointer
GENERIC: lookup-base-pointer* ( insn -- vreg/f )
M: ##tagged>integer lookup-base-pointer* src>> ;
M: ##unbox-any-c-ptr lookup-base-pointer*
! If the input to unbox-any-c-ptr was an alien and not a
! byte array, then the derived pointer will be outside of
! the data heap. The GC has to handle this case and ignore
! it.
src>> ;
M: ##copy lookup-base-pointer* src>> lookup-base-pointer ;
M: ##add-imm lookup-base-pointer* src1>> lookup-base-pointer ;
M: ##sub-imm lookup-base-pointer* src1>> lookup-base-pointer ;
M: ##add lookup-base-pointer*
! If both operands have a base pointer, then the user better
! not be doing memory reads and writes on the object, since
! we don't give it a base pointer in that case at all.
[ src1>> ] [ src2>> ] bi [ lookup-base-pointer ] bi@ xor ;
M: ##sub lookup-base-pointer*
src1>> lookup-base-pointer ;
M: vreg-insn lookup-base-pointer* drop f ;
: lookup-base-pointer ( vreg -- vreg/f )
base-pointers get [ insn-of lookup-base-pointer* ] cache ;
:: visit-derived-root ( vreg derived-roots gc-roots -- )
vreg lookup-base-pointer :> base
base [
{ vreg base } derived-roots push
base gc-roots adjoin
] when ;
: visit-gc-root ( vreg derived-roots gc-roots -- )
pick rep-of {
{ tagged-rep [ nip adjoin ] }
{ int-rep [ visit-derived-root ] }
[ 2drop 2drop ]
} case ;
: gc-roots ( live-set -- derived-roots gc-roots )
V{ } clone HS{ } clone
[ '[ drop _ _ visit-gc-root ] assoc-each ] 2keep
members ;
: fill-gc-map ( live-set insn -- live-set )
representations get [
gc-map>> over keys
[ rep-of tagged-rep? ] filter
>>gc-roots
] when
drop ;
[ representations get [ dup gc-roots ] [ f f ] if ] dip
gc-map>> [ gc-roots<< ] [ derived-roots<< ] bi ;
M: gc-map-insn visit-insn
[ kill-defs ] [ fill-gc-map ] [ gen-uses ] tri ;
@ -60,9 +119,6 @@ M: insn visit-insn drop ;
: transfer-liveness ( live-set instructions -- live-set' )
[ clone ] [ <reversed> ] bi* [ visit-insn ] each ;
: local-live-in ( instructions -- live-set )
[ H{ } ] dip transfer-liveness keys ;
SYMBOL: work-list
: add-to-work-list ( basic-blocks -- )
@ -98,11 +154,13 @@ SYMBOL: work-list
: compute-live-sets ( cfg -- )
needs-predecessors
dup compute-insns
<hashed-dlist> work-list set
H{ } clone live-ins set
H{ } clone edge-live-ins set
H{ } clone live-outs set
H{ } clone base-pointers set
post-order add-to-work-list
work-list get [ liveness-step ] slurp-deque ;

View File

@ -9,13 +9,14 @@ STRUCT: gc-info
{ scrub-d-count uint }
{ scrub-r-count uint }
{ gc-root-count uint }
{ derived-root-count uint }
{ return-address-count uint } ;
SINGLETON: fake-cpu
fake-cpu \ cpu set
M: fake-cpu gc-root-offsets ;
M: fake-cpu gc-root-offset ;
[ ] [
[
@ -27,7 +28,7 @@ M: fake-cpu gc-root-offsets ;
50 <byte-array> %
T{ gc-map f B{ 0 1 1 1 0 } B{ 1 0 } V{ 1 3 } } gc-map-here
T{ gc-map f B{ 0 1 1 1 0 } B{ 1 0 } V{ 1 3 } V{ { 2 4 } } } gc-map-here
emit-gc-info
] B{ } make
@ -54,7 +55,10 @@ M: fake-cpu gc-root-offsets ;
f t f t
} underlying>> %
! Return addresses - 4 bytes
! Derived pointers
uint-array{ -1 -1 4 } underlying>> %
! Return addresses
uint-array{ 100 } underlying>> %
! GC info footer - 16 bytes
@ -62,6 +66,7 @@ M: fake-cpu gc-root-offsets ;
{ scrub-d-count 5 }
{ scrub-r-count 2 }
{ gc-root-count 4 }
{ derived-root-count 3 }
{ return-address-count 1 }
} (underlying)>> %
] B{ } make

View File

@ -2,8 +2,8 @@
! See http://factorcode.org/license.txt for BSD license.
USING: arrays bit-arrays byte-arrays byte-vectors generic assocs
hashtables io.binary kernel kernel.private math namespaces make
sequences words quotations strings alien.accessors alien.strings
layouts system combinators math.bitwise math.order
sequences words quotations strings sorting alien.accessors
alien.strings layouts system combinators math.bitwise math.order
combinators.short-circuit combinators.smart accessors growable
fry memoize compiler.constants compiler.cfg.instructions
cpu.architecture ;
@ -144,12 +144,14 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
! - <scrubbed data stack locations>
! - <scrubbed retain stack locations>
! - <GC root spill slots>
! uint[] <base pointers>
! uint[] <return addresses>
! uint <largest scrubbed data stack location>
! uint <largest scrubbed retain stack location>
! uint <largest GC root spill slot>
! uint <number of return addresses>
! uint <largest derived root spill slot>
! int <number of return addresses>
!
SYMBOLS: return-addresses gc-maps ;
: gc-map-needed? ( gc-map -- ? )
@ -160,6 +162,7 @@ SYMBOLS: return-addresses gc-maps ;
[ scrub-d>> empty? ]
[ scrub-r>> empty? ]
[ gc-roots>> empty? ]
[ derived-roots>> empty? ]
} 1&& not
] when ;
@ -169,33 +172,64 @@ SYMBOLS: return-addresses gc-maps ;
compiled-offset return-addresses get push
] [ drop ] if ;
: longest ( seqs -- n )
[ length ] [ max ] map-reduce ;
: emit-scrub ( seqs -- n )
! seqs is a sequence of sequences of 0/1
dup [ length ] [ max ] map-reduce
dup longest
[ '[ [ 0 = ] ?{ } map-as _ f pad-tail % ] each ] keep ;
: integers>bits ( seq n -- bit-array )
<bit-array> [ '[ [ t ] dip _ set-nth ] each ] keep ;
: largest-spill-slot ( seqs -- n )
[ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce ;
: emit-gc-roots ( seqs -- n )
! seqs is a sequence of sequences of integers 0..n-1
dup [ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce
dup largest-spill-slot
[ '[ _ integers>bits % ] each ] keep ;
: emit-uint ( n -- )
building get push-uint ;
: emit-uints ( n -- )
[ emit-uint ] each ;
: gc-root-offsets ( gc-map -- offsets )
gc-roots>> [ gc-root-offset ] map ;
: emit-gc-info-bitmaps ( -- scrub-d-count scrub-r-count gc-root-count )
[
gc-maps get {
[ [ scrub-d>> ] map emit-scrub ]
[ [ scrub-r>> ] map emit-scrub ]
[ [ gc-root-offsets ] map emit-gc-roots ]
} cleave
] ?{ } make underlying>> % ;
: emit-base-table ( alist longest -- )
-1 <array> <enum> swap assoc-union! seq>> emit-uints ;
: derived-root-offsets ( gc-map -- offsets )
derived-roots>> [ [ gc-root-offset ] bi@ ] assoc-map ;
: emit-base-tables ( -- count )
gc-maps get [ derived-root-offsets ] map
dup [ keys ] map largest-spill-slot
[ '[ _ emit-base-table ] each ] keep ;
: emit-return-addresses ( -- )
return-addresses get emit-uints ;
: gc-info ( -- byte-array )
[
return-addresses get empty? [ 0 emit-uint ] [
gc-maps get
[
[ [ scrub-d>> ] map emit-scrub ]
[ [ scrub-r>> ] map emit-scrub ]
[ [ gc-roots>> gc-root-offsets ] map emit-gc-roots ] tri
] ?{ } make underlying>> %
return-addresses get [ emit-uint ] each
[ emit-uint ] tri@
emit-gc-info-bitmaps
emit-base-tables
emit-return-addresses
4array emit-uints
return-addresses get length emit-uint
] if
] B{ } make ;

View File

@ -823,25 +823,3 @@ TUPLE: some-tuple x ;
aa-indirect-1 >>x
] compile-call
] unit-test
! Write barrier elimination was being done before scheduling and
! GC check insertion, and didn't take subroutine calls into
! account. Oops...
: write-barrier-elim-in-wrong-place ( -- obj )
! A callback used below
void { } cdecl [ compact-gc ] alien-callback
! Allocate an object A in the nursery
1 f <array>
! Subroutine call promotes the object to tenured
swap void { } cdecl alien-indirect
! Allocate another object B in the nursery, store it into
! the first
1 f <array> over set-first
! Now object A's card should be marked and minor GC should
! promote B to aging
minor-gc
! Do stuff
[ 100 [ ] times ] infer.
;
[ { { f } } ] [ write-barrier-elim-in-wrong-place ] unit-test

View File

@ -4,7 +4,8 @@ sequences tools.test namespaces.private slots.private
sequences.private byte-arrays alien alien.accessors layouts
words definitions compiler.units io combinators vectors grouping
make alien.c-types combinators.short-circuit math.order
math.libm math.parser math.functions alien.syntax ;
math.libm math.parser math.functions alien.syntax memory
stack-checker ;
FROM: math => float ;
QUALIFIED: namespaces.private
IN: compiler.tests.codegen
@ -463,6 +464,13 @@ TUPLE: myseq { underlying1 byte-array read-only } { underlying2 byte-array read-
[ [ HEX: f bitand ] bi@ [ shift ] [ drop -3 shift ] 2bi ] compile-call
] unit-test
! Alias analysis bug
[ t ] [
[
10 10 <byte-array> [ <displaced-alien> underlying>> ] keep eq?
] compile-call
] unit-test
! GC root offsets were computed wrong on x86
: gc-root-messup ( a -- b )
dup [
@ -473,9 +481,45 @@ TUPLE: myseq { underlying1 byte-array read-only } { underlying2 byte-array read-
[ ] [ 2000 [ "hello" clone dup gc-root-messup first eq? t assert= ] times ] unit-test
! Alias analysis bug
[ t ] [
[
10 10 <byte-array> [ <displaced-alien> underlying>> ] keep eq?
] compile-call
] unit-test
! Write barrier elimination was being done before scheduling and
! GC check insertion, and didn't take subroutine calls into
! account. Oops...
: write-barrier-elim-in-wrong-place ( -- obj )
! A callback used below
void { } cdecl [ compact-gc ] alien-callback
! Allocate an object A in the nursery
1 f <array>
! Subroutine call promotes the object to tenured
swap void { } cdecl alien-indirect
! Allocate another object B in the nursery, store it into
! the first
1 f <array> over set-first
! Now object A's card should be marked and minor GC should
! promote B to aging
minor-gc
! Do stuff
[ 100 [ ] times ] infer.
;
[ { { f } } ] [ write-barrier-elim-in-wrong-place ] unit-test
! GC maps must support derived pointers
: (derived-pointer-test-1) ( -- byte-array )
2 <byte-array> ;
: derived-pointer-test-1 ( -- byte-array )
! A callback used below
void { } cdecl [ compact-gc ] alien-callback
! Put the construction in a word since instruction selection
! eliminates the untagged pointer entirely if the value is a
! byte array
(derived-pointer-test-1) { c-ptr } declare
! Store into an array, an untagged pointer to the payload
! is now an available expression
123 over 0 set-alien-unsigned-1
! GC, moving the array and derived pointer
swap void { } cdecl alien-indirect
! Store into the array again
231 over 1 set-alien-unsigned-1 ;
[ B{ 123 231 } ] [ derived-pointer-test-1 ] unit-test

View File

@ -1,7 +1,7 @@
USING: tools.test concurrency.distributed kernel io.files
io.files.temp io.directories arrays io.sockets system calendar
combinators threads math sequences concurrency.messaging
continuations accessors prettyprint io.servers.connection ;
continuations accessors prettyprint io.servers ;
FROM: concurrency.messaging => receive send ;
IN: concurrency.distributed.tests
@ -36,4 +36,4 @@ test-node-server [
test-node-client "thread-a" <remote-thread> send
100 seconds receive-timeout
] unit-test
] with-threaded-server
] with-threaded-server

View File

@ -1,7 +1,7 @@
! Copyright (C) 2005 Chris Double. All Rights Reserved.
! See http://factorcode.org/license.txt for BSD license.
USING: serialize sequences concurrency.messaging threads io
io.servers.connection io.encodings.binary assocs init
io.servers io.encodings.binary assocs init
arrays namespaces kernel accessors ;
FROM: io.sockets => host-name <inet> with-client ;
IN: concurrency.distributed

View File

@ -225,7 +225,7 @@ M: object vm-stack-space 0 ;
! %store-memory work
HOOK: complex-addressing? cpu ( -- ? )
HOOK: gc-root-offsets cpu ( seq -- seq' )
HOOK: gc-root-offset cpu ( spill-slot -- n )
HOOK: %load-immediate cpu ( reg val -- )
HOOK: %load-reference cpu ( reg obj -- )

View File

@ -503,8 +503,8 @@ M:: x86 %check-nursery-branch ( label size cc temp1 temp2 -- )
{ cc/<= [ label JG ] }
} case ;
M: x86 gc-root-offsets
[ n>> spill-offset special-offset cell + cell /i ] map f like ;
M: x86 gc-root-offset
n>> spill-offset special-offset cell + cell /i ;
M: x86 %call-gc ( gc-map -- )
\ minor-gc %call

View File

@ -1,6 +1,6 @@
USING: calendar ftp.server io.encodings.ascii io.files
io.files.unique namespaces threads tools.test kernel
io.servers.connection ftp.client accessors urls
io.servers ftp.client accessors urls
io.pathnames io.directories sequences fry io.backend
continuations ;
FROM: ftp.client => ftp-get ;

View File

@ -5,7 +5,7 @@ combinators.short-circuit concurrency.promises continuations
destructors ftp io io.directories io.encodings
io.encodings.8-bit.latin1 io.encodings.binary io.encodings.utf8
io.files io.files.info io.files.types io.pathnames
io.servers.connection io.sockets io.streams.string io.timeouts
io.servers io.sockets io.streams.string io.timeouts
kernel logging math math.bitwise math.parser namespaces
sequences simple-tokenizer splitting strings threads
tools.files unicode.case ;

View File

@ -1,6 +1,6 @@
USING: tools.test http furnace.sessions furnace.actions
http.server http.server.responses math namespaces make kernel
accessors io.sockets io.servers.connection prettyprint
accessors io.sockets io.servers prettyprint
io.streams.string io.files io.files.temp io.directories
splitting destructors sequences db db.tuples db.sqlite
continuations urls math.parser furnace furnace.utilities ;

View File

@ -1,4 +1,4 @@
! Copyright (C) 2008 Slava Pestov.
! Copyright (C) 2008, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces make assocs sequences kernel classes splitting
words vocabs.loader accessors strings combinators arrays
@ -27,10 +27,12 @@ ERROR: no-such-word name vocab ;
: each-responder ( quot -- )
nested-responders swap each ; inline
: base-path ( string -- pair )
ERROR: no-such-responder responder ;
: base-path ( string -- seq )
dup responder-nesting get
[ second class superclasses [ name>> = ] with any? ] with find nip
[ first ] [ "No such responder: " swap append throw ] ?if ;
[ first ] [ no-such-responder ] ?if ;
: resolve-base-path ( string -- string' )
"$" ?head [

View File

@ -205,7 +205,7 @@ Set-Cookie: oo="bar; a=b"; comment="your mom"; httponly=yes
! Live-fire exercise
USING: http.server.static furnace.sessions furnace.alloy
furnace.actions furnace.auth furnace.auth.login furnace.db
io.servers.connection io.files io.files.temp io.directories io
io.servers io.files io.files.temp io.directories io
threads
http.server.responses http.server.redirection furnace.redirection
http.server.dispatchers db.tuples ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs kernel io.servers.connection ;
USING: namespaces assocs kernel io.servers ;
IN: http.server.remapping
SYMBOL: port-remapping

View File

@ -1,5 +1,5 @@
USING: help.markup help.syntax io.streams.string quotations strings urls
http vocabs.refresh math io.servers.connection assocs ;
http vocabs.refresh math io.servers assocs ;
IN: http.server
HELP: trivial-responder
@ -109,7 +109,7 @@ ARTICLE: "http.server.variables" "HTTP server variables"
} ;
ARTICLE: "http.server" "HTTP server"
"The " { $vocab-link "http.server" } " vocabulary implements an HTTP and HTTPS server on top of " { $vocab-link "io.servers.connection" } "."
"The " { $vocab-link "http.server" } " vocabulary implements an HTTP and HTTPS server on top of " { $vocab-link "io.servers" } "."
{ $subsections
"http.server.responders"
"http.server.requests"

View File

@ -15,7 +15,7 @@ io.encodings.binary
io.streams.limited
io.streams.string
io.streams.throwing
io.servers.connection
io.servers
io.timeouts
io.crlf
fry logging logging.insomniac calendar urls urls.encoding

View File

@ -1,6 +1,6 @@
USING: calendar classes concurrency.semaphores help.markup
help.syntax io io.sockets io.sockets.secure math quotations ;
IN: io.servers.connection
IN: io.servers
ARTICLE: "server-config" "Threaded server configuration"
"The " { $link threaded-server } " tuple has a variety of slots which can be set before starting the server with " { $link start-server } "."
@ -52,8 +52,8 @@ $nl
ARTICLE: "server-examples" "Threaded server examples"
"The " { $vocab-link "time-server" } " vocabulary implements a simple threaded server which sends the current time to the client. The " { $vocab-link "concurrency.distributed" } ", " { $vocab-link "ftp.server" } ", and " { $vocab-link "http.server" } " vocabularies demonstrate more complex usage of the threaded server library." ;
ARTICLE: "io.servers.connection" "Threaded servers"
"The " { $vocab-link "io.servers.connection" } " vocabulary implements a generic server abstraction for " { $link "network-connection" } ". A set of threads listen for connections, and additional threads are spawned for each client connection. In addition to this basic functionality, it provides some advanced features such as logging, connection limits and secure socket support."
ARTICLE: "io.servers" "Threaded servers"
"The " { $vocab-link "io.servers" } " vocabulary implements a generic server abstraction for " { $link "network-connection" } ". A set of threads listen for connections, and additional threads are spawned for each client connection. In addition to this basic functionality, it provides some advanced features such as logging, connection limits and secure socket support."
{ $subsections "server-examples" }
"Creating threaded servers with client handler quotations:"
{ $subsections <threaded-server> }
@ -82,7 +82,7 @@ ARTICLE: "io.servers.connection" "Threaded servers"
"Additionally, the " { $link local-address } " and "
{ $subsections remote-address } " variables are set, as in " { $link with-client } "." ;
ABOUT: "io.servers.connection"
ABOUT: "io.servers"
HELP: threaded-server
{ $var-description "In client handlers, stores the current threaded server instance." }

View File

@ -1,8 +1,8 @@
USING: accessors calendar concurrency.promises fry io
io.encodings.ascii io.servers.connection
io.servers.connection.private io.sockets kernel namespaces
io.encodings.ascii io.servers
io.servers.private io.sockets kernel namespaces
sequences threads tools.test ;
IN: io.servers.connection
IN: io.servers
[ t ] [ ascii <threaded-server> listen-on empty? ] unit-test

View File

@ -8,7 +8,7 @@ io io.sockets io.sockets.secure io.streams.duplex io.styles
io.timeouts kernel logging make math math.parser namespaces
present prettyprint random sequences sets strings threads ;
FROM: namespaces => set ;
IN: io.servers.connection
IN: io.servers
TUPLE: threaded-server < identity-tuple
name
@ -22,7 +22,8 @@ semaphore
timeout
encoding
handler
server-stopped ;
server-stopped
secure-context ;
SYMBOL: running-servers
running-servers [ HS{ } clone ] initialize
@ -69,23 +70,20 @@ GENERIC: handle-client* ( threaded-server -- )
<PRIVATE
GENERIC: (>insecure) ( obj -- obj )
GENERIC: >insecure ( obj -- obj )
M: inet (>insecure) ;
M: inet4 (>insecure) ;
M: inet6 (>insecure) ;
M: local (>insecure) ;
M: integer (>insecure) internet-server ;
M: string (>insecure) internet-server ;
M: array (>insecure) [ (>insecure) ] map ;
M: f (>insecure) ;
: >insecure ( obj -- seq )
(>insecure) dup sequence? [ 1array ] unless ;
M: inet >insecure 1array ;
M: inet4 >insecure 1array ;
M: inet6 >insecure 1array ;
M: local >insecure 1array ;
M: integer >insecure internet-server 1array ;
M: string >insecure internet-server 1array ;
M: array >insecure [ >insecure ] map ;
M: f >insecure ;
: >secure ( addrspec -- addrspec' )
>insecure
[ dup { [ secure? ] [ not ] } 1|| [ <secure> ] unless ] map ;
[ dup secure? [ <secure> ] unless ] map ;
: listen-on ( threaded-server -- addrspecs )
[ secure>> >secure ] [ insecure>> >insecure ] bi append
@ -131,14 +129,24 @@ M: threaded-server handle-client* handler>> call( -- ) ;
[ (accept-connection) ]
if* ;
: with-existing-secure-context ( threaded-server quot -- )
[ secure-context>> secure-context ] dip with-variable ; inline
: accept-loop ( server -- )
[ accept-connection ] [ accept-loop ] bi ;
: start-accept-loop ( server -- ) accept-loop ;
: start-accept-loop ( threaded-server server -- )
'[ _ accept-loop ] with-existing-secure-context ;
\ start-accept-loop NOTICE add-error-logging
: create-secure-context ( threaded-server -- threaded-server )
dup secure>> [
dup secure-config>> <secure-context> >>secure-context
] when ;
: init-server ( threaded-server -- threaded-server )
create-secure-context
<flag> >>server-stopped
dup semaphore>> [
dup max-connections>> [
@ -153,48 +161,45 @@ ERROR: no-ports-configured threaded-server ;
'[ [ _ <server> |dispose ] map ] with-destructors ;
: set-servers ( threaded-server -- threaded-server )
dup dup listen-on [ no-ports-configured ] [ (make-servers) ] if-empty
>>servers ;
dup [
dup dup listen-on [ no-ports-configured ] [ (make-servers) ] if-empty
>>servers
] with-existing-secure-context ;
: server-thread-name ( threaded-server addrspec -- string )
[ name>> ] [ addr>> present ] bi* " server on " glue ;
: (start-server) ( threaded-server -- )
init-server
dup threaded-server [
[ ] [ name>> ] bi
[
set-servers
dup add-running-server
dup servers>>
[
[ nip '[ _ [ start-accept-loop ] with-disposal ] ]
[ server-thread-name ] 2bi spawn drop
] with each
] with-logging
] with-variable ;
PRIVATE>
: start-server ( threaded-server -- threaded-server )
#! Only create a secure-context if we want to listen on
#! a secure port, otherwise start-server won't work at
#! all if SSL is not available.
dup dup secure>> [
dup secure-config>> [
(start-server)
] with-secure-context
] [
(start-server)
] if ;
init-server
[
dup threaded-server [
[ ] [ name>> ] bi
[
set-servers
dup add-running-server
dup servers>>
[
[ '[ _ _ [ start-accept-loop ] with-disposal ] ]
[ server-thread-name ] 2bi spawn drop
] with each
] with-logging
] with-variable
] keep ;
: server-running? ( threaded-server -- ? )
server-stopped>> [ value>> not ] [ f ] if* ;
: stop-server ( threaded-server -- )
dup server-running? [
[ [ f ] change-servers drop dispose-each ]
[ remove-running-server ]
[
[
[ secure-context>> [ &dispose drop ] when* ]
[ [ f ] change-servers drop dispose-each ] bi
] with-destructors
]
[ server-stopped>> raise-flag ] tri
] [
drop

View File

@ -52,7 +52,7 @@ $nl
{ { $link inet4 } " - a TCP/IP connection to an IPv4 address and port number; no name lookup is performed" }
{ { $link inet6 } " - a TCP/IP connection to an IPv6 address and port number; no name lookup is performed" }
}
"The " { $vocab-link "io.servers.connection" } " library defines high-level wrappers around " { $link <server> } " which makes it easy to listen for IPv4, IPv6 and secure socket connections simultaneously, perform logging, and optionally only allow connections from the loopback interface."
"The " { $vocab-link "io.servers" } " library defines high-level wrappers around " { $link <server> } " which makes it easy to listen for IPv4, IPv6 and secure socket connections simultaneously, perform logging, and optionally only allow connections from the loopback interface."
$nl
"The " { $vocab-link "io.sockets.secure" } " vocabulary implements secure, encrypted sockets via SSL and TLS." ;
@ -170,7 +170,7 @@ HELP: <server>
{ $code "f 1234 <inet> resolve-host" }
"To start a server which listens for connections from the loopback interface only, use an address specifier returned by the following code, where 1234 is the desired port number:"
{ $code "\"localhost\" 1234 <inet> resolve-host" }
"Since " { $link resolve-host } " can return multiple address specifiers, your server code must listen on them all to work properly. The " { $vocab-link "io.servers.connection" } " vocabulary can be used to help with this."
"Since " { $link resolve-host } " can return multiple address specifiers, your server code must listen on them all to work properly. The " { $vocab-link "io.servers" } " vocabulary can be used to help with this."
$nl
"To start a TCP/IP server which listens for connections on a randomly-assigned port, set the port number in the address specifier to 0, and then read the " { $snippet "addr" } " slot of the server instance to obtain the actual port number it is listening on:"
{ $unchecked-example

View File

@ -38,7 +38,7 @@ HELP: limited-input
{ $description "Wraps the current " { $link input-stream } " in a " { $link limited-stream } "." } ;
ARTICLE: "io.streams.limited" "Limited input streams"
"The " { $vocab-link "io.streams.limited" } " vocabulary wraps a stream to behave as if it had only a limited number of bytes, either throwing an error or returning " { $link f } " upon reaching the end. Limiting a non-seekable stream keeps a byte count and triggers the end-of-stream behavior when this byte count has been reached. However, limiting a seekable stream creates a window of bytes that supports seeking and re-reading of bytes in that window." $nl
"The " { $vocab-link "io.streams.limited" } " vocabulary wraps a stream to behave as if it had only a limited number of bytes. Limiting a seekable stream creates a window of bytes that supports seeking and re-reading of bytes in that window. If it is desirable for a stream to throw an exception upon exhaustion, use the " { $vocab-link "io.streams.throwing" } " vocabulary in conjunction with this one." $nl
"Wrap a stream in a limited stream:"
{ $subsections limited-stream }
"Wrap the current " { $link input-stream } " in a limited stream:"

View File

@ -0,0 +1,44 @@
! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax io kernel quotations words
math ;
IN: io.streams.throwing
HELP: stream-exhausted
{ $values
{ "n" integer } { "stream" "an input stream" } { "word" word }
}
{ $description "The exception that gets thrown when a stream is exhausted." } ;
HELP: stream-throw-on-eof
{ $values
{ "stream" "an input stream" } { "quot" quotation }
}
{ $description "Wraps a stream in a " { $link <throws-on-eof-stream> } " tuple and calls the quotation with this stream as the " { $link input-stream } " variable. Causes a " { $link stream-exhausted } " exception to be thrown upon stream exhaustion. The stream is left open after this combinator returns." }
"This example will throw a " { $link stream-exhausted } " exception:"
{ $unchecked-example """USING: io.streams.throwing prettyprint ;
"abc" <string-reader> [ 4 read ] stream-throw-on-eof"""
""
} ;
HELP: throw-on-eof
{ $values
{ "quot" quotation }
}
{ $description "Wraps the value stored in the " { $link input-stream } " variable and causes a stream read that exhausts the input stream to throw a " { $link stream-exhausted } " exception. The stream is left open after this combinator returns." } $nl
"This example will throw a " { $link stream-exhausted } " exception:"
{ $unchecked-example """USING: io.streams.throwing prettyprint ;
"abc" [ [ 4 read ] throw-on-eof ] with-string-reader"""
""
} ;
ARTICLE: "io.streams.throwing" "Throwing exceptions on stream exhaustion"
"The " { $vocab-link "io.streams.throwing" } " vocabulary implements combinators for changing the behavior of a stream to throw an exception upon exhaustion instead of returning " { $link f } "." $nl
"A general combinator to wrap any stream:"
{ $subsections stream-throw-on-eof }
"A combinator for the " { $link input-stream } " variable:"
{ $subsections throw-on-eof }
"The exception itself:"
{ $subsections stream-exhausted } ;
ABOUT: "io.streams.throwing"

View File

@ -15,9 +15,8 @@ IN: io.streams.throwing.tests
[
[
"asdf" <string-reader> &dispose [
[ 4 swap stream-read ]
[ stream-read1 ] bi
"asdf" <string-reader> [
4 read read1
] stream-throw-on-eof
] with-destructors
] [ stream-exhausted? ] must-fail-with

View File

@ -6,12 +6,12 @@ IN: io.streams.throwing
ERROR: stream-exhausted n stream word ;
<PRIVATE
TUPLE: throws-on-eof-stream stream ;
C: <throws-on-eof-stream> throws-on-eof-stream
<PRIVATE
M: throws-on-eof-stream stream-element-type stream>> stream-element-type ;
M: throws-on-eof-stream dispose stream>> dispose ;
@ -41,7 +41,7 @@ M: throws-on-eof-stream stream-read-until
PRIVATE>
: stream-throw-on-eof ( ..a stream quot: ( ..a stream' -- ..b ) -- ..b )
[ <throws-on-eof-stream> ] dip call ; inline
[ <throws-on-eof-stream> ] dip with-input-stream* ; inline
: throw-on-eof ( ..a quot: ( ..a -- ..b ) -- ..b )
[ input-stream get <throws-on-eof-stream> ] dip with-input-stream* ; inline

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs continuations fry http.server io
io.encodings.ascii io.files io.files.unique
io.servers.connection io.streams.duplex io.streams.string
io.servers io.streams.duplex io.streams.string
kernel math.ranges mime.multipart multiline namespaces random
sequences strings threads tools.test ;
IN: mime.multipart.tests

View File

@ -52,7 +52,7 @@ os macosx? [
] each
USING: http.client http.server http.server.dispatchers
http.server.responses http.server.static io.servers.connection ;
http.server.responses http.server.static io.servers ;
SINGLETON: quit-responder

View File

@ -46,7 +46,7 @@ nmake /nologo /f Nmakefile %_target%
if errorlevel 1 goto fail
echo Fetching %_bootimage_version% boot image...
cscript /nologo build-support\http-get.vbs http://factorcode.org/images/%_bootimage_path%/%_bootimage% %_bootimage%
cscript /nologo build-support\http-get.vbs http://downloads.factorcode.org/images/%_bootimage_path%/%_bootimage% %_bootimage%
if errorlevel 1 goto fail
echo Bootstrapping...

View File

@ -447,7 +447,7 @@ update_boot_images() {
$DELETE $BOOT_IMAGE.{?,??} > /dev/null 2>&1
$DELETE temp/staging.*.image > /dev/null 2>&1
if [[ -f $BOOT_IMAGE ]] ; then
get_url http://factorcode.org/images/latest/checksums.txt
get_url http://downloads.factorcode.org/images/latest/checksums.txt
factorcode_md5=`cat checksums.txt|grep $BOOT_IMAGE|cut -f2 -d' '`;
set_md5sum
case $OS in
@ -469,7 +469,7 @@ update_boot_images() {
get_boot_image() {
$ECHO "Downloading boot image $BOOT_IMAGE."
get_url http://factorcode.org/images/latest/$BOOT_IMAGE
get_url http://downloads.factorcode.org/images/latest/$BOOT_IMAGE
}
get_url() {

View File

@ -1,8 +1,7 @@
! Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors debugger io io.encodings.utf8 io.servers.connection
USING: accessors debugger io io.encodings.utf8 io.servers
kernel listener math namespaces ;
IN: fuel.remote
<PRIVATE

View File

@ -359,7 +359,7 @@ CONSTANT: google-slides
}
{ $slide "Example: time server"
{ $vocab-link "time-server" }
{ "Demonstrates " { $vocab-link "io.servers.connection" } " vocabulary, threads" }
{ "Demonstrates " { $vocab-link "io.servers" } " vocabulary, threads" }
}
{ $slide "Example: what is my IP?"
{ $vocab-link "webapps.ip" }

View File

@ -1,7 +1,7 @@
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs calendar continuations destructors io
io.encodings.binary io.servers.connection io.sockets
io.encodings.binary io.servers io.sockets
io.streams.duplex fry kernel locals math math.ranges multiline
namespaces prettyprint random sequences sets splitting threads
tools.continuations ;

View File

@ -1,7 +1,7 @@
IN: mason.release.branch.tests
USING: mason.release.branch mason.config tools.test namespaces ;
[ { "git" "push" "joe@blah.com:/my/git" "master:clean-linux-x86-32" } ] [
[ { "git" "push" "-f" "joe@blah.com:/my/git" "master:clean-linux-x86-32" } ] [
[
"joe" branch-username set
"blah.com" branch-host set

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors calendar calendar.format io io.encodings.ascii
io.servers.connection kernel threads ;
io.servers kernel threads ;
IN: time-server
: handle-time-client ( -- )

View File

@ -1,5 +1,4 @@
USING: listener io.servers.connection io.encodings.utf8
accessors kernel ;
USING: listener io.servers io.encodings.utf8 accessors kernel ;
IN: tty-server
: <tty-server> ( port -- )

View File

@ -44,13 +44,13 @@ IN: webapps.mason.utils
"http://downloads.factorcode.org/" prepend ;
: package-url ( builder -- url )
[ URL" $mason-app/package" ] dip
[ URL" http://builds.factorcode.org/package" ] dip
[ os>> "os" set-query-param ]
[ cpu>> "cpu" set-query-param ] bi
adjust-url ;
: release-url ( builder -- url )
[ URL" $mason-app/release" ] dip
[ URL" http://builds.factorcode.org/release" ] dip
[ os>> "os" set-query-param ]
[ cpu>> "cpu" set-query-param ] bi
adjust-url ;

View File

@ -8,7 +8,7 @@ furnace.auth.features.registration furnace.auth.login
furnace.boilerplate furnace.redirection html.forms http.server
http.server.dispatchers kernel namespaces site-watcher site-watcher.db
site-watcher.private urls validators io.sockets.secure.unix.debug
io.servers.connection io.files.temp db db.tuples sequences
io.servers io.files.temp db db.tuples sequences
webapps.site-watcher.common webapps.site-watcher.watching
webapps.site-watcher.spidering ;
QUALIFIED: assocs

View File

@ -122,7 +122,7 @@ furnace.auth.features.edit-profile
furnace.auth.features.deactivate-user
db.sqlite
furnace.alloy
io.servers.connection
io.servers
io.sockets.secure ;
: <login-config> ( responder -- responder' )

View File

@ -1,7 +1,7 @@
! Copyright (c) 2008, 2010 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel sequences assocs io.files io.pathnames
io.sockets io.sockets.secure io.servers.connection
io.sockets io.sockets.secure io.servers
namespaces db db.tuples db.sqlite smtp urls
logging.insomniac
html.templates.chloe
@ -26,7 +26,8 @@ webapps.wiki
webapps.user-admin
webapps.help
webapps.mason
webapps.mason.backend ;
webapps.mason.backend
websites.factorcode ;
IN: websites.concatenative
: test-db ( -- db ) "resource:test.db" <sqlite-db> ;
@ -44,11 +45,11 @@ IN: websites.concatenative
} ensure-tables
] with-db ;
TUPLE: factor-website < dispatcher ;
TUPLE: concatenative-website < dispatcher ;
: <factor-boilerplate> ( responder -- responder' )
<boilerplate>
{ factor-website "page" } >>template ;
{ concatenative-website "page" } >>template ;
: <login-config> ( responder -- responder' )
"Factor website" <login-realm>
@ -64,8 +65,8 @@ TUPLE: factor-website < dispatcher ;
"6LeJWQgAAAAAAFlYV7SuBClE9uSpGtV_ZS-qVON7" >>public-key
"6LeJWQgAAAAAALh-XJgSSQ6xKygRgJ8-029Ip2Xv" >>private-key ;
: <factor-website> ( -- responder )
factor-website new-dispatcher
: <concatenative-website> ( -- responder )
concatenative-website new-dispatcher
URL" /wiki/view/Front Page" <redirect-responder> "" add-responder ;
SYMBOL: key-password
@ -84,7 +85,7 @@ SYMBOL: dh-file
"vocab:openssl/test/server.pem" key-file set-global
"password" key-password set-global
common-configuration
<factor-website>
<concatenative-website>
<wiki> <login-config> <factor-boilerplate> "wiki" add-responder
<user-admin> <login-config> <factor-boilerplate> "user-admin" add-responder
<pastebin> <factor-recaptcha> <login-config> <factor-boilerplate> "pastebin" add-responder
@ -102,7 +103,7 @@ SYMBOL: dh-file
: init-production ( -- )
common-configuration
<vhost-dispatcher>
<factor-website>
<concatenative-website>
<wiki> "wiki" add-responder
<user-admin> "user-admin" add-responder
<login-config> <factor-boilerplate> test-db <alloy> "concatenative.org" add-responder
@ -111,6 +112,7 @@ SYMBOL: dh-file
<mason-app> <login-config> <factor-boilerplate> test-db <alloy> "builds.factorcode.org" add-responder
home "docs" append-path <help-webapp> "docs.factorcode.org" add-responder
home "cgi" append-path <gitweb> "gitweb.factorcode.org" add-responder
<factor-website> "new.factorcode.org" add-responder
main-responder set-global ;
: <factor-secure-config> ( -- config )
@ -119,7 +121,7 @@ SYMBOL: dh-file
dh-file get >>dh-file
key-password get >>password ;
: <factor-website-server> ( -- threaded-server )
: <concatenative-website-server> ( -- threaded-server )
<http-server>
<factor-secure-config> >>secure-config
8080 >>insecure
@ -129,4 +131,4 @@ SYMBOL: dh-file
test-db start-expiring
test-db start-update-task
http-insomniac
<factor-website-server> start-server ;
<concatenative-website-server> start-server ;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,57 @@
USING: io math sequences ;
"Hello world" print
10 [ "Hello, Factor" print ] times
"Hello, " "Factor" append print
----
USING: io kernel sequences
http.client xml xml.data xml.traversal ;
"http://factorcode.org" http-get nip string>xml
"a" deep-tags-named
[ "href" attr ] map
[ print ] each
----
USING: accessors kernel math math.constants
math.functions prettyprint ;
IN: shapes
TUPLE: circle radius ;
TUPLE: rectangle width height ;
GENERIC: area ( shape -- area )
M: circle area radius>> sq pi * ;
M: rectangle area [ width>> ] [ height>> ] bi * ;
rectangle new 10 >>width 20 >>height area .
----
USING: accessors smtp ;
&lt;email>
"john@foobar.com" >>from
{ "jane@foobar.com" } >>to
"Up for lunch?" >>subject
"At Tracy's." >>body
send-email
----
USING: io.files io.encodings.utf8 kernel
sequences splitting ;
"table.txt" utf8 [
file-lines
[ "|" split ] map flip [ "|" join ] map
] 2keep
set-file-lines
----
USING: sequences xml.syntax xml.writer ;
{ "three" "blind" "mice" }
[ [XML &lt;li>&lt;->&lt;/li> XML] ] map
[XML &lt;ul>&lt;->&lt;/ul> XML]
pprint-xml
----
USING: inspector io.files.info io.pathnames system tools.files ;
home directory.
home file-system-info free-space>> .
image file-info describe

View File

@ -0,0 +1,17 @@
! Copyright (c) 2010 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: accessors http.server http.server.dispatchers
http.server.static kernel namespaces sequences ;
IN: websites.factorcode
SYMBOL: users
: <factor-website> ( -- website )
<dispatcher>
"resource:extra/websites/factorcode/" <static> enable-fhtml >>default
users get [
[ "/home/" "/www/" surround <static> ] keep add-responder
] each ;
: init-testing ( -- )
<factor-website> main-responder set-global ;

View File

@ -0,0 +1,103 @@
<% USING: namespaces http.client kernel io.files splitting random io io.encodings.utf8 sequences
webapps.mason.version.data webapps.mason.backend webapps.mason.grids webapps.mason.downloads
webapps.mason.utils html.elements accessors
xml.writer ; %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Factor programming language</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8" />
</head>
<body>
<div><img src="logo.png" alt="Factor programming language" /></div>
<table border="0" width="100%">
<tr>
<td width="50%" valign="top">
<h1>Why Factor?</h1>
<p>The <big>Factor programming language</big> combines <a href="http://concatenative.org/wiki/view/Factor/Features/The%20language">powerful language features</a> with a <a href="http://docs.factorcode.org/content/article-vocab-index.html">full-featured library</a>. The implementation is <a href="http://concatenative.org/wiki/view/Factor/Optimizing%20compiler">fully compiled</a> for performance, while still supporting <a href="http://concatenative.org/wiki/view/Factor/Interactive development">interactive development</a>. Factor applications are portable between all common platforms. Factor can <a href="http://concatenative.org/wiki/view/Factor/Deployment">deploy stand-alone applications</a> on all platforms. Full source code for the Factor project is available under a <a href="http://factorcode.org/license.txt">BSD license</a>.</p>
<ul>
<li>Screenshots: <a href="http://factorcode.org/factor-macosx.png">Mac OS X</a>, <a href="http://factorcode.org/factor-windows7.png">Windows</a></li>
<li><a href="http://concatenative.org/wiki/view/Factor">Learn more about Factor</a></li>
<li><a href="http://concatenative.org/wiki/view/Factor/Learning">Get started programming with Factor</a></li>
<li><a href="http://concatenative.org/wiki/view/Factor/FAQ">Get answers to frequently-asked questions</a></li>
<li><a href="http://docs.factorcode.org/">Read Factor reference documentation online</a></li>
<li><a href="http://concatenative.org/wiki/view/Concatenative%20language">Learn more about concatenative programming</a></li>
</ul>
<p>Most of the above links point to pages on the <a href="http://concatenative.org">concatenative.org wiki</a>.</p>
</td>
<td width="50%" valign="top">
<h1>Show me some code!</h1>
<p>Factor belongs to the family of <em><a href="http://concatenative.org/wiki/view/Concatenative%20language">concatenative languages</a></em>: this means that, at the lowest level, a Factor program is a series of words (functions) that manipulate a stack of references to dynamically-typed values. This gives the language a powerful foundation which allows many abstractions and paradigms to be built on top. Reload this page to see a random code example below.</p>
<pre>
<%
"resource:extra/websites/factorcode/examples.txt" utf8 file-lines
{ "----" } split random "\n" join write
%>
</pre>
<p>See the <a href="http://concatenative.org/wiki/view/Factor/Examples">example programs</a> page on the wiki for more.</p>
</td>
</tr>
</table>
<h1>Downloads</h1>
<% [ %>
<p>To download a binary, follow the link corresponding to your computer's CPU/OS configuration. Binary packages are the recommended route for new users who wish to try Factor.</p>
<h2>Stable release:
<% latest-version <a [ announcement-url>> =href a> ] [ version>> write ] bi </a> %>
</h2>
<table id="mytable" cellspacing="0" summary="Stable releases">
<% release-grid write-xml %>
</table>
<p><b>Source code</b>:
<% latest-version <a [ source-path>> download-url =href a> ] [ version>> write ] bi </a> %>
</p>
<h2>Development release</h2>
<table id="mytable" cellspacing="0" summary="Development releases">
<% package-grid write-xml %>
</table>
<% ] with-mason-db %>
<p>Stable and development releases are built and uploaded by the <a href="http://concatenative.org/wiki/view/Factor/Build farm">build farm</a>. Follow <a href="http://twitter.com/FactorBuilds">@FactorBuilds</a> on Twitter to receive notifications. If you're curious, take a look at the <a href="http://builds.factorcode.org/dashboard">build farm dashboard</a>.</p>
<p><b>Source code</b> is stored in our <a href="http://concatenative.org/wiki/view/Factor/GIT repository">GIT repository</a>. Source can can be browsed online via <a href="http://github.com/slavapestov/factor/">github</a> or <a href="http://gitweb.factorcode.org/">gitweb</a>.</p>
<h1>More</h1>
<ul>
<li><a href="http://concatenative.org/wiki/view/Factor/Mailing list">Join the mailing list</a></li>
<li><a href="http://concatenative.org/wiki/view/Concatenative IRC channel">Join the IRC channel</a></li>
<li><a href="http://planet.factorcode.org/">planet.factorcode.org</a> - Factor community blogs</li>
<li><a href="http://concatenative.org/wiki/view/Concatenative%20language/Publications">Academic publications</a></li>
<li><a href="http://paste.factorcode.org/">Factor community pastebin</a> - if you're in an IRC channel and want to share some code</li>
</ul>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -0,0 +1,144 @@
body {
font:75%/1.6em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
}
ul {
margin:10px 10px 10px 0;
padding:0 0 0 15px;
}
li {
margin:0 0 0 10px;
padding:5px;
}
a {
color:#222;
border-bottom:1px solid #aaa;
text-decoration:none;
}
a:hover {
border-bottom:1px solid #ccc;
}
ol.subnav {
margin:-10px -10px 0 -5px;
padding:0;
}
ol.subnav li {
font:85%/0.9em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
float:left;
list-style:none;
margin:0;
padding:0;
}
ol.subnav a {
font-weight:bold;
color:#555;
border-top:2px solid #fff;
display:block;
padding:5px;
text-decoration:none;
margin:0 5px 0 0;
border-bottom:none;
}
ol.subnav a:hover {
border-top:2px solid #943329;
color:#121212;
border-bottom:none;
}
#downloads {
width: 520px;
padding: 0;
margin: 0;
}
caption {
padding: 0 0 5px 0;
width: 520px;
font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
text-align: right;
}
th {
font: bold 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
color: #4f6b72;
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
border-top: 1px solid #C1DAD7;
letter-spacing: 2px;
text-transform: uppercase;
padding: 6px 6px 6px 6px;
background: #CAE8EA url(bg_header.jpg) no-repeat;
}
th.nobg {
border-top: 0;
border-left: 0;
border-right: 1px solid #C1DAD7;
background: none;
}
pre {
border: 1px dashed #ccc;
background-color: #f5f5f5;
font-size: 120%;
}
td.alt {
background: #F5FAFA;
color: #797268;
}
td.doesnotexist {
background: #E5EAEA;
}
td.unsupported {
background: #ffaaaa;
}
td.supported {
background: #aaffaa;
}
td.supported :hover { background-color: #88ff88; }
td.nobinary {
background: #eeee88;
}
div.bigdiv {
width: 100px;
text-align: center;
color: #050;
}
th.spec {
border-left: 1px solid #C1DAD7;
border-top: 0;
background: #fff;
font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
}
th.specalt {
border-left: 1px solid #C1DAD7;
border-top: 0;
background: #f5fafa;
font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
color: #797268;
}
th.allbg {
border-top: 0;
border-left: 0;
border-right: 0;
background: none;
}

View File

@ -60,9 +60,9 @@ void context::scrub_stacks(gc_info *info, cell index)
u8 *bitmap = info->gc_info_bitmap();
{
cell base = info->scrub_d_base(index);
cell base = info->callsite_scrub_d(index);
for(int loc = 0; loc < info->scrub_d_count; loc++)
for(cell loc = 0; loc < info->scrub_d_count; loc++)
{
if(bitmap_p(bitmap,base + loc))
{
@ -75,9 +75,9 @@ void context::scrub_stacks(gc_info *info, cell index)
}
{
cell base = info->scrub_r_base(index);
cell base = info->callsite_scrub_r(index);
for(int loc = 0; loc < info->scrub_r_count; loc++)
for(cell loc = 0; loc < info->scrub_r_count; loc++)
{
if(bitmap_p(bitmap,base + loc))
{

View File

@ -3,17 +3,17 @@
namespace factor
{
int gc_info::return_address_index(cell return_address)
cell gc_info::return_address_index(cell return_address)
{
u32 *return_address_array = return_addresses();
for(int i = 0; i < return_address_count; i++)
for(cell i = 0; i < return_address_count; i++)
{
if(return_address == return_address_array[i])
return i;
}
return -1;
return gc_info_missing_value;
}
}

View File

@ -1,15 +1,23 @@
namespace factor
{
const u32 gc_info_missing_value = (u32)-1;
struct gc_info {
int scrub_d_count;
int scrub_r_count;
int gc_root_count;
int return_address_count;
u32 scrub_d_count;
u32 scrub_r_count;
u32 gc_root_count;
u32 derived_root_count;
u32 return_address_count;
cell callsite_bitmap_size()
{
return scrub_d_count + scrub_r_count + gc_root_count;
}
cell total_bitmap_size()
{
return return_address_count * (scrub_d_count + scrub_r_count + gc_root_count);
return return_address_count * callsite_bitmap_size();
}
cell total_bitmap_bytes()
@ -19,33 +27,43 @@ struct gc_info {
u32 *return_addresses()
{
return (u32 *)((u8 *)this - return_address_count * sizeof(u32));
return (u32 *)this - return_address_count;
}
u32 *base_pointer_map()
{
return return_addresses() - return_address_count * derived_root_count;
}
u8 *gc_info_bitmap()
{
return (u8 *)return_addresses() - total_bitmap_bytes();
return (u8 *)base_pointer_map() - total_bitmap_bytes();
}
cell scrub_d_base(cell index)
cell callsite_scrub_d(cell index)
{
return index * scrub_d_count;
}
cell scrub_r_base(cell index)
cell callsite_scrub_r(cell index)
{
return return_address_count * scrub_d_count +
index * scrub_r_count;
}
cell spill_slot_base(cell index)
cell callsite_gc_roots(cell index)
{
return return_address_count * scrub_d_count
+ return_address_count * scrub_r_count
+ index * gc_root_count;
}
int return_address_index(cell return_address);
cell lookup_base_pointer(cell index, cell derived_root)
{
return base_pointer_map()[index * derived_root_count + derived_root];
}
cell return_address_index(cell return_address);
};
}

View File

@ -292,27 +292,52 @@ struct call_frame_slot_visitor {
gc_info *info = compiled->block_gc_info();
assert(return_address < compiled->size());
int index = info->return_address_index(return_address);
if(index == -1)
u32 callsite = info->return_address_index(return_address);
if(callsite == gc_info_missing_value)
return;
#ifdef DEBUG_GC_MAPS
std::cout << "call frame code block " << compiled << " with offset " << return_address << std::endl;
#endif
u8 *bitmap = info->gc_info_bitmap();
cell base = info->spill_slot_base(index);
cell *stack_pointer = (cell *)(parent->frame_successor(frame) + 1);
u8 *bitmap = info->gc_info_bitmap();
for(int spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++)
/* Subtract old value of base pointer from every derived pointer. */
for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++)
{
if(bitmap_p(bitmap,base + spill_slot))
cell base_pointer = info->lookup_base_pointer(callsite, spill_slot);
if(base_pointer != gc_info_missing_value)
{
#ifdef DEBUG_GC_MAPS
std::cout << "visiting spill slot " << spill_slot << std::endl;
std::cout << "visiting derived root " << spill_slot
<< " with base pointer " << base_pointer
<< std::endl;
#endif
stack_pointer[spill_slot] -= stack_pointer[base_pointer];
}
}
/* Update all GC roots, including base pointers. */
cell callsite_gc_roots = info->callsite_gc_roots(callsite);
for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++)
{
if(bitmap_p(bitmap,callsite_gc_roots + spill_slot))
{
#ifdef DEBUG_GC_MAPS
std::cout << "visiting GC root " << spill_slot << std::endl;
#endif
visitor->visit_handle(stack_pointer + spill_slot);
}
}
/* Add the base pointers to obtain new derived pointer values. */
for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++)
{
cell base_pointer = info->lookup_base_pointer(callsite, spill_slot);
if(base_pointer != gc_info_missing_value)
stack_pointer[spill_slot] += stack_pointer[base_pointer];
}
}
};

View File

@ -329,14 +329,16 @@ struct factor_vm
return (Type *)allot_object(Type::type_number,size);
}
inline bool in_data_heap_p(cell pointer)
{
return (pointer >= data->seg->start && pointer < data->seg->end);
}
inline void check_data_pointer(object *pointer)
{
#ifdef FACTOR_DEBUG
if(!(current_gc && current_gc->op == collect_growing_heap_op))
{
assert((cell)pointer >= data->seg->start
&& (cell)pointer < data->seg->end);
}
assert(in_data_heap_p((cell)pointer));
#endif
}