3 /* The compiled code heap is structured into blocks. */
5 // header format (bits indexed with least significant as zero):
7 // bits 1-2: type (as a code_block_type)
9 // bits 3-23: code size / 8
10 // bits 24-31: stack frame size / 16
12 // bits 3-end: code size / 8
14 cell owner; /* tagged pointer to word, quotation or f */
15 cell parameters; /* tagged pointer to array or f */
16 cell relocation; /* tagged pointer to byte-array or f */
18 bool free_p() const { return (header & 1) == 1; }
20 code_block_type type() const {
21 return (code_block_type)((header >> 1) & 0x3);
24 void set_type(code_block_type type) {
25 header = ((header & ~0x7) | (type << 1));
28 bool pic_p() const { return type() == code_block_pic; }
30 bool optimized_p() const { return type() == code_block_optimized; }
37 size = header & 0xFFFFF8;
38 FACTOR_ASSERT(size > 0);
42 cell stack_frame_size() const {
45 return (header >> 20) & 0xFF0;
48 cell stack_frame_size_for_address(cell addr) const {
49 cell natural_frame_size = stack_frame_size();
50 /* The first instruction in a code block is the prolog safepoint,
51 and a leaf procedure code block will record a frame size of zero.
52 If we're seeing a stack frame in either of these cases, it's a
53 fake "leaf frame" set up by the signal handler. */
54 if (natural_frame_size == 0 || addr == entry_point())
55 return LEAF_FRAME_SIZE;
56 return natural_frame_size;
59 void set_stack_frame_size(cell frame_size) {
60 FACTOR_ASSERT(size() < 0xFFFFFF);
61 FACTOR_ASSERT(!free_p());
62 FACTOR_ASSERT(frame_size % 16 == 0);
63 FACTOR_ASSERT(frame_size <= 0xFF0);
64 header = (header & 0xFFFFFF) | (frame_size << 20);
67 template <typename Fixup> cell size(Fixup fixup) const { return size(); }
69 cell entry_point() const { return (cell)(this + 1); }
71 /* GC info is stored at the end of the block */
72 gc_info* block_gc_info() const {
73 return (gc_info*)((uint8_t*)this + size() - sizeof(gc_info));
76 void flush_icache() { factor::flush_icache((cell)this, size()); }
78 template <typename Iterator> void each_instruction_operand(Iterator& iter) {
79 if (!to_boolean(relocation))
82 byte_array* rels = untag<byte_array>(relocation);
85 cell length = untag_fixnum(rels->capacity) / sizeof(relocation_entry);
87 for (cell i = 0; i < length; i++) {
88 relocation_entry rel = rels->data<relocation_entry>()[i];
89 iter(instruction_operand(rel, this, index));
90 index += rel.number_of_parameters();
94 cell offset(cell addr) const { return addr - entry_point(); }
96 cell address_for_offset(cell offset) const {
97 return entry_point() + offset;
100 cell scan(factor_vm* vm, cell addr) const;
101 cell owner_quot() const;
104 VM_C_API void undefined_symbol(void);
106 inline code_block* word::code() const {
107 FACTOR_ASSERT(entry_point != 0);
108 return (code_block*)entry_point - 1;
111 inline code_block* quotation::code() const {
112 FACTOR_ASSERT(entry_point != 0);
113 return (code_block*)entry_point - 1;