1 ! Copyright (C) 2007, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays accessors io.backend io.streams.c init fry namespaces
4 math make assocs kernel parser parser.notes lexer strings.parser
5 vocabs sequences sequences.private words memory kernel.private
6 continuations io vocabs.loader system strings sets vectors quotations
7 byte-arrays sorting compiler.units definitions generic
8 generic.standard generic.single tools.deploy.config combinators
9 classes classes.builtin slots.private grouping ;
10 QUALIFIED: bootstrap.stage2
11 QUALIFIED: command-line
12 QUALIFIED: compiler.errors
13 QUALIFIED: continuations
14 QUALIFIED: definitions
17 QUALIFIED: source-files
18 QUALIFIED: source-files.errors
20 IN: tools.deploy.shaker
22 ! This file is some hairy shit.
24 : strip-init-hooks ( -- )
25 "Stripping startup hooks" show
33 [ init-hooks get delete-at ] each
35 "threads" init-hooks get delete-at
38 "io.thread" init-hooks get delete-at
41 "io.files" init-hooks get delete-at
42 "io.backend" init-hooks get delete-at
43 "io.thread" init-hooks get delete-at
51 } [ init-hooks get delete-at ] each
54 : strip-debugger ( -- )
55 strip-debugger? "debugger" vocab and [
56 "Stripping debugger" show
57 "vocab:tools/deploy/shaker/strip-debugger.factor"
63 "Stripping manual memory management debug code" show
64 "vocab:tools/deploy/shaker/strip-libc.factor"
69 "Stripping stack effect checking from call( and execute(" show
70 "vocab:tools/deploy/shaker/strip-call.factor" run-file ;
74 "Stripping unused Cocoa methods" show
75 "vocab:tools/deploy/shaker/strip-cocoa.factor"
79 : strip-word-names ( words -- )
80 "Stripping word names" show
81 [ f >>name f >>vocabulary drop ] each ;
83 : strip-word-defs ( words -- )
84 "Stripping symbolic word definitions" show
85 [ "no-def-strip" word-prop not ] filter
86 [ [ ] >>def drop ] each ;
88 : sift-assoc ( assoc -- assoc' ) [ nip ] assoc-filter ;
90 : strip-word-props ( stripped-props words -- )
91 "Stripping word properties" show
95 [ drop _ member? not ] assoc-filter sift-assoc
101 [ [ _ [ ] cache ] map ] change-props drop
105 : stripped-word-props ( -- seq )
113 "compiled-generic-uses"
121 "default-output-classes"
153 "predicate-definition"
190 : strip-words ( props -- )
192 deploy-word-props? get [ 2dup strip-word-props ] unless
193 deploy-word-defs? get [ dup strip-word-defs ] unless
194 strip-word-names? [ dup strip-word-names ] when
197 : compiler-classes ( -- seq )
198 { "compiler" "stack-checker" }
199 [ child-vocabs [ words ] map concat [ class? ] filter ]
202 : prune-decision-tree ( tree classes -- )
203 [ tuple class>type ] 2dip '[
209 [ drop _ key? not ] assoc-filter
217 : strip-compiler-classes ( -- )
219 "Stripping compiler classes" show
220 [ single-generic? ] instances
221 compiler-classes '[ "decision-tree" word-prop _ prune-decision-tree ] each
224 : recursive-subst ( seq old new -- )
229 { [ 3dup drop eq? ] [ 2nip ] }
230 ! recurse into arrays
231 { [ pick array? ] [ [ dup ] 2dip recursive-subst ] }
232 ! otherwise do nothing
237 : strip-default-method ( generic new-default -- )
239 [ "decision-tree" word-prop ]
240 [ "default-method" word-prop ] bi
244 : new-default-method ( -- gensym )
245 [ [ "No method" throw ] (( -- * )) define-temp ] with-compilation-unit ;
247 : strip-default-methods ( -- )
248 ! In a development image, each generic has its own default method.
249 ! This gives better error messages for runtime type errors, but
250 ! takes up space. For deployment we merge them all together.
252 "Stripping default methods" show
253 [ single-generic? ] instances
254 new-default-method '[ _ strip-default-method ] each
257 : strip-vocab-globals ( except names -- words )
258 [ child-vocabs [ words ] map concat ] map concat
259 swap [ first2 lookup ] map sift diff ;
261 : stripped-globals ( -- seq )
263 "inspector-hook" "inspector" lookup ,
267 continuations:error-continuation
268 continuations:error-thread
269 continuations:restarts
271 source-files:source-files
277 "io-thread" "io.thread" lookup ,
279 "mallocs" "libc.private" lookup ,
282 "initial-thread" "threads" lookup ,
285 strip-io? [ io-backend , ] when
295 } strip-vocab-globals %
298 "libraries" "alien" lookup ,
300 { { "yield-hook" "compiler.utilities" } }
301 { "cpu" "compiler" } strip-vocab-globals %
306 next-method-quot-cache
311 classes-intersect-cache
314 command-line:main-vocab-hook
316 compiled-generic-crossref
318 compiler.errors:compiler-errors
322 source-files.errors:error-types
323 source-files.errors:error-observers
325 vocabs:load-vocab-hook
326 vocabs:vocab-observers
331 { } { "layouts" } strip-vocab-globals %
333 { } { "math.partial-dispatch" } strip-vocab-globals %
335 { } { "math.vectors.specialization" } strip-vocab-globals %
337 { } { "peg" } strip-vocab-globals %
341 { } { "prettyprint.config" } strip-vocab-globals %
346 compiler.errors:compiler-errors
347 continuations:thread-error-hook
351 "ui-error-hook" "ui.gadgets.worlds" lookup ,
355 deploy-c-types? get [
356 "c-types" "alien.c-types" lookup ,
359 "windows-messages" "windows.messages" lookup [ , ] when*
362 : strip-globals ( stripped-globals -- )
364 "Stripping globals" show
366 '[ drop _ member? not ] assoc-filter
367 [ drop string? not ] assoc-filter ! strip CLI args
374 deploy-io get 3 = os windows? not and
378 "io.streams.c" forget-vocab
379 "io-thread-running?" "io.thread" lookup [
382 ] with-compilation-unit
385 : compress ( pred post-process string -- )
386 "Compressing " prepend show
387 [ instances dup H{ } clone [ [ ] cache ] curry map ] dip call
390 : compress-object? ( obj -- ? )
392 { [ dup array? ] [ empty? ] }
393 { [ dup byte-array? ] [ drop t ] }
394 { [ dup string? ] [ drop t ] }
395 { [ dup wrapper? ] [ drop t ] }
399 : compress-objects ( -- )
400 [ compress-object? ] [ ] "objects" compress ;
402 : remain-compiled ( old new -- old new )
403 ! Quotations which were formerly compiled must remain
406 2dup [ quot-compiled? ] [ quot-compiled? not ] bi* and
407 [ nip jit-compile ] [ 2drop ] if
410 : compress-quotations ( -- )
411 [ quotation? ] [ remain-compiled ] "quotations" compress
412 [ quotation? ] instances [ f >>cached-effect f >>cache-counter drop ] each ;
416 : [:c] ( -- word ) ":c" "debugger" lookup ;
418 : [print-error] ( -- word ) "print-error" "debugger" lookup ;
420 : deploy-boot-quot ( word -- )
423 init-hooks get values concat %
424 strip-debugger? [ , ] [
425 ! Don't reference 'try' directly since we don't want
426 ! to pull in the debugger and prettyprinter into every
431 [ _ execute( obj -- ) ] [
432 _ execute( obj -- ) nl
437 strip-io? [ [ flush ] % ] unless
442 : init-stripper ( -- )
444 f output-stream set-global ;
446 : next-method* ( method -- quot )
447 [ "method-class" word-prop ]
448 [ "method-generic" word-prop ] bi
451 : compute-next-methods ( -- )
452 [ standard-generic? ] instances [
453 "methods" word-prop [
454 nip dup next-method* "next-method" set-word-prop
457 "vocab:tools/deploy/shaker/next-methods.factor" run-file ;
459 : (clear-megamorphic-cache) ( i array -- )
460 ! Can't do any dispatch while clearing caches since that
461 ! might leave them in an inconsistent state.
463 2dup [ f ] 2dip set-array-nth
464 [ 1 + ] dip (clear-megamorphic-cache)
467 : clear-megamorphic-cache ( array -- )
468 [ 0 ] dip (clear-megamorphic-cache) ;
470 : find-megamorphic-caches ( -- seq )
471 "Finding megamorphic caches" show
472 [ standard-generic? ] instances [ def>> third ] map ;
474 : clear-megamorphic-caches ( cache -- )
475 "Clearing megamorphic caches" show
476 [ clear-megamorphic-cache ] each ;
487 strip-default-methods
488 strip-compiler-classes
489 f 5 setenv ! we can't use the Factor debugger or Factor I/O anymore
490 deploy-vocab get vocab-main deploy-boot-quot
491 find-megamorphic-caches
493 stripped-globals strip-globals
497 clear-megamorphic-caches ;
499 : deploy-error-handler ( quot -- )
502 [ error-continuation get call>> callstack>array die 1 exit ]
503 ! Don't reference these words literally, if we're stripping the
504 ! debugger out we don't want to load the prettyprinter at all
505 [ [:c] execute( -- ) nl [print-error] execute( error -- ) flush ] if
509 : (deploy) ( final-image vocab config -- )
510 #! Does the actual work of a deployment in the slave
518 "ui.debugger" require
522 deploy-vocab get require
523 deploy-vocab get vocab-main [
524 "Vocabulary has no MAIN: word." print flush 1 exit
527 "Saving final image" show
529 ] deploy-error-handler
535 "Deploying " write dup write "..." print
536 "deploy-config" get parse-file first