return (a + (b-1)) & ~(b-1);
}
+inline static cell alignment_for(cell a, cell b)
+{
+ return align(a,b) - a;
+}
+
static const cell data_alignment = 16;
#define WORD_SIZE (signed)(sizeof(cell)*8)
-#define TAG_MASK 7
-#define TAG_BITS 3
+#define TAG_MASK 15
+#define TAG_BITS 4
#define TAG(x) ((cell)(x) & TAG_MASK)
#define UNTAG(x) ((cell)(x) & ~TAG_MASK)
#define RETAG(x,tag) (UNTAG(x) | (tag))
/*** Tags ***/
#define FIXNUM_TYPE 0
-#define BIGNUM_TYPE 1
+#define F_TYPE 1
#define ARRAY_TYPE 2
#define FLOAT_TYPE 3
#define QUOTATION_TYPE 4
-#define F_TYPE 5
-#define OBJECT_TYPE 6
+#define BIGNUM_TYPE 5
+#define ALIEN_TYPE 6
#define TUPLE_TYPE 7
-
-#define HEADER_TYPE 8 /* anything less than this is a tag */
-
-#define GC_COLLECTED 5 /* can be anything other than FIXNUM_TYPE */
-
-/*** Header types ***/
#define WRAPPER_TYPE 8
#define BYTE_ARRAY_TYPE 9
#define CALLSTACK_TYPE 10
#define STRING_TYPE 11
#define WORD_TYPE 12
#define DLL_TYPE 13
-#define ALIEN_TYPE 14
-
-#define TYPE_COUNT 15
-/* Not real types, but code_block's type can be set to this */
+#define TYPE_COUNT 14
enum code_block_type
{
code_block_unoptimized,
code_block_optimized,
- code_block_profiling,
+ code_block_counting_profiler,
code_block_pic
};
inline static bool immediate_p(cell obj)
{
- return (obj == false_object || TAG(obj) == FIXNUM_TYPE);
+ /* We assume that fixnums have tag 0 and false_object has tag 1 */
+ return TAG(obj) <= F_TYPE;
}
inline static fixnum untag_fixnum(cell tagged)
return RETAG(untagged << TAG_BITS,FIXNUM_TYPE);
}
-inline static cell tag_for(cell type)
-{
- return type < HEADER_TYPE ? type : OBJECT_TYPE;
-}
+#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
-struct object;
+struct object {
+ NO_TYPE_CHECK;
+ cell header;
-struct header {
- cell value;
+ cell size() const;
+ template<typename Fixup> cell size(Fixup fixup) const;
- /* Default ctor to make gcc 3.x happy */
- explicit header() { abort(); }
+ cell binary_payload_start() const;
+ template<typename Fixup> cell binary_payload_start(Fixup fixup) const;
- explicit header(cell value_) : value(value_ << TAG_BITS) {}
+ cell *slots() const { return (cell *)this; }
- void check_header()
+ template<typename Iterator> void each_slot(Iterator &iter);
+
+ /* Only valid for objects in tenured space; must cast to free_heap_block
+ to do anything with it if its free */
+ bool free_p() const
{
-#ifdef FACTOR_DEBUG
- assert(TAG(value) == FIXNUM_TYPE && untag_fixnum(value) < TYPE_COUNT);
-#endif
+ return (header & 1) == 1;
}
- cell hi_tag()
+ cell type() const
{
- check_header();
- return value >> TAG_BITS;
+ return (header >> 2) & TAG_MASK;
}
- bool forwarding_pointer_p()
+ void initialize(cell type)
{
- return TAG(value) == GC_COLLECTED;
+ header = type << 2;
}
- object *forwarding_pointer()
+ cell hashcode() const
{
- return (object *)UNTAG(value);
+ return (header >> 6);
}
- void forward_to(object *pointer)
+ void set_hashcode(cell hashcode)
{
- value = RETAG(pointer,GC_COLLECTED);
+ header = (header & 0x3f) | (hashcode << 6);
}
-};
-#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
-
-struct object {
- NO_TYPE_CHECK;
- header h;
-
- cell size();
+ bool forwarding_pointer_p() const
+ {
+ return (header & 2) == 2;
+ }
- cell *slots() { return (cell *)this; }
+ object *forwarding_pointer() const
+ {
+ return (object *)UNTAG(header);
+ }
- /* Only valid for objects in tenured space; must fast to free_heap_block
- to do anything with it if its free */
- bool free_p()
+ void forward_to(object *pointer)
{
- return h.value & 1 == 1;
+ header = ((cell)pointer | 2);
}
};
/* tagged */
cell capacity;
- cell *data() { return (cell *)(this + 1); }
+ cell *data() const { return (cell *)(this + 1); }
};
/* These are really just arrays, but certain elements have special
/* tagged */
cell capacity;
- cell *data() { return (cell *)(this + 1); }
+ cell *data() const { return (cell *)(this + 1); }
};
struct byte_array : public object {
cell padding1;
#endif
- template<typename Scalar> Scalar *data() { return (Scalar *)(this + 1); }
+ template<typename Scalar> Scalar *data() const { return (Scalar *)(this + 1); }
};
/* Assembly code makes assumptions about the layout of this struct */
/* tagged */
cell hashcode;
- u8 *data() { return (u8 *)(this + 1); }
+ u8 *data() const { return (u8 *)(this + 1); }
};
-/* The compiled code heap is structured into blocks. */
-struct heap_block
-{
- cell header;
-
- bool free_p()
- {
- return header & 1 == 1;
- }
-
- void set_free()
- {
- header |= 1;
- }
-
- void clear_free()
- {
- header &= ~1;
- }
-
- cell size()
- {
- return header >> 3;
- }
-
- void set_size(cell size)
- {
- header = (header & 0x7) | (size << 3);
- }
-};
-
-struct free_heap_block : public heap_block
-{
- free_heap_block *next_free;
-};
-
-struct code_block : public heap_block
-{
- cell owner; /* tagged pointer to word, quotation or f */
- cell literals; /* tagged pointer to array or f */
- cell relocation; /* tagged pointer to byte-array or f */
-
- void *xt()
- {
- return (void *)(this + 1);
- }
-
- code_block_type type()
- {
- return (code_block_type)((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;
- }
-};
+struct code_block;
/* Assembly code makes assumptions about the layout of this struct */
struct word : public object {
cell pic_def;
/* TAGGED alternative entry point for direct tail calls. Used for inline caching */
cell pic_tail_def;
- /* TAGGED call count for profiling */
+ /* TAGGED call count for counting_profiler */
cell counter;
/* TAGGED machine code for sub-primitive */
cell subprimitive;
- /* UNTAGGED execution token: jump here to execute word */
- void *xt;
+ /* UNTAGGED entry point: jump here to execute word */
+ void *entry_point;
/* UNTAGGED compiled code block */
code_block *code;
- /* UNTAGGED profiler stub */
- code_block *profiling;
+ /* UNTAGGED counting_profiler stub */
+ code_block *counting_profiler;
};
/* Assembly code makes assumptions about the layout of this struct */
cell cached_effect;
/* tagged */
cell cache_counter;
- /* UNTAGGED */
- void *xt;
+ /* UNTAGGED entry point; jump here to call quotation */
+ void *entry_point;
/* UNTAGGED compiled code block */
code_block *code;
};
cell expired;
/* untagged */
cell displacement;
+ /* untagged */
+ cell address;
+
+ void update_address()
+ {
+ if(base == false_object)
+ address = displacement;
+ else
+ address = UNTAG(base) + sizeof(byte_array) + displacement;
+ }
};
struct dll : public object {
/* tagged byte array holding a C string */
cell path;
/* OS-specific handle */
- void *dll;
+ void *handle;
};
-struct stack_frame
-{
- void *xt;
+struct stack_frame {
+ /* Updated by procedure prologue with procedure start address */
+ void *entry_point;
/* Frame size in bytes */
cell size;
};
/* tagged */
cell length;
- stack_frame *frame_at(cell offset)
+ stack_frame *frame_at(cell offset) const
{
return (stack_frame *)((char *)(this + 1) + offset);
}
- stack_frame *top() { return (stack_frame *)(this + 1); }
- stack_frame *bottom() { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
+ stack_frame *top() const { return (stack_frame *)(this + 1); }
+ stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
};
struct tuple : public object {
/* tagged layout */
cell layout;
- cell *data() { return (cell *)(this + 1); }
+ cell *data() const { return (cell *)(this + 1); }
+};
+
+struct data_root_range {
+ cell *start;
+ cell len;
+
+ explicit data_root_range(cell *start_, cell len_) :
+ start(start_), len(len_) {}
};
}