Merge branch 'master' of git://factorcode.org/git/factor
commit
23288da694
1
Makefile
1
Makefile
|
@ -60,6 +60,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
|
|||
vm/strings.o \
|
||||
vm/tuples.o \
|
||||
vm/utilities.o \
|
||||
vm/vm.o \
|
||||
vm/words.o \
|
||||
vm/write_barrier.o
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ M: stack-frame-insn compute-stack-frame*
|
|||
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 ;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! 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
|
||||
|
@ -17,11 +17,26 @@ IN: compiler.cfg.gc-checks
|
|||
: 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 ;
|
||||
|
||||
|
|
|
@ -672,7 +672,7 @@ use: src1/int-rep src2/int-rep ;
|
|||
|
||||
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
|
||||
|
@ -740,10 +740,6 @@ use: src1/int-rep src2/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
|
||||
|
|
|
@ -55,6 +55,9 @@ IN: compiler.cfg.intrinsics.allot
|
|||
] [ 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 ;
|
||||
|
||||
|
@ -69,7 +72,7 @@ IN: compiler.cfg.intrinsics.allot
|
|||
[ 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 -- )
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! 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
|
||||
|
@ -117,8 +117,6 @@ 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 ;
|
||||
|
||||
! 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.
|
||||
|
@ -141,12 +139,16 @@ M: vreg-insn assign-registers-in-insn
|
|||
] 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 ;
|
||||
|
|
|
@ -97,21 +97,6 @@ M: ##dispatch linearize-insn
|
|||
[ 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 )
|
||||
[
|
||||
[
|
||||
|
|
|
@ -9,7 +9,7 @@ IN: compiler.cfg.stacks.uninitialized
|
|||
|
||||
! 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,
|
||||
|
|
|
@ -271,10 +271,10 @@ M: object load-gc-root drop %load-gc-root ;
|
|||
|
||||
: 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 ]
|
||||
|
|
|
@ -317,7 +317,7 @@ HOOK: %allot cpu ( dst size class temp -- )
|
|||
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 -- )
|
||||
|
|
|
@ -446,12 +446,11 @@ M:: ppc %write-barrier ( src card# table -- )
|
|||
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 ;
|
||||
|
|
|
@ -410,10 +410,10 @@ M:: x86 %write-barrier ( src card# table -- )
|
|||
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 ;
|
||||
|
|
|
@ -119,8 +119,10 @@ CONSTANT: zero-matrix4
|
|||
TYPED:: m4^n ( m: matrix4 n: fixnum -- m^n: matrix4 )
|
||||
identity-matrix4 n [ m m4. ] times ;
|
||||
|
||||
: vmerge-diagonal* ( x y -- h t )
|
||||
[ vmerge-head ] [ swap vmerge-tail ] 2bi ; inline
|
||||
: vmerge-diagonal ( x -- h t )
|
||||
0.0 float-4-with [ vmerge-head ] [ swap vmerge-tail ] 2bi ; inline
|
||||
0.0 float-4-with vmerge-diagonal* ; inline
|
||||
|
||||
TYPED: diagonal-matrix4 ( diagonal: float-4 -- matrix: matrix4 )
|
||||
[ vmerge-diagonal [ vmerge-diagonal ] bi@ ] make-matrix4 ;
|
||||
|
@ -133,23 +135,22 @@ TYPED: transpose-matrix4 ( matrix: matrix4 -- matrix: matrix4 )
|
|||
|
||||
: scale-matrix4 ( factors -- matrix )
|
||||
[ float-4{ t t t f } ] dip float-4{ 0.0 0.0 0.0 1.0 } v?
|
||||
diagonal-matrix4 ;
|
||||
diagonal-matrix4 ; inline
|
||||
|
||||
: ortho-matrix4 ( factors -- matrix )
|
||||
float-4{ 1.0 1.0 1.0 1.0 } swap v/ scale-matrix4 ; inline
|
||||
|
||||
TYPED:: translation-matrix4 ( offset: float-4 -- matrix: matrix4 )
|
||||
matrix4 (struct) :> c
|
||||
[
|
||||
float-4{ 1.0 1.0 1.0 1.0 } :> diagonal
|
||||
|
||||
float-4{ 0.0 0.0 0.0 1.0 } :> c4
|
||||
float-4{ t t t f } offset c4 v? :> offset'
|
||||
offset 0 float-4-with vmerge
|
||||
[ 0 float-4-with swap vmerge ] bi@ drop :> z :> y :> x
|
||||
|
||||
offset' { 3 3 3 0 } vshuffle float-4{ t f f t } vbitand
|
||||
offset' { 3 3 3 1 } vshuffle float-4{ f t f t } vbitand
|
||||
offset' { 3 3 3 2 } vshuffle float-4{ f f t t } vbitand
|
||||
c4
|
||||
|
||||
c set-rows ;
|
||||
diagonal y vmerge-diagonal*
|
||||
[ x vmerge-diagonal* ]
|
||||
[ z vmerge-diagonal* ] bi*
|
||||
] make-matrix4 ;
|
||||
|
||||
TYPED:: rotation-matrix4 ( axis: float-4 theta: float -- matrix: matrix4 )
|
||||
! x*x + c*(1.0 - x*x) x*y*(1.0 - c) - s*z x*z*(1.0 - c) + s*y 0
|
||||
|
@ -188,16 +189,13 @@ TYPED:: rotation-matrix4 ( axis: float-4 theta: float -- matrix: matrix4 )
|
|||
diagonal-m triangle-m m4+ ;
|
||||
|
||||
TYPED:: frustum-matrix4 ( xy: float-4 near: float far: float -- matrix: matrix4 )
|
||||
matrix4 (struct) :> c
|
||||
[
|
||||
near near near far + 2 near far * * float-4-boa ! num
|
||||
float-4{ t t f f } xy near far - float-4-with v? ! denom
|
||||
v/ :> fov
|
||||
|
||||
near near near far + 2 near far * * float-4-boa :> num
|
||||
float-4{ t t f f } xy near far - float-4-with v? :> denom
|
||||
num denom v/ :> fov
|
||||
|
||||
fov { 0 0 0 0 } vshuffle float-4{ t f f f } vbitand
|
||||
fov { 1 1 1 1 } vshuffle float-4{ f t f f } vbitand
|
||||
fov { 2 2 2 3 } vshuffle float-4{ f f t t } vbitand
|
||||
fov 0.0 float-4-with vmerge-head vmerge-diagonal
|
||||
fov float-4{ f f t t } vand
|
||||
float-4{ 0.0 0.0 -1.0 0.0 }
|
||||
|
||||
c set-rows ;
|
||||
] make-matrix4 ;
|
||||
|
||||
|
|
|
@ -12,18 +12,16 @@ gc_state::gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_ge
|
|||
data(data_),
|
||||
growing_data_heap(growing_data_heap_),
|
||||
collecting_gen(collecting_gen_),
|
||||
collecting_aging_again(false),
|
||||
start_time(current_micros()) { }
|
||||
|
||||
gc_state::~gc_state() { }
|
||||
|
||||
/* If a generation fills up, throw this error. It is caught in garbage_collection() */
|
||||
struct generation_full_condition { };
|
||||
|
||||
/* Given a pointer to oldspace, copy it to newspace */
|
||||
object *factor_vm::copy_untagged_object_impl(object *pointer, cell size)
|
||||
{
|
||||
if(current_gc->newspace->here + size >= current_gc->newspace->end)
|
||||
throw generation_full_condition();
|
||||
longjmp(current_gc->gc_unwind,1);
|
||||
|
||||
object *newpointer = allot_zone(current_gc->newspace,size);
|
||||
|
||||
|
@ -502,7 +500,6 @@ void factor_vm::begin_gc(cell requested_bytes)
|
|||
|
||||
void factor_vm::end_gc()
|
||||
{
|
||||
|
||||
gc_stats *s = &stats[current_gc->collecting_gen];
|
||||
|
||||
cell gc_elapsed = (current_micros() - current_gc->start_time);
|
||||
|
@ -545,10 +542,34 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
|
|||
|
||||
/* Keep trying to GC higher and higher generations until we don't run out
|
||||
of space */
|
||||
for(;;)
|
||||
if(setjmp(current_gc->gc_unwind))
|
||||
{
|
||||
try
|
||||
/* We come back here if a generation is full */
|
||||
|
||||
/* We have no older generations we can try collecting, so we
|
||||
resort to growing the data heap */
|
||||
if(current_gc->collecting_tenured_p())
|
||||
{
|
||||
current_gc->growing_data_heap = true;
|
||||
|
||||
/* see the comment in unmark_marked() */
|
||||
code->unmark_marked();
|
||||
}
|
||||
/* we try collecting aging space twice before going on to
|
||||
collect tenured */
|
||||
else if(data->have_aging_p()
|
||||
&& current_gc->collecting_gen == data->aging()
|
||||
&& !current_gc->collecting_aging_again)
|
||||
{
|
||||
current_gc->collecting_aging_again = true;
|
||||
}
|
||||
/* Collect the next oldest generation */
|
||||
else
|
||||
{
|
||||
current_gc->collecting_gen++;
|
||||
}
|
||||
}
|
||||
|
||||
begin_gc(requested_bytes);
|
||||
|
||||
/* Initialize chase pointer */
|
||||
|
@ -585,37 +606,6 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
|
|||
update_dirty_code_blocks();
|
||||
|
||||
/* GC completed without any generations filling up; finish up */
|
||||
break;
|
||||
}
|
||||
catch(const generation_full_condition &c)
|
||||
{
|
||||
/* We come back here if a generation is full */
|
||||
|
||||
/* We have no older generations we can try collecting, so we
|
||||
resort to growing the data heap */
|
||||
if(current_gc->collecting_tenured_p())
|
||||
{
|
||||
current_gc->growing_data_heap = true;
|
||||
|
||||
/* see the comment in unmark_marked() */
|
||||
code->unmark_marked();
|
||||
}
|
||||
/* we try collecting aging space twice before going on to
|
||||
collect tenured */
|
||||
else if(data->have_aging_p()
|
||||
&& current_gc->collecting_gen == data->aging()
|
||||
&& !current_gc->collecting_aging_again)
|
||||
{
|
||||
current_gc->collecting_aging_again = true;
|
||||
}
|
||||
/* Collect the next oldest generation */
|
||||
else
|
||||
{
|
||||
current_gc->collecting_gen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end_gc();
|
||||
|
||||
delete current_gc;
|
||||
|
@ -748,10 +738,10 @@ object *factor_vm::allot_object(header header, cell size)
|
|||
|
||||
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;
|
||||
|
|
|
@ -34,6 +34,8 @@ struct gc_state {
|
|||
/* GC start time, for benchmarking */
|
||||
u64 start_time;
|
||||
|
||||
jmp_buf gc_unwind;
|
||||
|
||||
explicit gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_);
|
||||
~gc_state();
|
||||
|
||||
|
@ -56,11 +58,6 @@ struct gc_state {
|
|||
}
|
||||
};
|
||||
|
||||
/* 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);
|
||||
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ struct startargs {
|
|||
|
||||
factor_vm *new_factor_vm()
|
||||
{
|
||||
factor_vm *newvm = new factor_vm;
|
||||
factor_vm *newvm = new factor_vm();
|
||||
register_vm_with_thread(newvm);
|
||||
thread_vms[thread_id()] = newvm;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace factor
|
|||
template<typename Array> cell array_capacity(Array *array)
|
||||
{
|
||||
#ifdef FACTOR_DEBUG
|
||||
assert(array->h.hi_tag() == T::type_number);
|
||||
assert(array->h.hi_tag() == Array::type_number);
|
||||
#endif
|
||||
return array->capacity >> TAG_BITS;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ LONG factor_vm::exception_handler(PEXCEPTION_POINTERS pe)
|
|||
else
|
||||
signal_callstack_top = NULL;
|
||||
|
||||
switch (e->ExceptionCode) {
|
||||
switch (e->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
signal_fault_addr = e->ExceptionInformation[1];
|
||||
c->EIP = (cell)factor::memory_signal_handler_impl;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#include "master.hpp"
|
||||
|
||||
namespace factor
|
||||
{
|
||||
|
||||
factor_vm::factor_vm() { }
|
||||
|
||||
}
|
|
@ -535,7 +535,6 @@ struct factor_vm
|
|||
//code_heap
|
||||
heap *code;
|
||||
unordered_map<heap_block *, char *> forwarding;
|
||||
typedef void (factor_vm::*code_heap_iterator)(code_block *compiled);
|
||||
|
||||
void init_code_heap(cell size);
|
||||
bool in_code_heap_p(cell ptr);
|
||||
|
@ -743,16 +742,7 @@ struct factor_vm
|
|||
void call_fault_handler(exception_type_t exception, exception_data_type_t code, MACH_EXC_STATE_TYPE *exc_state, MACH_THREAD_STATE_TYPE *thread_state, MACH_FLOAT_STATE_TYPE *float_state);
|
||||
#endif
|
||||
|
||||
factor_vm()
|
||||
: profiling_p(false),
|
||||
secure_gc(false),
|
||||
gc_off(false),
|
||||
fep_disabled(false),
|
||||
full_output(false),
|
||||
max_pic_size(0)
|
||||
{
|
||||
memset(this,0,sizeof(this)); // just to make sure
|
||||
}
|
||||
factor_vm();
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue