1 ! Copyright (C) 2007, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays alien.libraries accessors io.backend io.encodings.utf8 io.files
4 io.streams.c init fry namespaces math make assocs kernel parser
5 parser.notes lexer strings.parser vocabs sequences sequences.deep
6 sequences.private words memory kernel.private continuations io
7 vocabs.loader system strings sets vectors quotations byte-arrays
8 sorting compiler.units definitions generic generic.standard
9 generic.single tools.deploy.config combinators classes
10 classes.builtin slots.private grouping command-line io.pathnames ;
11 QUALIFIED: bootstrap.stage2
12 QUALIFIED: classes.private
13 QUALIFIED: compiler.crossref
14 QUALIFIED: compiler.errors
15 QUALIFIED: continuations
16 QUALIFIED: definitions
19 QUALIFIED: source-files
20 QUALIFIED: source-files.errors
22 FROM: alien.libraries.private => >deployed-library-path ;
23 IN: tools.deploy.shaker
25 ! This file is some hairy shit.
27 : add-command-line-hook ( -- )
28 [ (command-line) command-line set-global ] "command-line"
29 startup-hooks get set-at ;
31 : strip-startup-hooks ( -- )
32 "Stripping startup hooks" show
39 [ startup-hooks get delete-at ] each
41 "threads" startup-hooks get delete-at
44 "io.thread" startup-hooks get delete-at
47 "io.backend" startup-hooks get delete-at
48 "io.thread" startup-hooks get delete-at
55 } [ startup-hooks get delete-at ] each
58 : strip-debugger ( -- )
59 strip-debugger? "debugger" vocab and [
60 "Stripping debugger" show
61 "vocab:tools/deploy/shaker/strip-debugger.factor"
67 "Stripping manual memory management debug code" show
68 "vocab:tools/deploy/shaker/strip-libc.factor"
72 : strip-destructors ( -- )
73 "Stripping destructor debug code" show
74 "vocab:tools/deploy/shaker/strip-destructors.factor"
78 "Stripping stack effect checking from call( and execute(" show
79 "vocab:tools/deploy/shaker/strip-call.factor" run-file ;
83 "Stripping unused Cocoa methods" show
84 "vocab:tools/deploy/shaker/strip-cocoa.factor"
88 : strip-specialized-arrays ( -- )
89 strip-dictionary? "specialized-arrays" vocab and [
90 "Stripping specialized arrays" show
91 "vocab:tools/deploy/shaker/strip-specialized-arrays.factor"
95 : strip-word-names ( words -- )
96 "Stripping word names" show
97 [ f >>name f >>vocabulary drop ] each ;
99 : strip-word-defs ( words -- )
100 "Stripping symbolic word definitions" show
101 [ "no-def-strip" word-prop not ] filter
102 [ [ ] >>def drop ] each ;
104 : sift-assoc ( assoc -- assoc' ) [ nip ] assoc-filter ;
106 : strip-word-props ( stripped-props words -- )
107 "Stripping word properties" show
110 [ drop _ member? not ] assoc-filter sift-assoc
115 : stripped-word-props ( -- seq )
124 "effect-dependencies"
125 "definition-dependencies"
126 "conditional-dependencies"
135 "default-output-classes"
167 "predicate-definition"
206 deploy-c-types? get [
207 { "c-type" "struct-slots" "struct-align" } %
211 : strip-words ( props -- )
213 deploy-word-props? get [ 2dup strip-word-props ] unless
214 deploy-word-defs? get [ dup strip-word-defs ] unless
215 strip-word-names? [ dup strip-word-names strip-stack-traces ] when
218 : compiler-classes ( -- seq )
219 { "compiler" "stack-checker" }
220 [ child-vocabs [ words ] map concat [ class? ] filter ]
223 : prune-decision-tree ( tree classes -- )
224 [ tuple class>type ] 2dip '[
230 [ drop _ key? not ] assoc-filter
238 : strip-compiler-classes ( -- )
240 "Stripping compiler classes" show
241 [ single-generic? ] instances
242 compiler-classes '[ "decision-tree" word-prop _ prune-decision-tree ] each
245 : recursive-subst ( seq old new -- )
250 { [ 3dup drop eq? ] [ 2nip ] }
251 ! recurse into arrays
252 { [ pick array? ] [ [ dup ] 2dip recursive-subst ] }
253 ! otherwise do nothing
258 : strip-default-method ( generic new-default -- )
260 [ "decision-tree" word-prop ]
261 [ "default-method" word-prop ] bi
265 : new-default-method ( -- gensym )
266 [ [ "No method" throw ] (( -- * )) define-temp ] with-compilation-unit ;
268 : strip-default-methods ( -- )
269 ! In a development image, each generic has its own default method.
270 ! This gives better error messages for runtime type errors, but
271 ! takes up space. For deployment we merge them all together.
273 "Stripping default methods" show
274 [ single-generic? ] instances
275 new-default-method '[ _ strip-default-method ] each
278 : strip-vocab-globals ( except names -- words )
279 [ child-vocabs [ words ] map concat ] map concat
280 swap [ first2 lookup ] map sift diff ;
282 : stripped-globals ( -- seq )
284 "inspector-hook" "inspector" lookup ,
288 continuations:error-continuation
289 continuations:error-thread
290 continuations:restarts
292 source-files:source-files
301 "io-thread" "io.thread" lookup ,
303 "disposables" "destructors" lookup ,
305 "functor-words" "functors.backend" lookup ,
308 "initial-thread" "threads" lookup ,
311 strip-io? [ io-backend , ] when
321 } strip-vocab-globals %
324 "libraries" "alien" lookup ,
326 { { "yield-hook" "compiler.utilities" } }
327 { "cpu" "compiler" } strip-vocab-globals %
332 classes.private:next-method-quot-cache
333 classes.private:class-and-cache
334 classes.private:class-not-cache
335 classes.private:class-or-cache
336 classes.private:class<=-cache
337 classes.private:classes-intersect-cache
338 classes.private:implementors-map
339 classes.private:update-map
341 compiler.crossref:compiled-crossref
342 compiler.crossref:generic-call-site-crossref
344 compiler.errors:compiler-errors
348 source-files.errors:error-types
349 source-files.errors:error-observers
351 vocabs:load-vocab-hook
352 vocabs:vocab-observers
357 { } { "layouts" } strip-vocab-globals %
359 { } { "math.partial-dispatch" } strip-vocab-globals %
361 { } { "math.vectors.simd" } strip-vocab-globals %
363 { } { "peg" } strip-vocab-globals %
367 { } { "prettyprint.config" } strip-vocab-globals %
372 compiler.errors:compiler-errors
373 continuations:thread-error-hook
377 "ui-error-hook" "ui.gadgets.worlds" lookup ,
381 deploy-c-types? get [
382 "c-types" "alien.c-types" lookup ,
385 "windows-messages" "windows.messages" lookup [ , ] when*
388 : strip-globals ( stripped-globals -- )
390 "Stripping globals" show
392 '[ drop _ member? not ] assoc-filter
393 [ drop string? not ] assoc-filter ! strip CLI args
395 21 set-special-object
400 deploy-io get 3 = os windows? not and
404 "io.streams.c" forget-vocab
405 "io-thread-running?" "io.thread" lookup [
408 ] with-compilation-unit
411 : compress ( pred post-process string -- )
412 "Compressing " prepend show
413 [ instances dup H{ } clone [ [ ] cache ] curry map ] dip call
416 : compress-object? ( obj -- ? )
418 { [ dup array? ] [ empty? ] }
419 { [ dup byte-array? ] [ drop t ] }
420 { [ dup string? ] [ drop t ] }
421 { [ dup wrapper? ] [ drop t ] }
425 : compress-objects ( -- )
426 [ compress-object? ] [ ] "objects" compress ;
428 : remain-compiled ( old new -- old new )
429 ! Quotations which were formerly compiled must remain
432 2dup [ quot-compiled? ] [ quot-compiled? not ] bi* and
433 [ nip jit-compile ] [ 2drop ] if
436 : compress-quotations ( -- )
437 [ quotation? ] [ remain-compiled ] "quotations" compress
438 [ quotation? ] instances [ f >>cached-effect f >>cache-counter drop ] each ;
442 : [:c] ( -- word ) ":c" "debugger" lookup ;
444 : [print-error] ( -- word ) "print-error" "debugger" lookup ;
446 : deploy-startup-quot ( word -- )
449 startup-hooks get values concat %
450 strip-debugger? [ , ] [
451 ! Don't reference 'try' directly since we don't want
452 ! to pull in the debugger and prettyprinter into every
457 [ _ execute( obj -- ) ] [
458 _ execute( obj -- ) nl
463 strip-io? [ [ flush ] % ] unless
468 : startup-stripper ( -- )
470 f output-stream set-global
471 V{ "resource:" } clone vocab-roots set-global ;
473 : next-method* ( method -- quot )
474 [ "method-class" word-prop ]
475 [ "method-generic" word-prop ] bi
478 : calls-next-method? ( method -- ? )
479 def>> flatten \ (call-next-method) swap member-eq? ;
481 : compute-next-methods ( -- )
482 [ standard-generic? ] instances [
483 "methods" word-prop values [ calls-next-method? ] filter
484 [ dup next-method* "next-method" set-word-prop ] each
486 "vocab:tools/deploy/shaker/next-methods.factor" run-file ;
488 : (clear-megamorphic-cache) ( i array -- )
489 ! Can't do any dispatch while clearing caches since that
490 ! might leave them in an inconsistent state.
492 2dup [ f ] 2dip set-array-nth
493 [ 1 + ] dip (clear-megamorphic-cache)
496 : clear-megamorphic-cache ( array -- )
497 [ 0 ] dip (clear-megamorphic-cache) ;
499 : find-megamorphic-caches ( -- seq )
500 "Finding megamorphic caches" show
501 [ standard-generic? ] instances [ def>> third ] map ;
503 : clear-megamorphic-caches ( cache -- )
504 "Clearing megamorphic caches" show
505 [ clear-megamorphic-cache ] each ;
507 : write-vocab-manifest ( vocab-manifest-out -- )
508 "Writing vocabulary manifest to " write dup print flush
509 vocabs "VOCABS:" prefix
510 deploy-libraries get [ libraries get path>> ] map "LIBRARIES:" prefix append
511 swap utf8 set-file-lines ;
513 : prepare-deploy-libraries ( -- )
514 "Preparing deployed libraries" print flush
515 deploy-libraries get [
517 [ path>> >deployed-library-path ] [ abi>> ] bi <library>
522 "deploy-libraries" "alien.libraries" lookup forget
523 "deploy-library" "alien.libraries" lookup forget
524 ">deployed-library-path" "alien.libraries.private" lookup forget
525 ] with-compilation-unit ;
527 : strip ( vocab-manifest-out -- )
528 [ write-vocab-manifest ] when*
530 prepare-deploy-libraries
536 strip-specialized-arrays
539 add-command-line-hook
541 strip-default-methods
542 strip-compiler-classes
543 f 5 set-special-object ! we can't use the Factor debugger or Factor I/O anymore
544 deploy-vocab get vocab-main deploy-startup-quot
545 find-megamorphic-caches
547 stripped-globals strip-globals
551 clear-megamorphic-caches ;
553 : deploy-error-handler ( quot -- )
556 [ error-continuation get call>> callstack>array die 1 exit ]
557 ! Don't reference these words literally, if we're stripping the
558 ! debugger out we don't want to load the prettyprinter at all
559 [ [:c] execute( -- ) nl [print-error] execute( error -- ) flush ] if
563 : (deploy) ( final-image vocab-manifest-out vocab config -- )
564 #! Does the actual work of a deployment in the slave
570 "tools.errors" require
573 "ui.debugger" require
576 [ deploy-vocab set ] [ require ] [
578 "Vocabulary has no MAIN: word." print flush 1 exit
582 "Saving final image" show
584 ] deploy-error-handler
589 "vocab-manifest-out" get
591 "Deploying " write dup write "..." print
592 "deploy-config" get parse-file first