Merge branch 'master' of git://factorcode.org/git/factor

db4
Doug Coleman 2009-10-05 12:34:56 -05:00
commit 23288da694
21 changed files with 180 additions and 195 deletions

View File

@ -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

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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

View File

@ -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 -- )

View File

@ -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 ;

View File

@ -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 )
[
[

View File

@ -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,

View File

@ -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 ]

View File

@ -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 -- )

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

2
vm/generic_arrays.hpp Normal file → Executable file
View File

@ -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;
}

View File

@ -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
vm/tuples.cpp Normal file → Executable file
View File

8
vm/vm.cpp Executable file
View File

@ -0,0 +1,8 @@
#include "master.hpp"
namespace factor
{
factor_vm::factor_vm() { }
}

12
vm/vm.hpp Normal file → Executable file
View File

@ -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();
};