Merge remote-tracking branch 'upstream/master'
						commit
						b6bd35fd4b
					
				| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
! Copyright (C) 2004, 2010 Slava Pestov, Daniel Ehrenberg.
 | 
			
		||||
! Copyright (C) 2004, 2011 Slava Pestov, Daniel Ehrenberg.
 | 
			
		||||
! See http://factorcode.org/license.txt for BSD license.
 | 
			
		||||
USING: fry accessors alien alien.accessors alien.private arrays
 | 
			
		||||
byte-arrays classes continuations.private effects generic
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ quotations.private sbufs sbufs.private sequences
 | 
			
		|||
sequences.private slots.private strings strings.private system
 | 
			
		||||
threads.private classes.tuple classes.tuple.private vectors
 | 
			
		||||
vectors.private words words.private definitions assocs summary
 | 
			
		||||
compiler.units system.private combinators
 | 
			
		||||
compiler.units system.private combinators tools.memory.private
 | 
			
		||||
combinators.short-circuit locals locals.backend locals.types
 | 
			
		||||
combinators.private stack-checker.values generic.single
 | 
			
		||||
generic.single.private alien.libraries tools.dispatch.private
 | 
			
		||||
| 
						 | 
				
			
			@ -348,13 +348,13 @@ M: object infer-call* \ call bad-macro-input ;
 | 
			
		|||
\ callstack-for { c-ptr } { callstack } define-primitive \ callstack make-flushable
 | 
			
		||||
\ callstack>array { callstack } { array } define-primitive \ callstack>array make-flushable
 | 
			
		||||
\ check-datastack { array integer integer } { object } define-primitive \ check-datastack make-flushable
 | 
			
		||||
\ code-room { } { byte-array } define-primitive \ code-room  make-flushable
 | 
			
		||||
\ (code-room) { } { byte-array } define-primitive \ (code-room)  make-flushable
 | 
			
		||||
\ compact-gc { } { } define-primitive
 | 
			
		||||
\ compute-identity-hashcode { object } { } define-primitive
 | 
			
		||||
\ context-object { fixnum } { object } define-primitive \ context-object make-flushable
 | 
			
		||||
\ context-object-for { fixnum c-ptr } { object } define-primitive \ context-object-for make-flushable
 | 
			
		||||
\ current-callback { } { fixnum } define-primitive \ current-callback make-flushable
 | 
			
		||||
\ data-room { } { byte-array } define-primitive \ data-room make-flushable
 | 
			
		||||
\ (data-room) { } { byte-array } define-primitive \ (data-room) make-flushable
 | 
			
		||||
\ datastack { } { array } define-primitive \ datastack make-flushable
 | 
			
		||||
\ datastack-for { c-ptr } { array } define-primitive \ datastack-for make-flushable
 | 
			
		||||
\ die { } { } define-primitive
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,3 +48,11 @@ HELP: gc-summary.
 | 
			
		|||
 | 
			
		||||
HELP: gc-events
 | 
			
		||||
{ $var-description "A sequence of " { $link gc-event } " instances, set by " { $link collect-gc-events } ". Can be inspected directly, or with the " { $link gc-events. } ", " { $link gc-stats. } " and " { $link gc-summary. } " words." } ;
 | 
			
		||||
 | 
			
		||||
HELP: data-room
 | 
			
		||||
{ $values { "data-heap-room" data-heap-room } }
 | 
			
		||||
{ $description "Queries the VM for memory usage information." } ;
 | 
			
		||||
 | 
			
		||||
HELP: code-room
 | 
			
		||||
{ $values { "mark-sweep-sizes" mark-sweep-sizes } }
 | 
			
		||||
{ $description "Queries the VM for memory usage information." } ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,11 @@
 | 
			
		|||
! Copyright (C) 2005, 2010 Slava Pestov.
 | 
			
		||||
! Copyright (C) 2005, 2011 Slava Pestov.
 | 
			
		||||
! See http://factorcode.org/license.txt for BSD license.
 | 
			
		||||
USING: accessors arrays assocs binary-search classes
 | 
			
		||||
classes.struct combinators combinators.smart continuations fry
 | 
			
		||||
generalizations generic grouping io io.styles kernel make math
 | 
			
		||||
math.order math.parser math.statistics memory memory.private
 | 
			
		||||
layouts namespaces parser prettyprint sequences
 | 
			
		||||
sequences.generalizations sorting splitting strings system vm
 | 
			
		||||
words hints hashtables ;
 | 
			
		||||
math.order math.parser math.statistics memory layouts namespaces
 | 
			
		||||
parser prettyprint sequences sequences.generalizations sorting
 | 
			
		||||
splitting strings system vm words hints hashtables ;
 | 
			
		||||
IN: tools.memory
 | 
			
		||||
 | 
			
		||||
<PRIVATE
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +57,12 @@ IN: tools.memory
 | 
			
		|||
 | 
			
		||||
PRIVATE>
 | 
			
		||||
 | 
			
		||||
: data-room ( -- data-heap-room )
 | 
			
		||||
    (data-room) data-heap-room memory>struct ;
 | 
			
		||||
 | 
			
		||||
: data-room. ( -- )
 | 
			
		||||
    "== Data heap ==" print nl
 | 
			
		||||
    data-room data-heap-room memory>struct {
 | 
			
		||||
    data-room {
 | 
			
		||||
        [ nursery-room. nl ]
 | 
			
		||||
        [ aging-room. nl ]
 | 
			
		||||
        [ tenured-room. nl ]
 | 
			
		||||
| 
						 | 
				
			
			@ -286,9 +288,12 @@ INSTANCE: code-blocks immutable-sequence
 | 
			
		|||
 | 
			
		||||
PRIVATE>
 | 
			
		||||
 | 
			
		||||
: code-room ( -- mark-sweep-sizes )
 | 
			
		||||
    (code-room) mark-sweep-sizes memory>struct ;
 | 
			
		||||
 | 
			
		||||
: code-room. ( -- )
 | 
			
		||||
    "== Code heap ==" print nl
 | 
			
		||||
    code-room mark-sweep-sizes memory>struct mark-sweep-table. nl
 | 
			
		||||
    code-room mark-sweep-table. nl
 | 
			
		||||
    code-blocks code-block-stats code-block-table. ;
 | 
			
		||||
 | 
			
		||||
: room. ( -- )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,7 @@ call( -- )
 | 
			
		|||
    "system.private"
 | 
			
		||||
    "threads.private"
 | 
			
		||||
    "tools.dispatch.private"
 | 
			
		||||
    "tools.memory.private"
 | 
			
		||||
    "tools.profiler.private"
 | 
			
		||||
    "words"
 | 
			
		||||
    "words.private"
 | 
			
		||||
| 
						 | 
				
			
			@ -515,12 +516,12 @@ tuple
 | 
			
		|||
    { "float>bignum" "math.private" "primitive_float_to_bignum" (( x -- y )) }
 | 
			
		||||
    { "float>fixnum" "math.private" "primitive_float_to_fixnum" (( x -- y )) }
 | 
			
		||||
    { "all-instances" "memory" "primitive_all_instances" (( -- array )) }
 | 
			
		||||
    { "(code-blocks)" "memory.private" "primitive_code_blocks" (( -- array )) }
 | 
			
		||||
    { "code-room" "memory" "primitive_code_room" (( -- code-room )) }
 | 
			
		||||
    { "(code-blocks)" "tools.memory.private" "primitive_code_blocks" (( -- array )) }
 | 
			
		||||
    { "(code-room)" "tools.memory.private" "primitive_code_room" (( -- code-room )) }
 | 
			
		||||
    { "compact-gc" "memory" "primitive_compact_gc" (( -- )) }
 | 
			
		||||
    { "data-room" "memory" "primitive_data_room" (( -- data-room )) }
 | 
			
		||||
    { "disable-gc-events" "memory" "primitive_disable_gc_events" (( -- events )) }
 | 
			
		||||
    { "enable-gc-events" "memory" "primitive_enable_gc_events" (( -- )) }
 | 
			
		||||
    { "(data-room)" "tools.memory.private" "primitive_data_room" (( -- data-room )) }
 | 
			
		||||
    { "disable-gc-events" "tools.memory.private" "primitive_disable_gc_events" (( -- events )) }
 | 
			
		||||
    { "enable-gc-events" "tools.memory.private" "primitive_enable_gc_events" (( -- )) }
 | 
			
		||||
    { "gc" "memory" "primitive_full_gc" (( -- )) }
 | 
			
		||||
    { "minor-gc" "memory" "primitive_minor_gc" (( -- )) }
 | 
			
		||||
    { "size" "memory" "primitive_size" (( obj -- n )) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,14 +9,6 @@ HELP: instances
 | 
			
		|||
HELP: gc ( -- )
 | 
			
		||||
{ $description "Performs a full garbage collection." } ;
 | 
			
		||||
 | 
			
		||||
HELP: data-room ( -- data-room )
 | 
			
		||||
{ $values { "data-room" data-room } }
 | 
			
		||||
{ $description "Queries the VM for memory usage information." } ;
 | 
			
		||||
 | 
			
		||||
HELP: code-room ( -- code-room )
 | 
			
		||||
{ $values { "code-room" code-room } }
 | 
			
		||||
{ $description "Queries the VM for memory usage information." } ;
 | 
			
		||||
 | 
			
		||||
HELP: size ( obj -- n )
 | 
			
		||||
{ $values { "obj" "an object" } { "n" "a size in bytes" } }
 | 
			
		||||
{ $description "Outputs the size of the object in memory, in bytes. Tagged immediate objects such as fixnums and " { $link f } " will yield a size of 0." } ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,34 +1,56 @@
 | 
			
		|||
USING: generic kernel kernel.private math memory prettyprint io
 | 
			
		||||
sequences tools.test words namespaces layouts classes
 | 
			
		||||
classes.builtin arrays quotations io.launcher system ;
 | 
			
		||||
USING: accessors kernel kernel.private math memory prettyprint
 | 
			
		||||
io sequences tools.test words namespaces layouts classes
 | 
			
		||||
classes.builtin arrays quotations system ;
 | 
			
		||||
FROM: tools.memory => data-room code-room ;
 | 
			
		||||
IN: memory.tests
 | 
			
		||||
 | 
			
		||||
[ save-image-and-exit ] must-fail
 | 
			
		||||
 | 
			
		||||
! Tests for 'instances'
 | 
			
		||||
[ [ ] instances ] must-infer
 | 
			
		||||
2 [ [ [ 3 throw ] instances ] must-fail ] times
 | 
			
		||||
 | 
			
		||||
! Tests for 'become'
 | 
			
		||||
[ ] [ { } { } become ] unit-test
 | 
			
		||||
 | 
			
		||||
! LOL
 | 
			
		||||
[ ] [
 | 
			
		||||
    vm
 | 
			
		||||
    "-i=" image append
 | 
			
		||||
    "-generations=2"
 | 
			
		||||
    "-e=USING: memory io prettyprint system ; input-stream gc . 0 exit"
 | 
			
		||||
    4array try-process
 | 
			
		||||
] unit-test
 | 
			
		||||
! Bug found on Windows build box, having too many words in the
 | 
			
		||||
! image breaks 'become'
 | 
			
		||||
[ ] [ 100000 [ f <uninterned-word> ] replicate { } { } become drop ] unit-test
 | 
			
		||||
 | 
			
		||||
[ [ ] instances ] must-infer
 | 
			
		||||
 | 
			
		||||
! Code GC wasn't kicking in when needed
 | 
			
		||||
! Bug: code heap collection had to be done when data heap was
 | 
			
		||||
! full, not just when code heap was full. If the code heap
 | 
			
		||||
! contained dead code blocks referring to large data heap
 | 
			
		||||
! objects, those large objects would continue to live on even
 | 
			
		||||
! if the code blocks were not reachable, as long as the code
 | 
			
		||||
! heap did not fill up.
 | 
			
		||||
: leak-step ( -- ) 800000 f <array> 1quotation call( -- obj ) drop ;
 | 
			
		||||
 | 
			
		||||
: leak-loop ( -- ) 100 [ leak-step ] times ;
 | 
			
		||||
 | 
			
		||||
[ ] [ leak-loop ] unit-test
 | 
			
		||||
 | 
			
		||||
TUPLE: testing x y z ;
 | 
			
		||||
! Bug: allocation of large objects directly into tenured space
 | 
			
		||||
! can proceed past the high water mark.
 | 
			
		||||
!
 | 
			
		||||
! Suppose the nursery and aging spaces are mostly comprised of
 | 
			
		||||
! reachable objects. When doing a full GC, objects from young
 | 
			
		||||
! generations ere promoted *before* unreachable objects in
 | 
			
		||||
! tenured space are freed by the sweep phase. So if large object
 | 
			
		||||
! allocation filled up the heap past the high water mark, this
 | 
			
		||||
! promotion might trigger heap growth, even if most of those
 | 
			
		||||
! large objects are unreachable.
 | 
			
		||||
SYMBOL: foo
 | 
			
		||||
 | 
			
		||||
[ save-image-and-exit ] must-fail
 | 
			
		||||
[ ] [
 | 
			
		||||
    gc
 | 
			
		||||
 | 
			
		||||
! Erg's bug
 | 
			
		||||
2 [ [ [ 3 throw ] instances ] must-fail ] times
 | 
			
		||||
 | 
			
		||||
! Bug found on Windows build box, having too many words in the image breaks 'become'
 | 
			
		||||
[ ] [ 100000 [ f <uninterned-word> ] replicate { } { } become drop ] unit-test
 | 
			
		||||
    data-room tenured>> size>>
 | 
			
		||||
    
 | 
			
		||||
    10 [
 | 
			
		||||
        4 [ 120 1024 * f <array> ] replicate foo set-global
 | 
			
		||||
        100 [ 256 1024 * f <array> drop ] times
 | 
			
		||||
    ] times
 | 
			
		||||
    
 | 
			
		||||
    data-room tenured>> size>>
 | 
			
		||||
    assert=
 | 
			
		||||
] unit-test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,11 +2,13 @@ USING: tools.deploy.config ;
 | 
			
		|||
H{
 | 
			
		||||
    { deploy-name "Bunny" }
 | 
			
		||||
    { deploy-ui? t }
 | 
			
		||||
    { deploy-help? f }
 | 
			
		||||
    { deploy-c-types? f }
 | 
			
		||||
    { deploy-console? t }
 | 
			
		||||
    { deploy-unicode? f }
 | 
			
		||||
    { "stop-after-last-window?" t }
 | 
			
		||||
    { deploy-io 3 }
 | 
			
		||||
    { deploy-reflection 2 }
 | 
			
		||||
    { deploy-reflection 1 }
 | 
			
		||||
    { deploy-word-props? f }
 | 
			
		||||
    { deploy-math? t }
 | 
			
		||||
    { deploy-threads? t }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
! (c)2009 Joe Groff bsd license
 | 
			
		||||
USING: accessors alien.c-types classes.struct game.loop
 | 
			
		||||
game.loop.private kernel sequences specialized-vectors
 | 
			
		||||
tools.time.struct ;
 | 
			
		||||
IN: game.loop.benchmark
 | 
			
		||||
 | 
			
		||||
STRUCT: game-loop-benchmark
 | 
			
		||||
    { benchmark-data-pair benchmark-data-pair }
 | 
			
		||||
    { tick# ulonglong }
 | 
			
		||||
    { frame# ulonglong } ;
 | 
			
		||||
 | 
			
		||||
SPECIALIZED-VECTOR: game-loop-benchmark
 | 
			
		||||
 | 
			
		||||
: <game-loop-benchmark> ( benchmark-data-pair tick frame -- obj )
 | 
			
		||||
    \ game-loop-benchmark <struct>
 | 
			
		||||
        swap >>frame#
 | 
			
		||||
        swap >>tick#
 | 
			
		||||
        swap >>benchmark-data-pair ; inline
 | 
			
		||||
 | 
			
		||||
: ensure-benchmark-data ( loop -- vector )
 | 
			
		||||
    dup benchmark-data>> [
 | 
			
		||||
        game-loop-benchmark-vector{ } clone
 | 
			
		||||
        >>benchmark-data
 | 
			
		||||
    ] unless
 | 
			
		||||
    benchmark-data>> ; inline
 | 
			
		||||
 | 
			
		||||
M: game-loop record-benchmarking ( loop quot: ( loop -- benchmark-data-pair ) -- )
 | 
			
		||||
    [
 | 
			
		||||
        [ [ call( loop -- ) ] with-benchmarking ]
 | 
			
		||||
        [ drop tick#>> ]
 | 
			
		||||
        [ drop frame#>> ]
 | 
			
		||||
        2tri
 | 
			
		||||
        <game-loop-benchmark>
 | 
			
		||||
    ]
 | 
			
		||||
    [ drop ensure-benchmark-data ]
 | 
			
		||||
    2bi push ;
 | 
			
		||||
                                
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,8 @@
 | 
			
		|||
! (c)2009 Joe Groff bsd license
 | 
			
		||||
USING: accessors timers alien.c-types calendar classes.struct
 | 
			
		||||
continuations destructors fry kernel math math.order memory
 | 
			
		||||
namespaces sequences specialized-vectors system
 | 
			
		||||
ui ui.gadgets.worlds vm vocabs.loader arrays
 | 
			
		||||
tools.time.struct locals ;
 | 
			
		||||
namespaces sequences system ui ui.gadgets.worlds vm
 | 
			
		||||
vocabs.loader arrays locals ;
 | 
			
		||||
IN: game.loop
 | 
			
		||||
 | 
			
		||||
TUPLE: game-loop
 | 
			
		||||
| 
						 | 
				
			
			@ -17,19 +16,6 @@ TUPLE: game-loop
 | 
			
		|||
    draw-timer
 | 
			
		||||
    benchmark-data ;
 | 
			
		||||
 | 
			
		||||
STRUCT: game-loop-benchmark
 | 
			
		||||
    { benchmark-data-pair benchmark-data-pair }
 | 
			
		||||
    { tick# ulonglong }
 | 
			
		||||
    { frame# ulonglong } ;
 | 
			
		||||
 | 
			
		||||
SPECIALIZED-VECTOR: game-loop-benchmark
 | 
			
		||||
 | 
			
		||||
: <game-loop-benchmark> ( benchmark-data-pair tick frame -- obj )
 | 
			
		||||
    \ game-loop-benchmark <struct>
 | 
			
		||||
        swap >>frame#
 | 
			
		||||
        swap >>tick#
 | 
			
		||||
        swap >>benchmark-data-pair ; inline
 | 
			
		||||
 | 
			
		||||
GENERIC: tick* ( delegate -- )
 | 
			
		||||
GENERIC: draw* ( tick-slice delegate -- )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,26 +34,24 @@ TUPLE: game-loop-error game-loop error ;
 | 
			
		|||
 | 
			
		||||
<PRIVATE
 | 
			
		||||
 | 
			
		||||
: record-benchmarking ( benchark-data-pair loop -- )
 | 
			
		||||
    [ tick#>> ]
 | 
			
		||||
    [ frame#>> <game-loop-benchmark> ]
 | 
			
		||||
    [ benchmark-data>> ] tri push ;
 | 
			
		||||
 | 
			
		||||
: last-tick-percent-offset ( loop -- float )
 | 
			
		||||
    [ draw-timer>> iteration-start-nanos>> nano-count swap - ]
 | 
			
		||||
    [ tick-interval-nanos>> ] bi /f 1.0 min ;
 | 
			
		||||
 | 
			
		||||
GENERIC# record-benchmarking 1 ( loop quot -- )
 | 
			
		||||
 | 
			
		||||
M: object record-benchmarking
 | 
			
		||||
    call( loop -- ) ;
 | 
			
		||||
 | 
			
		||||
: redraw ( loop -- )
 | 
			
		||||
    [ 1 + ] change-frame#
 | 
			
		||||
    [
 | 
			
		||||
        [ last-tick-percent-offset ] [ draw-delegate>> ] bi
 | 
			
		||||
        [ draw* ] with-benchmarking
 | 
			
		||||
    ] keep record-benchmarking ;
 | 
			
		||||
        draw*
 | 
			
		||||
    ] record-benchmarking ;
 | 
			
		||||
 | 
			
		||||
: tick ( loop -- )
 | 
			
		||||
    [
 | 
			
		||||
        [ tick-delegate>> tick* ] with-benchmarking
 | 
			
		||||
    ] keep record-benchmarking ;
 | 
			
		||||
    [ tick-delegate>> tick* ] record-benchmarking ;
 | 
			
		||||
 | 
			
		||||
: increment-tick ( loop -- )
 | 
			
		||||
    [ 1 + ] change-tick#
 | 
			
		||||
| 
						 | 
				
			
			@ -105,9 +89,7 @@ PRIVATE>
 | 
			
		|||
    [ tick-timer>> ] [ draw-timer>> ] bi [ stop-timer ] bi@ ;
 | 
			
		||||
 | 
			
		||||
: <game-loop*> ( tick-interval-nanos tick-delegate draw-delegate -- loop )
 | 
			
		||||
    f 0 0 f f
 | 
			
		||||
    game-loop-benchmark-vector{ } clone
 | 
			
		||||
    game-loop boa ;
 | 
			
		||||
    f 0 0 f f f game-loop boa ;
 | 
			
		||||
 | 
			
		||||
: <game-loop> ( tick-interval-nanos delegate -- loop )
 | 
			
		||||
    dup <game-loop*> ; inline
 | 
			
		||||
| 
						 | 
				
			
			@ -116,3 +98,4 @@ M: game-loop dispose
 | 
			
		|||
    stop-loop ;
 | 
			
		||||
 | 
			
		||||
{ "game.loop" "prettyprint" } "game.loop.prettyprint" require-when
 | 
			
		||||
{ "game.loop" "tools.memory" } "game.loop.benchmark" require-when
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
unix
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
! Copyright (C) 2010 Doug Coleman.
 | 
			
		||||
! See http://factorcode.org/license.txt for BSD license.
 | 
			
		||||
USING: accessors alien.c-types classes.struct kernel memory
 | 
			
		||||
system vm ;
 | 
			
		||||
tools.memory system vm ;
 | 
			
		||||
IN: tools.time.struct
 | 
			
		||||
 | 
			
		||||
STRUCT: benchmark-data
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,8 @@ void factor_vm::collect_aging()
 | 
			
		|||
	/* Promote objects referenced from tenured space to tenured space, copy
 | 
			
		||||
	everything else to the aging semi-space, and reset the nursery pointer. */
 | 
			
		||||
	{
 | 
			
		||||
		/* Change the op so that if we fail here, we proceed to a full
 | 
			
		||||
		tenured collection. We are collecting to tenured space, and
 | 
			
		||||
		cards were unmarked, so we can't proceed with a to_tenured
 | 
			
		||||
		collection. */
 | 
			
		||||
		/* Change the op so that if we fail here, an assertion will be
 | 
			
		||||
		raised. */
 | 
			
		||||
		current_gc->op = collect_to_tenured_op;
 | 
			
		||||
 | 
			
		||||
		to_tenured_collector collector(this);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -330,14 +330,22 @@ void factor_vm::collect_compact(bool trace_contexts_p)
 | 
			
		|||
{
 | 
			
		||||
	collect_mark_impl(trace_contexts_p);
 | 
			
		||||
	collect_compact_impl(trace_contexts_p);
 | 
			
		||||
	
 | 
			
		||||
	if(data->high_fragmentation_p())
 | 
			
		||||
	{
 | 
			
		||||
		/* Compaction did not free up enough memory. Grow the heap. */
 | 
			
		||||
		set_current_gc_op(collect_growing_heap_op);
 | 
			
		||||
		collect_growing_heap(0,trace_contexts_p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	code->flush_icache();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::collect_growing_heap(cell requested_bytes, bool trace_contexts_p)
 | 
			
		||||
void factor_vm::collect_growing_heap(cell requested_size, bool trace_contexts_p)
 | 
			
		||||
{
 | 
			
		||||
	/* Grow the data heap and copy all live objects to the new heap. */
 | 
			
		||||
	data_heap *old = data;
 | 
			
		||||
	set_data_heap(data->grow(requested_bytes));
 | 
			
		||||
	set_data_heap(data->grow(requested_size));
 | 
			
		||||
	collect_mark_impl(trace_contexts_p);
 | 
			
		||||
	collect_compact_code_impl(trace_contexts_p);
 | 
			
		||||
	code->flush_icache();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,12 +100,12 @@ void data_heap::reset_generation(tenured_space *gen)
 | 
			
		|||
 | 
			
		||||
bool data_heap::high_fragmentation_p()
 | 
			
		||||
{
 | 
			
		||||
	return (tenured->largest_free_block() <= nursery->size + aging->size);
 | 
			
		||||
	return (tenured->largest_free_block() <= high_water_mark());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool data_heap::low_memory_p()
 | 
			
		||||
{
 | 
			
		||||
	return (tenured->free_space() <= nursery->size + aging->size);
 | 
			
		||||
	return (tenured->free_space() <= high_water_mark());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void data_heap::mark_all_cards()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,9 @@ struct data_heap {
 | 
			
		|||
	bool high_fragmentation_p();
 | 
			
		||||
	bool low_memory_p();
 | 
			
		||||
	void mark_all_cards();
 | 
			
		||||
	cell high_water_mark() {
 | 
			
		||||
		return nursery->size + aging->size;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct data_heap_room {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,11 +112,14 @@ void factor_vm::collect_full(bool trace_contexts_p)
 | 
			
		|||
 | 
			
		||||
	if(data->low_memory_p())
 | 
			
		||||
	{
 | 
			
		||||
		/* Full GC did not free up enough memory. Grow the heap. */
 | 
			
		||||
		set_current_gc_op(collect_growing_heap_op);
 | 
			
		||||
		collect_growing_heap(0,trace_contexts_p);
 | 
			
		||||
	}
 | 
			
		||||
	else if(data->high_fragmentation_p())
 | 
			
		||||
	{
 | 
			
		||||
		/* Enough free memory, but it is not contiguous. Perform a
 | 
			
		||||
		compaction. */
 | 
			
		||||
		set_current_gc_op(collect_compact_op);
 | 
			
		||||
		collect_compact_impl(trace_contexts_p);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										44
									
								
								vm/gc.cpp
								
								
								
								
							
							
						
						
									
										44
									
								
								vm/gc.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -116,19 +116,19 @@ void factor_vm::start_gc_again()
 | 
			
		|||
	switch(current_gc->op)
 | 
			
		||||
	{
 | 
			
		||||
	case collect_nursery_op:
 | 
			
		||||
		/* Nursery collection can fail if aging does not have enough
 | 
			
		||||
		free space to fit all live objects from nursery. */
 | 
			
		||||
		current_gc->op = collect_aging_op;
 | 
			
		||||
		break;
 | 
			
		||||
	case collect_aging_op:
 | 
			
		||||
		/* Aging collection can fail if the aging semispace cannot fit
 | 
			
		||||
		all the live objects from the other aging semispace and the
 | 
			
		||||
		nursery. */
 | 
			
		||||
		current_gc->op = collect_to_tenured_op;
 | 
			
		||||
		break;
 | 
			
		||||
	case collect_to_tenured_op:
 | 
			
		||||
		current_gc->op = collect_full_op;
 | 
			
		||||
		break;
 | 
			
		||||
	case collect_full_op:
 | 
			
		||||
	case collect_compact_op:
 | 
			
		||||
		current_gc->op = collect_growing_heap_op;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* Nothing else should fail mid-collection due to insufficient
 | 
			
		||||
		space in the target generation. */
 | 
			
		||||
		critical_error("Bad GC op",current_gc->op);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -143,15 +143,21 @@ void factor_vm::set_current_gc_op(gc_op op)
 | 
			
		|||
	if(gc_events) current_gc->event->op = op;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 | 
			
		||||
void factor_vm::gc(gc_op op, cell requested_size, bool trace_contexts_p)
 | 
			
		||||
{
 | 
			
		||||
	assert(!gc_off);
 | 
			
		||||
	assert(!current_gc);
 | 
			
		||||
 | 
			
		||||
	/* Important invariant: tenured space must have enough contiguous free
 | 
			
		||||
	space to fit the entire contents of the aging space and nursery. This is
 | 
			
		||||
	because when doing a full collection, objects from younger generations
 | 
			
		||||
	are promoted before any unreachable tenured objects are freed. */
 | 
			
		||||
	assert(!data->high_fragmentation_p());
 | 
			
		||||
 | 
			
		||||
	current_gc = new gc_state(op,this);
 | 
			
		||||
 | 
			
		||||
	/* Keep trying to GC higher and higher generations until we don't run out
 | 
			
		||||
	of space */
 | 
			
		||||
	/* Keep trying to GC higher and higher generations until we don't run
 | 
			
		||||
	out of space in the target generation. */
 | 
			
		||||
	for(;;)
 | 
			
		||||
	{
 | 
			
		||||
		try
 | 
			
		||||
| 
						 | 
				
			
			@ -164,17 +170,23 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 | 
			
		|||
				collect_nursery();
 | 
			
		||||
				break;
 | 
			
		||||
			case collect_aging_op:
 | 
			
		||||
				/* We end up here if the above fails. */
 | 
			
		||||
				collect_aging();
 | 
			
		||||
				if(data->high_fragmentation_p())
 | 
			
		||||
				{
 | 
			
		||||
					/* Change GC op so that if we fail again,
 | 
			
		||||
					we crash. */
 | 
			
		||||
					set_current_gc_op(collect_full_op);
 | 
			
		||||
					collect_full(trace_contexts_p);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			case collect_to_tenured_op:
 | 
			
		||||
				/* We end up here if the above fails. */
 | 
			
		||||
				collect_to_tenured();
 | 
			
		||||
				if(data->high_fragmentation_p())
 | 
			
		||||
				{
 | 
			
		||||
					/* Change GC op so that if we fail again,
 | 
			
		||||
					we crash. */
 | 
			
		||||
					set_current_gc_op(collect_full_op);
 | 
			
		||||
					collect_full(trace_contexts_p);
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +198,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 | 
			
		|||
				collect_compact(trace_contexts_p);
 | 
			
		||||
				break;
 | 
			
		||||
			case collect_growing_heap_op:
 | 
			
		||||
				collect_growing_heap(requested_bytes,trace_contexts_p);
 | 
			
		||||
				collect_growing_heap(requested_size,trace_contexts_p);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				critical_error("Bad GC op",current_gc->op);
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +209,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 | 
			
		|||
		}
 | 
			
		||||
		catch(const must_start_gc_again &)
 | 
			
		||||
		{
 | 
			
		||||
			/* We come back here if a generation is full */
 | 
			
		||||
			/* We come back here if the target generation is full. */
 | 
			
		||||
			start_gc_again();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +219,9 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 | 
			
		|||
 | 
			
		||||
	delete current_gc;
 | 
			
		||||
	current_gc = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Check the invariant again, just in case. */
 | 
			
		||||
	assert(!data->high_fragmentation_p());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* primitive_minor_gc() is invoked by inline GC checks, and it needs to fill in
 | 
			
		||||
| 
						 | 
				
			
			@ -283,12 +298,13 @@ void factor_vm::primitive_compact_gc()
 | 
			
		|||
object *factor_vm::allot_large_object(cell type, cell size)
 | 
			
		||||
{
 | 
			
		||||
	/* If tenured space does not have enough room, collect and compact */
 | 
			
		||||
	if(!data->tenured->can_allot_p(size))
 | 
			
		||||
	cell requested_size = size + data->high_water_mark();
 | 
			
		||||
	if(!data->tenured->can_allot_p(requested_size))
 | 
			
		||||
	{
 | 
			
		||||
		primitive_compact_gc();
 | 
			
		||||
 | 
			
		||||
		/* If it still won't fit, grow the heap */
 | 
			
		||||
		if(!data->tenured->can_allot_p(size))
 | 
			
		||||
		if(!data->tenured->can_allot_p(requested_size))
 | 
			
		||||
		{
 | 
			
		||||
			gc(collect_growing_heap_op,
 | 
			
		||||
				size, /* requested size */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -314,8 +314,8 @@ struct factor_vm
 | 
			
		|||
	void collect_compact_impl(bool trace_contexts_p);
 | 
			
		||||
	void collect_compact_code_impl(bool trace_contexts_p);
 | 
			
		||||
	void collect_compact(bool trace_contexts_p);
 | 
			
		||||
	void collect_growing_heap(cell requested_bytes, bool trace_contexts_p);
 | 
			
		||||
	void gc(gc_op op, cell requested_bytes, bool trace_contexts_p);
 | 
			
		||||
	void collect_growing_heap(cell requested_size, bool trace_contexts_p);
 | 
			
		||||
	void gc(gc_op op, cell requested_size, bool trace_contexts_p);
 | 
			
		||||
	void scrub_context(context *ctx);
 | 
			
		||||
	void scrub_contexts();
 | 
			
		||||
	void primitive_minor_gc();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue