vm: make a new old_space type to encapsulate a few things, split up generations array somewhat
parent
651a7fb6fa
commit
23e133e383
4
Makefile
4
Makefile
|
@ -51,7 +51,6 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
|
|||
vm/inline_cache.o \
|
||||
vm/io.o \
|
||||
vm/jit.o \
|
||||
vm/local_roots.o \
|
||||
vm/math.o \
|
||||
vm/primitives.o \
|
||||
vm/profiler.o \
|
||||
|
@ -61,8 +60,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
|
|||
vm/tuples.o \
|
||||
vm/utilities.o \
|
||||
vm/vm.o \
|
||||
vm/words.o \
|
||||
vm/write_barrier.o
|
||||
vm/words.o
|
||||
|
||||
EXE_OBJS = $(PLAF_EXE_OBJS)
|
||||
|
||||
|
|
|
@ -76,19 +76,20 @@ template<typename Strategy> object *factor_vm::promote_object(object *untagged,
|
|||
return newpointer;
|
||||
}
|
||||
|
||||
template<typename Strategy> void factor_vm::trace_card(card *ptr, cell here, Strategy &strategy)
|
||||
template<typename Strategy> void factor_vm::trace_card(card *ptr, old_space *gen, Strategy &strategy)
|
||||
{
|
||||
cell card_scan = card_to_addr(ptr) + card_offset(ptr);
|
||||
cell card_start = card_to_addr(ptr);
|
||||
cell card_scan = card_start + gen->card_offset(card_start);
|
||||
cell card_end = card_to_addr(ptr + 1);
|
||||
|
||||
if(here < card_end) card_end = here;
|
||||
if(gen->here < card_end) card_end = gen->here;
|
||||
|
||||
strategy.copy_reachable_objects(card_scan,&card_end);
|
||||
|
||||
gc_stats.cards_scanned++;
|
||||
}
|
||||
|
||||
template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cell here, card mask, card unmask, Strategy &strategy)
|
||||
template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, old_space *gen, card mask, card unmask, Strategy &strategy)
|
||||
{
|
||||
card *first_card = deck_to_card(deck);
|
||||
card *last_card = deck_to_card(deck + 1);
|
||||
|
@ -107,7 +108,7 @@ template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cel
|
|||
{
|
||||
if(ptr[card] & mask)
|
||||
{
|
||||
trace_card(&ptr[card],here,strategy);
|
||||
trace_card(&ptr[card],gen,strategy);
|
||||
ptr[card] &= ~unmask;
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +119,7 @@ template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cel
|
|||
}
|
||||
|
||||
/* Trace all objects referenced from marked cards */
|
||||
template<typename Strategy> void factor_vm::trace_cards(cell gen, zone *z, Strategy &strategy)
|
||||
template<typename Strategy> void factor_vm::trace_cards(cell gen, old_space *z, Strategy &strategy)
|
||||
{
|
||||
u64 start_time = current_micros();
|
||||
|
||||
|
@ -179,7 +180,7 @@ template<typename Strategy> void factor_vm::trace_cards(cell gen, zone *z, Strat
|
|||
{
|
||||
if(*ptr & mask)
|
||||
{
|
||||
trace_card_deck(ptr,z->here,mask,unmask,strategy);
|
||||
trace_card_deck(ptr,z,mask,unmask,strategy);
|
||||
*ptr &= ~unmask;
|
||||
}
|
||||
}
|
||||
|
@ -398,10 +399,10 @@ void factor_vm::update_dirty_code_blocks()
|
|||
}
|
||||
|
||||
template<typename Strategy>
|
||||
copying_collector<Strategy>::copying_collector(factor_vm *myvm_, zone *newspace_)
|
||||
: myvm(myvm_), current_gc(myvm_->current_gc), newspace(newspace_)
|
||||
copying_collector<Strategy>::copying_collector(factor_vm *myvm_, old_space *target_)
|
||||
: myvm(myvm_), current_gc(myvm_->current_gc), target(target_)
|
||||
{
|
||||
scan = newspace->here;
|
||||
scan = target->here;
|
||||
}
|
||||
|
||||
template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
||||
|
@ -411,14 +412,7 @@ template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
|||
|
||||
template<typename Strategy> object *copying_collector<Strategy>::allot(cell size)
|
||||
{
|
||||
if(newspace->here + size <= newspace->end)
|
||||
{
|
||||
object *obj = newspace->allot(size);
|
||||
myvm->allot_barrier(obj);
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return target->allot(size);
|
||||
}
|
||||
|
||||
template<typename Strategy> object *copying_collector<Strategy>::copy_object(object *untagged)
|
||||
|
@ -440,13 +434,13 @@ template<typename Strategy> cell copying_collector<Strategy>::trace_next(cell sc
|
|||
|
||||
template<typename Strategy> void copying_collector<Strategy>::go()
|
||||
{
|
||||
strategy().copy_reachable_objects(scan,&newspace->here);
|
||||
strategy().copy_reachable_objects(scan,&target->here);
|
||||
}
|
||||
|
||||
struct nursery_collector : copying_collector<nursery_collector>
|
||||
{
|
||||
explicit nursery_collector(factor_vm *myvm_, zone *newspace_) :
|
||||
copying_collector<nursery_collector>(myvm_,newspace_) {}
|
||||
explicit nursery_collector(factor_vm *myvm_, old_space *target_) :
|
||||
copying_collector<nursery_collector>(myvm_,target_) {}
|
||||
|
||||
bool should_copy_p(object *untagged)
|
||||
{
|
||||
|
@ -463,13 +457,13 @@ struct aging_collector : copying_collector<aging_collector>
|
|||
{
|
||||
zone *tenured;
|
||||
|
||||
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
|
||||
copying_collector<aging_collector>(myvm_,newspace_),
|
||||
explicit aging_collector(factor_vm *myvm_, old_space *target_) :
|
||||
copying_collector<aging_collector>(myvm_,target_),
|
||||
tenured(myvm->data->tenured) {}
|
||||
|
||||
bool should_copy_p(object *untagged)
|
||||
{
|
||||
if(newspace->contains_p(untagged))
|
||||
if(target->contains_p(untagged))
|
||||
return false;
|
||||
else
|
||||
return !tenured->contains_p(untagged);
|
||||
|
@ -483,12 +477,12 @@ struct aging_collector : copying_collector<aging_collector>
|
|||
|
||||
struct aging_again_collector : copying_collector<aging_again_collector>
|
||||
{
|
||||
explicit aging_again_collector(factor_vm *myvm_, zone *newspace_) :
|
||||
copying_collector<aging_again_collector>(myvm_,newspace_) {}
|
||||
explicit aging_again_collector(factor_vm *myvm_, old_space *target_) :
|
||||
copying_collector<aging_again_collector>(myvm_,target_) {}
|
||||
|
||||
bool should_copy_p(object *untagged)
|
||||
{
|
||||
return !newspace->contains_p(untagged);
|
||||
return !target->contains_p(untagged);
|
||||
}
|
||||
|
||||
void copy_reachable_objects(cell scan, cell *end)
|
||||
|
@ -499,12 +493,12 @@ struct aging_again_collector : copying_collector<aging_again_collector>
|
|||
|
||||
struct tenured_collector : copying_collector<tenured_collector>
|
||||
{
|
||||
explicit tenured_collector(factor_vm *myvm_, zone *newspace_) :
|
||||
copying_collector<tenured_collector>(myvm_,newspace_) {}
|
||||
explicit tenured_collector(factor_vm *myvm_, old_space *target_) :
|
||||
copying_collector<tenured_collector>(myvm_,target_) {}
|
||||
|
||||
bool should_copy_p(object *untagged)
|
||||
{
|
||||
return !newspace->contains_p(untagged);
|
||||
return !target->contains_p(untagged);
|
||||
}
|
||||
|
||||
void copy_reachable_objects(cell scan, cell *end)
|
||||
|
@ -791,7 +785,6 @@ object *factor_vm::allot_object(header header, cell size)
|
|||
garbage_collection(tenured_gen,true,true,size);
|
||||
|
||||
obj = data->tenured->allot(size);
|
||||
allot_barrier(obj);
|
||||
|
||||
/* Allows initialization code to store old->new pointers
|
||||
without hitting the write barrier in the common case of
|
||||
|
|
|
@ -66,10 +66,10 @@ struct gc_state {
|
|||
template<typename Strategy> struct copying_collector {
|
||||
factor_vm *myvm;
|
||||
gc_state *current_gc;
|
||||
zone *newspace;
|
||||
old_space *target;
|
||||
cell scan;
|
||||
|
||||
explicit copying_collector(factor_vm *myvm_, zone *newspace);
|
||||
explicit copying_collector(factor_vm *myvm_, old_space *target);
|
||||
Strategy &strategy();
|
||||
object *allot(cell size);
|
||||
cell trace_next(cell scan);
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace factor
|
|||
void factor_vm::init_card_decks()
|
||||
{
|
||||
cell start = align(data->seg->start,deck_size);
|
||||
allot_markers_offset = (cell)data->allot_markers - (start >> card_bits);
|
||||
cards_offset = (cell)data->cards - (start >> card_bits);
|
||||
decks_offset = (cell)data->decks - (start >> deck_bits);
|
||||
}
|
||||
|
@ -36,26 +35,17 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t
|
|||
decks = new char[decks_size];
|
||||
decks_end = decks + decks_size;
|
||||
|
||||
allot_markers = new char[cards_size];
|
||||
allot_markers_end = allot_markers + cards_size;
|
||||
cell start = align(seg->start,deck_size);
|
||||
|
||||
cell alloter = align(seg->start,deck_size);
|
||||
tenured = new old_space(tenured_size,start);
|
||||
tenured_semispace = new old_space(tenured_size,tenured->end);
|
||||
|
||||
tenured = new zone;
|
||||
tenured_semispace = new zone;
|
||||
alloter = tenured->init_zone(tenured_size,alloter);
|
||||
alloter = tenured_semispace->init_zone(tenured_size,alloter);
|
||||
aging = new old_space(aging_size,tenured_semispace->end);
|
||||
aging_semispace = new old_space(aging_size,aging->end);
|
||||
|
||||
aging = new zone;
|
||||
aging_semispace = new zone;
|
||||
alloter = aging->init_zone(aging_size,alloter);
|
||||
alloter = aging_semispace->init_zone(aging_size,alloter);
|
||||
nursery = new zone(young_size,aging_semispace->end);
|
||||
|
||||
nursery = new zone;
|
||||
alloter = nursery->init_zone(young_size,alloter);
|
||||
|
||||
if(seg->end - alloter > deck_size)
|
||||
critical_error("Bug in alloc_data_heap",alloter);
|
||||
assert(seg->end - nursery->end <= deck_size);
|
||||
}
|
||||
|
||||
data_heap::~data_heap()
|
||||
|
@ -66,7 +56,6 @@ data_heap::~data_heap()
|
|||
delete aging_semispace;
|
||||
delete tenured;
|
||||
delete tenured_semispace;
|
||||
delete[] allot_markers;
|
||||
delete[] cards;
|
||||
delete[] decks;
|
||||
}
|
||||
|
@ -81,7 +70,7 @@ data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes)
|
|||
new_tenured_size);
|
||||
}
|
||||
|
||||
void factor_vm::clear_cards(zone *gen)
|
||||
void factor_vm::clear_cards(old_space *gen)
|
||||
{
|
||||
/* NOTE: reverse order due to heap layout. */
|
||||
card *first_card = addr_to_card(gen->start);
|
||||
|
@ -89,7 +78,7 @@ void factor_vm::clear_cards(zone *gen)
|
|||
memset(first_card,0,last_card - first_card);
|
||||
}
|
||||
|
||||
void factor_vm::clear_decks(zone *gen)
|
||||
void factor_vm::clear_decks(old_space *gen)
|
||||
{
|
||||
/* NOTE: reverse order due to heap layout. */
|
||||
card_deck *first_deck = addr_to_deck(gen->start);
|
||||
|
@ -97,23 +86,16 @@ void factor_vm::clear_decks(zone *gen)
|
|||
memset(first_deck,0,last_deck - first_deck);
|
||||
}
|
||||
|
||||
void factor_vm::clear_allot_markers(zone *gen)
|
||||
{
|
||||
card *first_card = addr_to_allot_marker((object *)gen->start);
|
||||
card *last_card = addr_to_allot_marker((object *)gen->end);
|
||||
memset(first_card,invalid_allot_marker,last_card - first_card);
|
||||
}
|
||||
|
||||
/* After garbage collection, any generations which are now empty need to have
|
||||
their allocation pointers and cards reset. */
|
||||
void factor_vm::reset_generation(zone *gen)
|
||||
void factor_vm::reset_generation(old_space *gen)
|
||||
{
|
||||
gen->here = gen->start;
|
||||
if(secure_gc) memset((void*)gen->start,69,gen->size);
|
||||
|
||||
clear_cards(gen);
|
||||
clear_decks(gen);
|
||||
clear_allot_markers(gen);
|
||||
gen->clear_allot_markers();
|
||||
}
|
||||
|
||||
void factor_vm::set_data_heap(data_heap *data_)
|
||||
|
|
|
@ -9,13 +9,10 @@ struct data_heap {
|
|||
segment *seg;
|
||||
|
||||
zone *nursery;
|
||||
zone *aging;
|
||||
zone *aging_semispace;
|
||||
zone *tenured;
|
||||
zone *tenured_semispace;
|
||||
|
||||
char *allot_markers;
|
||||
char *allot_markers_end;
|
||||
old_space *aging;
|
||||
old_space *aging_semispace;
|
||||
old_space *tenured;
|
||||
old_space *tenured_semispace;
|
||||
|
||||
char *cards;
|
||||
char *cards_end;
|
||||
|
|
|
@ -280,7 +280,7 @@ void factor_vm::relocate_data()
|
|||
relocating += untagged_object_size((object *)relocating))
|
||||
{
|
||||
object *obj = (object *)relocating;
|
||||
allot_barrier(obj);
|
||||
data->tenured->record_allocation(obj);
|
||||
relocate_object(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#include "master.hpp"
|
||||
|
||||
namespace factor
|
||||
{
|
||||
}
|
|
@ -69,9 +69,10 @@ namespace factor
|
|||
#include "bignumint.hpp"
|
||||
#include "bignum.hpp"
|
||||
#include "code_block.hpp"
|
||||
#include "gc/zone.hpp"
|
||||
#include "data_heap.hpp"
|
||||
#include "zone.hpp"
|
||||
#include "write_barrier.hpp"
|
||||
#include "old_space.hpp"
|
||||
#include "data_heap.hpp"
|
||||
#include "data_gc.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "strings.hpp"
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
struct old_space : zone {
|
||||
card *allot_markers;
|
||||
card *allot_markers_end;
|
||||
|
||||
old_space(cell size_, cell start_) : zone(size_,start_)
|
||||
{
|
||||
cell cards_size = size_ >> card_bits;
|
||||
allot_markers = new card[cards_size];
|
||||
allot_markers_end = allot_markers + cards_size;
|
||||
}
|
||||
|
||||
~old_space()
|
||||
{
|
||||
delete[] allot_markers;
|
||||
}
|
||||
|
||||
card *addr_to_allot_marker(object *a)
|
||||
{
|
||||
return (card *)((((cell)a - start) >> card_bits) + (cell)allot_markers);
|
||||
}
|
||||
|
||||
/* we need to remember the first object allocated in the card */
|
||||
void record_allocation(object *obj)
|
||||
{
|
||||
card *ptr = addr_to_allot_marker(obj);
|
||||
if(*ptr == invalid_allot_marker)
|
||||
*ptr = ((cell)obj & addr_card_mask);
|
||||
}
|
||||
|
||||
cell card_offset(cell address)
|
||||
{
|
||||
return allot_markers[(address - start) >> card_bits];
|
||||
}
|
||||
|
||||
object *allot(cell size)
|
||||
{
|
||||
if(here + size > end) return NULL;
|
||||
|
||||
object *obj = zone::allot(size);
|
||||
record_allocation(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void clear_allot_markers()
|
||||
{
|
||||
memset(allot_markers,invalid_allot_marker,size >> card_bits);
|
||||
}
|
||||
|
||||
/* object *next_object_after(object *ptr)
|
||||
{
|
||||
cell size = untagged_object_size(ptr);
|
||||
if((cell)ptr + size < end)
|
||||
return (object *)((cell)ptr + size);
|
||||
else
|
||||
return NULL;
|
||||
} */
|
||||
};
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace factor
|
|||
{
|
||||
|
||||
factor_vm::factor_vm() :
|
||||
nursery(0,0),
|
||||
profiling_p(false),
|
||||
secure_gc(false),
|
||||
gc_off(false),
|
||||
|
|
34
vm/vm.hpp
34
vm/vm.hpp
|
@ -53,9 +53,6 @@ struct factor_vm
|
|||
/* Code heap */
|
||||
code_heap *code;
|
||||
|
||||
/* Where we store object start offsets in cards */
|
||||
cell allot_markers_offset;
|
||||
|
||||
/* Only set if we're performing a GC */
|
||||
gc_state *current_gc;
|
||||
|
||||
|
@ -211,10 +208,9 @@ struct factor_vm
|
|||
//data_heap
|
||||
void init_card_decks();
|
||||
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
|
||||
void clear_cards(zone *gen);
|
||||
void clear_decks(zone *gen);
|
||||
void clear_allot_markers(zone *gen);
|
||||
void reset_generation(zone *gen);
|
||||
void clear_cards(old_space *gen);
|
||||
void clear_decks(old_space *gen);
|
||||
void reset_generation(old_space *gen);
|
||||
void set_data_heap(data_heap *data_);
|
||||
void init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_);
|
||||
cell untagged_object_size(object *pointer);
|
||||
|
@ -243,11 +239,6 @@ struct factor_vm
|
|||
return ((cell)c - cards_offset) << card_bits;
|
||||
}
|
||||
|
||||
inline cell card_offset(card *c)
|
||||
{
|
||||
return *(c - (cell)data->cards + (cell)data->allot_markers);
|
||||
}
|
||||
|
||||
inline card_deck *addr_to_deck(cell a)
|
||||
{
|
||||
return (card_deck *)(((cell)a >> deck_bits) + decks_offset);
|
||||
|
@ -263,11 +254,6 @@ struct factor_vm
|
|||
return (card *)((((cell)d - decks_offset) << (deck_bits - card_bits)) + cards_offset);
|
||||
}
|
||||
|
||||
inline card *addr_to_allot_marker(object *a)
|
||||
{
|
||||
return (card *)(((cell)a >> card_bits) + allot_markers_offset);
|
||||
}
|
||||
|
||||
/* the write barrier must be called any time we are potentially storing a
|
||||
pointer from an older generation to a younger one */
|
||||
inline void write_barrier(object *obj)
|
||||
|
@ -276,22 +262,14 @@ struct factor_vm
|
|||
*addr_to_deck((cell)obj) = card_mark_mask;
|
||||
}
|
||||
|
||||
/* we need to remember the first object allocated in the card */
|
||||
inline void allot_barrier(object *address)
|
||||
{
|
||||
card *ptr = addr_to_allot_marker(address);
|
||||
if(*ptr == invalid_allot_marker)
|
||||
*ptr = ((cell)address & addr_card_mask);
|
||||
}
|
||||
|
||||
// data_gc
|
||||
template<typename Strategy> object *resolve_forwarding(object *untagged, Strategy &strategy);
|
||||
template<typename Strategy> void trace_handle(cell *handle, Strategy &strategy);
|
||||
template<typename Strategy> object *promote_object(object *pointer, Strategy &strategy);
|
||||
template<typename Strategy> void trace_slots(object *ptr, Strategy &strategy);
|
||||
template<typename Strategy> void trace_card(card *ptr, cell here, Strategy &strategy);
|
||||
template<typename Strategy> void trace_card_deck(card_deck *deck, cell here, card mask, card unmask, Strategy &strategy);
|
||||
template<typename Strategy> void trace_cards(cell gen, zone *z, Strategy &strategy);
|
||||
template<typename Strategy> void trace_card(card *ptr, old_space *gen, Strategy &strategy);
|
||||
template<typename Strategy> void trace_card_deck(card_deck *deck, old_space *gen, card mask, card unmask, Strategy &strategy);
|
||||
template<typename Strategy> void trace_cards(cell gen, old_space *z, Strategy &strategy);
|
||||
template<typename Strategy> void trace_stack_elements(segment *region, cell top, Strategy &strategy);
|
||||
template<typename Strategy> void trace_registered_locals(Strategy &strategy);
|
||||
template<typename Strategy> void trace_registered_bignums(Strategy &strategy);
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#include "master.hpp"
|
||||
|
||||
using namespace factor;
|
||||
|
Loading…
Reference in New Issue