are referenced after this is done. So instead of polluting
the code heap with dead PICs that will be freed on the next
GC, we add them to the free list immediately. */
- else if(compiled->type() == PIC_TYPE)
+ else if(compiled->pic_p())
code->code_heap_free(compiled);
else
{
}
/* Might GC */
-code_block *factor_vm::allot_code_block(cell size, cell type)
+code_block *factor_vm::allot_code_block(cell size, code_block_type type)
{
- heap_block *block = code->heap_allot(size + sizeof(code_block),type);
+ heap_block *block = code->heap_allot(size + sizeof(code_block));
/* If allocation failed, do a full GC and compact the code heap.
A full GC that occurs as a result of the data heap filling up does not
if(block == NULL)
{
primitive_compact_gc();
- block = code->heap_allot(size + sizeof(code_block),type);
+ block = code->heap_allot(size + sizeof(code_block));
/* Insufficient room even after code GC, give up */
if(block == NULL)
}
}
- return (code_block *)block;
+ code_block *compiled = (code_block *)block;
+ compiled->set_type(type);
+ return compiled;
}
/* Might GC */
-code_block *factor_vm::add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_)
+code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_)
{
gc_root<byte_array> code(code_,this);
gc_root<object> labels(labels_,this);
cell code = array_nth(compiled_data,4);
code_block *compiled = add_code_block(
- WORD_TYPE,
+ code_block_optimized,
code,
labels,
owner,
while(scan != end)
{
const char *status;
- if(scan->type() == FREE_BLOCK_TYPE)
+ if(scan->free_p())
status = "free";
else if(code->state->is_marked_p(scan))
{
{
clear_free_list();
free_heap_block *end = (free_heap_block *)(seg->start + size);
- end->set_type(FREE_BLOCK_TYPE);
+ end->set_free();
end->set_size(seg->end - (cell)end);
add_to_free_list(end);
}
void heap::assert_free_block(free_heap_block *block)
{
- if(block->type() != FREE_BLOCK_TYPE)
- critical_error("Invalid block in free list",(cell)block);
+#ifdef FACTOR_DEBUG
+ assert(block->free_p());
+#endif
}
free_heap_block *heap::find_free_block(cell size)
free_heap_block *heap::split_free_block(free_heap_block *block, cell size)
{
- if(block->size() != size )
+ if(block->size() != size)
{
/* split the block in two */
free_heap_block *split = (free_heap_block *)((cell)block + size);
- split->set_type(FREE_BLOCK_TYPE);
+ split->set_free();
split->set_size(block->size() - size);
split->next_free = block->next_free;
block->set_size(size);
return block;
}
-/* Allocate a block of memory from the mark and sweep GC heap */
-heap_block *heap::heap_allot(cell size, cell type)
+heap_block *heap::heap_allot(cell size)
{
- size = (size + block_size_increment - 1) & ~(block_size_increment - 1);
+ size = align(size,block_size_increment);
free_heap_block *block = find_free_block(size);
if(block)
{
block = split_free_block(block,size);
- block->set_type(type);
return block;
}
else
return NULL;
}
-/* Deallocates a block manually */
void heap::heap_free(heap_block *block)
{
- block->set_type(FREE_BLOCK_TYPE);
- add_to_free_list((free_heap_block *)block);
+ free_heap_block *free_block = (free_heap_block *)block;
+ free_block->set_free();
+ add_to_free_list(free_block);
}
void heap::mark_block(heap_block *block)
{
cell size = scan->size();
- if(scan->type() == FREE_BLOCK_TYPE)
+ if(scan->free_p())
{
*total_free += size;
if(size > *max_free)
while(scan != end)
{
- if(scan->type() == FREE_BLOCK_TYPE) break;
+ if(scan->free_p()) break;
else scan = scan->next();
}
- assert(scan->type() == FREE_BLOCK_TYPE);
- assert((cell)scan + scan->size() == seg->end);
-
- return (cell)scan - (cell)first_block();
-}
-
-heap_block *heap::free_allocated(heap_block *prev, heap_block *scan)
-{
- if(secure_gc)
- memset(scan + 1,0,scan->size() - sizeof(heap_block));
-
- if(prev && prev->type() == FREE_BLOCK_TYPE)
+ if(scan != end)
{
- prev->set_size(prev->size() + scan->size());
- return prev;
+ assert(scan->free_p());
+ assert((cell)scan + scan->size() == seg->end);
+
+ return (cell)scan - (cell)first_block();
}
else
- {
- scan->set_type(FREE_BLOCK_TYPE);
- return scan;
- }
+ return seg->size;
}
}
void assert_free_block(free_heap_block *block);
free_heap_block *find_free_block(cell size);
free_heap_block *split_free_block(free_heap_block *block, cell size);
- heap_block *heap_allot(cell size, cell type);
+ heap_block *heap_allot(cell size);
void heap_free(heap_block *block);
void mark_block(heap_block *block);
void heap_usage(cell *used, cell *total_free, cell *max_free);
cell heap_size();
void compact_heap();
- heap_block *free_allocated(heap_block *prev, heap_block *scan);
-
template<typename Iterator> void sweep_heap(Iterator &iter);
template<typename Iterator> void compact_heap(Iterator &iter);
while(scan != end)
{
heap_block *next = scan->next();
- if(scan->type() != FREE_BLOCK_TYPE) iter(scan,scan->size());
+ if(!scan->free_p()) iter(scan,scan->size());
scan = next;
}
}
while(scan != end)
{
- if(scan->type() == FREE_BLOCK_TYPE)
+ if(scan->free_p())
{
- if(prev && prev->type() == FREE_BLOCK_TYPE)
+ if(prev && prev->free_p())
prev->set_size(prev->size() + scan->size());
else
prev = scan;
}
else if(this->state->is_marked_p(scan))
{
- if(prev && prev->type() == FREE_BLOCK_TYPE)
+ if(prev && prev->free_p())
this->add_to_free_list((free_heap_block *)prev);
prev = scan;
iter(scan,scan->size());
}
else
- prev = this->free_allocated(prev,scan);
+ {
+ if(secure_gc)
+ memset(scan + 1,0,scan->size() - sizeof(heap_block));
+
+ if(prev && prev->free_p())
+ {
+ free_heap_block *free_prev = (free_heap_block *)prev;
+ free_prev->set_size(free_prev->size() + scan->size());
+ }
+ else
+ {
+ scan->set_free();
+ prev = scan;
+ }
+ }
scan = scan->next();
}
- if(prev && prev->type() == FREE_BLOCK_TYPE)
+ if(prev && prev->free_p())
this->add_to_free_list((free_heap_block *)prev);
}
check_code_pointer((cell)old_xt);
code_block *old_block = (code_block *)old_xt - 1;
- cell old_type = old_block->type();
-#ifdef FACTOR_DEBUG
- /* The call target was either another PIC,
- or a compiled quotation (megamorphic stub) */
- assert(old_type == PIC_TYPE || old_type == QUOTATION_TYPE);
-#endif
-
- if(old_type == PIC_TYPE)
+ /* Free the old PIC since we know its unreachable */
+ if(old_block->pic_p())
code->code_heap_free(old_block);
}
struct inline_cache_jit : public jit {
fixnum index;
- explicit inline_cache_jit(cell generic_word_,factor_vm *vm) : jit(PIC_TYPE,generic_word_,vm) {};
+ explicit inline_cache_jit(cell generic_word_,factor_vm *vm) : jit(code_block_pic,generic_word_,vm) {};
void emit_check(cell klass);
void compile_inline_cache(fixnum index,
- polymorphic inline caches (inline_cache.cpp) */
/* Allocates memory */
-jit::jit(cell type_, cell owner_, factor_vm *vm)
+jit::jit(code_block_type type_, cell owner_, factor_vm *vm)
: type(type_),
owner(owner_,vm),
code(vm),
{
struct jit {
- cell type;
+ code_block_type type;
gc_root<object> owner;
growable_byte_array code;
growable_byte_array relocation;
cell offset;
factor_vm *parent;
- explicit jit(cell jit_type, cell owner, factor_vm *vm);
+ explicit jit(code_block_type type, cell owner, factor_vm *parent);
void compute_position(cell offset);
void emit_relocation(cell code_template);
#define TYPE_COUNT 15
/* Not real types, but code_block's type can be set to this */
-#define PIC_TYPE 16
-#define FREE_BLOCK_TYPE 17
+
+enum code_block_type
+{
+ code_block_unoptimized,
+ code_block_optimized,
+ code_block_profiling,
+ code_block_pic
+};
/* Constants used when floating-point trap exceptions are thrown */
enum
{
cell header;
- cell type() { return (header >> 1) & 0x1f; }
- void set_type(cell type)
+ bool free_p()
{
- header = ((header & ~(0x1f << 1)) | (type << 1));
+ return header & 1 == 1;
+ }
+
+ void set_free()
+ {
+ header |= 1;
+ }
+
+ void clear_free()
+ {
+ header &= ~1;
+ }
+
+ cell size()
+ {
+ return header >> 3;
}
- cell size() { return (header >> 6); }
void set_size(cell size)
{
- header = (header & 0x2f) | (size << 6);
+ header = (header & 0x7) | (size << 3);
}
inline heap_block *next()
cell literals; /* tagged pointer to array or f */
cell relocation; /* tagged pointer to byte-array or f */
- void *xt() { return (void *)(this + 1); }
+ void *xt()
+ {
+ return (void *)(this + 1);
+ }
+
+ cell type()
+ {
+ return (header >> 1) & 0x3;
+ }
+
+ void set_type(code_block_type type)
+ {
+ header = ((header & ~0x7) | (type << 1));
+ }
+
+ bool pic_p()
+ {
+ return type() == code_block_pic;
+ }
+
+ bool optimized_p()
+ {
+ return type() == code_block_optimized;
+ }
};
/* Assembly code makes assumptions about the layout of this struct */
cell size;
cell bits_size;
u64 *marked;
- u64 *allocated;
cell *forwarding;
void clear_mark_bits()
memset(marked,0,bits_size * sizeof(u64));
}
- void clear_allocated_bits()
- {
- memset(allocated,0,bits_size * sizeof(u64));
- }
-
void clear_forwarding()
{
memset(forwarding,0,bits_size * sizeof(cell));
size(size_),
bits_size(size / Granularity / forwarding_granularity),
marked(new u64[bits_size]),
- allocated(new u64[bits_size]),
forwarding(new cell[bits_size])
{
clear_mark_bits();
- clear_allocated_bits();
clear_forwarding();
}
{
delete[] marked;
marked = NULL;
- delete[] allocated;
- allocated = NULL;
delete[] forwarding;
forwarding = NULL;
}
set_bitmap_range(marked,address);
}
- bool is_allocated_p(Block *address)
- {
- return bitmap_elt(allocated,address);
- }
-
- void set_allocated_p(Block *address)
- {
- set_bitmap_range(allocated,address);
- }
-
/* From http://chessprogramming.wikispaces.com/Population+Count */
cell popcount(u64 x)
{
{
gc_root<word> word(word_,this);
- jit jit(WORD_TYPE,word.value(),this);
+ jit jit(code_block_profiling,word.value(),this);
jit.emit_with(userenv[JIT_PROFILING],word.value());
return jit.to_code_block();
{
gc_root<word> word(array_nth(words.untagged(),i),this);
- if(!word->code || !word_optimized_p(word.untagged()))
+ if(!word->code || !word->code->optimized_p())
jit_compile_word(word.value(),word->def,false);
update_word_xt(word.value());
bool compiling, relocate;
explicit quotation_jit(cell quot, bool compiling_, bool relocate_, factor_vm *vm)
- : jit(QUOTATION_TYPE,quot,vm),
+ : jit(code_block_unoptimized,quot,vm),
elements(owner.as<quotation>().untagged()->array,vm),
compiling(compiling_),
relocate(relocate_){};
return tag;
}
- bool type_p(cell type_) const { return type() == type_; }
+ bool type_p(cell type_) const
+ {
+ return type() == type_;
+ }
+
+ bool type_p() const
+ {
+ if(Type::type_number == TYPE_COUNT)
+ return true;
+ else
+ return type_p(Type::type_number);
+ }
Type *untag_check(factor_vm *parent) const {
- if(Type::type_number != TYPE_COUNT && !type_p(Type::type_number))
+ if(!type_p())
parent->type_error(Type::type_number,value_);
return untagged();
}
explicit tagged(cell tagged) : value_(tagged) {
#ifdef FACTOR_DEBUG
- untag_check(tls_vm());
+ assert(type_p());
#endif
}
explicit tagged(Type *untagged) : value_(factor::tag(untagged)) {
#ifdef FACTOR_DEBUG
- untag_check(tls_vm());
+ assert(type_p());
#endif
}
void check_code_address(cell address);
void relocate_code_block(code_block *compiled);
void fixup_labels(array *labels, code_block *compiled);
- code_block *allot_code_block(cell size, cell type);
- code_block *add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
+ code_block *allot_code_block(cell size, code_block_type type);
+ code_block *add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
//code heap
inline void check_code_pointer(cell ptr)
void factor_vm::primitive_optimized_p()
{
- drepl(tag_boolean(word_optimized_p(untag_check<word>(dpeek()))));
+ word *w = untag_check<word>(dpeek());
+ drepl(tag_boolean(w->code->optimized_p()));
}
void factor_vm::primitive_wrapper()
namespace factor
{
-inline bool word_optimized_p(word *word)
-{
- return word->code->type() == WORD_TYPE;
-}
-
}