154 lines
3.2 KiB
C++
154 lines
3.2 KiB
C++
namespace factor
|
|
{
|
|
|
|
/* The compiled code heap is structured into blocks. */
|
|
struct code_block
|
|
{
|
|
// header format (bits indexed with least significant as zero):
|
|
// bit 0 : free?
|
|
// bits 1-2: type (as a code_block_type)
|
|
// if not free:
|
|
// bits 3-23: code size / 8
|
|
// bits 24-31: stack frame size / 16
|
|
// if free:
|
|
// bits 3-end: code size / 8
|
|
cell header;
|
|
cell owner; /* tagged pointer to word, quotation or f */
|
|
cell parameters; /* tagged pointer to array or f */
|
|
cell relocation; /* tagged pointer to byte-array or f */
|
|
|
|
bool free_p() const
|
|
{
|
|
return (header & 1) == 1;
|
|
}
|
|
|
|
code_block_type type() const
|
|
{
|
|
return (code_block_type)((header >> 1) & 0x3);
|
|
}
|
|
|
|
void set_type(code_block_type type)
|
|
{
|
|
header = ((header & ~0x7) | (type << 1));
|
|
}
|
|
|
|
bool pic_p() const
|
|
{
|
|
return type() == code_block_pic;
|
|
}
|
|
|
|
bool optimized_p() const
|
|
{
|
|
return type() == code_block_optimized;
|
|
}
|
|
|
|
cell size() const
|
|
{
|
|
cell size;
|
|
if (free_p())
|
|
size = header & ~7;
|
|
else
|
|
size = header & 0xFFFFF8;
|
|
FACTOR_ASSERT(size > 0);
|
|
return size;
|
|
}
|
|
|
|
cell stack_frame_size() const
|
|
{
|
|
if (free_p())
|
|
return 0;
|
|
else
|
|
return (header >> 20) & 0xFF0;
|
|
}
|
|
|
|
cell stack_frame_size_for_address(cell addr) const
|
|
{
|
|
cell natural_frame_size = stack_frame_size();
|
|
/* The first instruction in a code block is the prolog safepoint,
|
|
and a leaf procedure code block will record a frame size of zero.
|
|
If we're seeing a stack frame in either of these cases, it's a
|
|
fake "leaf frame" set up by the signal handler. */
|
|
if (natural_frame_size == 0 || (void*)addr == entry_point())
|
|
return LEAF_FRAME_SIZE;
|
|
else
|
|
return natural_frame_size;
|
|
}
|
|
|
|
void set_stack_frame_size(cell frame_size)
|
|
{
|
|
FACTOR_ASSERT(size() < 0xFFFFFF);
|
|
FACTOR_ASSERT(!free_p());
|
|
FACTOR_ASSERT(frame_size % 16 == 0);
|
|
FACTOR_ASSERT(frame_size <= 0xFF0);
|
|
header = (header & 0xFFFFFF) | (frame_size << 20);
|
|
}
|
|
|
|
template<typename Fixup> cell size(Fixup fixup) const
|
|
{
|
|
return size();
|
|
}
|
|
|
|
void *entry_point() const
|
|
{
|
|
return (void *)(this + 1);
|
|
}
|
|
|
|
/* GC info is stored at the end of the block */
|
|
gc_info *block_gc_info() const
|
|
{
|
|
return (gc_info *)((u8 *)this + size() - sizeof(gc_info));
|
|
}
|
|
|
|
void flush_icache()
|
|
{
|
|
factor::flush_icache((cell)this,size());
|
|
}
|
|
|
|
template<typename Iterator> void each_instruction_operand(Iterator &iter)
|
|
{
|
|
if(to_boolean(relocation))
|
|
{
|
|
byte_array *rels = (byte_array *)UNTAG(relocation);
|
|
|
|
cell index = 0;
|
|
cell length = (rels->capacity >> TAG_BITS) / sizeof(relocation_entry);
|
|
|
|
for(cell i = 0; i < length; i++)
|
|
{
|
|
relocation_entry rel = rels->data<relocation_entry>()[i];
|
|
iter(instruction_operand(rel,this,index));
|
|
index += rel.number_of_parameters();
|
|
}
|
|
}
|
|
}
|
|
|
|
cell offset(void *addr) const
|
|
{
|
|
return (char*)addr - (char*)entry_point();
|
|
}
|
|
|
|
void *address_for_offset(cell offset) const
|
|
{
|
|
return (void*)((char*)entry_point() + offset);
|
|
}
|
|
|
|
cell scan(factor_vm *vm, void *addr) const;
|
|
cell owner_quot() const;
|
|
};
|
|
|
|
VM_C_API void undefined_symbol(void);
|
|
|
|
inline code_block *word::code() const {
|
|
FACTOR_ASSERT(entry_point != NULL);
|
|
return (code_block*)entry_point - 1;
|
|
}
|
|
|
|
inline code_block *quotation::code() const {
|
|
FACTOR_ASSERT(entry_point != NULL);
|
|
return (code_block*)entry_point - 1;
|
|
}
|
|
|
|
}
|
|
|
|
|