M: ##call compute-stack-frame*
word>> sub-primitive>> [ frame-required? on ] unless ;
-M: _gc compute-stack-frame*
+M: ##gc compute-stack-frame*
frame-required? on
stack-frame new swap tagged-values>> length cells >>gc-root-size
request-stack-frame ;
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel sequences assocs fry
-cpu.architecture
+cpu.architecture layouts
compiler.cfg.rpo
compiler.cfg.registers
compiler.cfg.instructions
: blocks-with-gc ( cfg -- bbs )
post-order [ insert-gc-check? ] filter ;
+GENERIC: allocation-size* ( insn -- n )
+
+M: ##allot allocation-size* size>> ;
+
+M: ##box-alien allocation-size* drop 4 cells ;
+
+M: ##box-displaced-alien allocation-size* drop 4 cells ;
+
+: allocation-size ( bb -- n )
+ instructions>> [ ##allocation? ] filter [ allocation-size* ] sigma ;
+
: insert-gc-check ( bb -- )
- dup '[
+ dup dup '[
int-rep next-vreg-rep
int-rep next-vreg-rep
- f f _ uninitialized-locs \ ##gc new-insn
+ _ allocation-size
+ f
+ f
+ _ uninitialized-locs
+ \ ##gc new-insn
prefix
] change-instructions drop ;
INSN: ##gc
temp: temp1/int-rep temp2/int-rep
-literal: data-values tagged-values uninitialized-locs ;
+literal: size data-values tagged-values uninitialized-locs ;
INSN: ##save-context
temp: temp1/int-rep temp2/int-rep
TUPLE: spill-slot { n integer } ;
C: <spill-slot> spill-slot
-INSN: _gc
-temp: temp1 temp2
-literal: data-values tagged-values uninitialized-locs ;
-
! These instructions operate on machine registers and not
! virtual registers
INSN: _spill
] [ node emit-primitive ] if
] ;
+: expand-(byte-array)? ( obj -- ? )
+ dup integer? [ 0 1024 between? ] [ drop f ] if ;
+
: expand-<byte-array>? ( obj -- ? )
dup integer? [ 0 32 between? ] [ drop f ] if ;
[ byte-array store-length ] [ ds-push ] [ ] tri ;
: emit-(byte-array) ( node -- )
- dup node-input-infos first literal>> dup expand-<byte-array>?
+ dup node-input-infos first literal>> dup expand-(byte-array)?
[ nip emit-allot-byte-array drop ] [ drop emit-primitive ] if ;
:: emit-<byte-array> ( node -- )
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel math assocs namespaces sequences heaps
fry make combinators sets locals arrays
-cpu.architecture
+cpu.architecture layouts
compiler.cfg
compiler.cfg.def-use
compiler.cfg.liveness
M: vreg-insn assign-registers-in-insn
[ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ;
-! TODO: needs tagged-rep
-
: trace-on-gc ( assoc -- assoc' )
! When a GC occurs, virtual registers which contain tagged data
! are traced by the GC. Outputs a sequence physical registers.
] assoc-each
] { } make ;
+: gc-root-offsets ( registers -- alist )
+ ! Outputs a sequence of { offset register/spill-slot } pairs
+ [ length iota [ cell * ] map ] keep zip ;
+
M: ##gc assign-registers-in-insn
! Since ##gc is always the first instruction in a block, the set of
! values live at the ##gc is just live-in.
dup call-next-method
basic-block get register-live-ins get at
- [ trace-on-gc >>tagged-values ] [ spill-on-gc >>data-values ] bi
+ [ trace-on-gc gc-root-offsets >>tagged-values ] [ spill-on-gc >>data-values ] bi
drop ;
M: insn assign-registers-in-insn drop ;
[ successors>> [ block-number _dispatch-label ] each ]
bi* ;
-: gc-root-offsets ( registers -- alist )
- ! Outputs a sequence of { offset register/spill-slot } pairs
- [ length iota [ cell * ] map ] keep zip ;
-
-M: ##gc linearize-insn
- nip
- {
- [ temp1>> ]
- [ temp2>> ]
- [ data-values>> ]
- [ tagged-values>> gc-root-offsets ]
- [ uninitialized-locs>> ]
- } cleave
- _gc ;
-
: linearize-basic-blocks ( cfg -- insns )
[
[
! Consider the following sequence of instructions:
! ##inc-d 2
-! _gc
+! ##gc
! ##replace ... D 0
! ##replace ... D 1
! The GC check runs before stack locations 0 and 1 have been initialized,
: load-data-regs ( data-regs -- ) [ first3 %reload ] each ;
-M: _gc generate-insn
+M: ##gc generate-insn
"no-gc" define-label
{
- [ [ "no-gc" get ] dip [ temp1>> ] [ temp2>> ] bi %check-nursery ]
+ [ [ "no-gc" get ] dip [ size>> ] [ temp1>> ] [ temp2>> ] tri %check-nursery ]
[ [ uninitialized-locs>> ] [ temp1>> ] bi wipe-locs ]
[ data-values>> save-data-regs ]
[ [ tagged-values>> ] [ temp1>> ] bi save-gc-roots ]
HOOK: %write-barrier cpu ( src card# table -- )
! GC checks
-HOOK: %check-nursery cpu ( label temp1 temp2 -- )
+HOOK: %check-nursery cpu ( label size temp1 temp2 -- )
HOOK: %save-gc-root cpu ( gc-root register -- )
HOOK: %load-gc-root cpu ( gc-root register -- )
HOOK: %call-gc cpu ( gc-root-count temp1 -- )
src card# deck-bits SRWI
table scratch-reg card# STBX ;
-M:: ppc %check-nursery ( label temp1 temp2 -- )
+M:: ppc %check-nursery ( label size temp1 temp2 -- )
temp2 load-zone-ptr
temp1 temp2 cell LWZ
temp2 temp2 3 cells LWZ
- ! add ALLOT_BUFFER_ZONE to here
- temp1 temp1 1024 ADDI
+ temp1 temp1 size ADDI
! is here >= end?
temp1 0 temp2 CMP
label BLE ;
table table [] MOV
table card# [+] card-mark <byte> MOV ;
-M:: x86 %check-nursery ( label temp1 temp2 -- )
+M:: x86 %check-nursery ( label size temp1 temp2 -- )
temp1 load-zone-ptr
temp2 temp1 cell [+] MOV
- temp2 1024 ADD
+ temp2 size ADD
temp1 temp1 3 cells [+] MOV
temp2 temp1 CMP
label JLE ;
object *obj;
- if(nursery.size - allot_buffer_zone > size)
+ if(nursery.size > size)
{
/* If there is insufficient room, collect the nursery */
- if(nursery.here + allot_buffer_zone + size > nursery.end)
+ if(nursery.here + size > nursery.end)
garbage_collection(data->nursery(),false,true,0);
cell h = nursery.here;
}
};
-/* We leave this many bytes free at the top of the nursery so that inline
-allocation (which does not call GC because of possible roots in volatile
-registers) does not run out of memory */
-static const cell allot_buffer_zone = 1024;
-
VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *myvm);
}