]> gitweb.factorcode.org Git - factor.git/blob - vm/code_blocks.hpp
VM: Refactor code_blocks to Factor style
[factor.git] / vm / code_blocks.hpp
1 namespace factor {
2
3 /* The compiled code heap is structured into blocks. */
4 struct code_block {
5   // header format (bits indexed with least significant as zero):
6   // bit   0  : free?
7   // bits  1-2: type (as a code_block_type)
8   // if not free:
9   //   bits  3-23: code size / 8
10   //   bits 24-31: stack frame size / 16
11   // if free:
12   //   bits  3-end: code size / 8
13   cell header;
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 */
17
18   bool free_p() const { return (header & 1) == 1; }
19
20   code_block_type type() const {
21     return (code_block_type)((header >> 1) & 0x3);
22   }
23
24   void set_type(code_block_type type) {
25     header = ((header & ~0x7) | (type << 1));
26   }
27
28   bool pic_p() const { return type() == code_block_pic; }
29
30   bool optimized_p() const { return type() == code_block_optimized; }
31
32   cell size() const {
33     cell size;
34     if (free_p())
35       size = header & ~7;
36     else
37       size = header & 0xFFFFF8;
38     FACTOR_ASSERT(size > 0);
39     return size;
40   }
41
42   cell stack_frame_size() const {
43     if (free_p())
44       return 0;
45     else
46       return (header >> 20) & 0xFF0;
47   }
48
49   cell stack_frame_size_for_address(cell addr) const {
50     cell natural_frame_size = stack_frame_size();
51     /* The first instruction in a code block is the prolog safepoint,
52        and a leaf procedure code block will record a frame size of zero.
53        If we're seeing a stack frame in either of these cases, it's a
54        fake "leaf frame" set up by the signal handler. */
55     if (natural_frame_size == 0 || (void*)addr == entry_point())
56       return LEAF_FRAME_SIZE;
57     else
58       return natural_frame_size;
59   }
60
61   void set_stack_frame_size(cell frame_size) {
62     FACTOR_ASSERT(size() < 0xFFFFFF);
63     FACTOR_ASSERT(!free_p());
64     FACTOR_ASSERT(frame_size % 16 == 0);
65     FACTOR_ASSERT(frame_size <= 0xFF0);
66     header = (header & 0xFFFFFF) | (frame_size << 20);
67   }
68
69   template <typename Fixup> cell size(Fixup fixup) const { return size(); }
70
71   void* entry_point() const { return (void*)(this + 1); }
72
73   /* GC info is stored at the end of the block */
74   gc_info* block_gc_info() const {
75     return (gc_info*)((u8*)this + size() - sizeof(gc_info));
76   }
77
78   void flush_icache() { factor::flush_icache((cell) this, size()); }
79
80   template <typename Iterator> void each_instruction_operand(Iterator& iter) {
81     if (to_boolean(relocation)) {
82       byte_array* rels = (byte_array*)UNTAG(relocation);
83
84       cell index = 0;
85       cell length = (rels->capacity >> TAG_BITS) / sizeof(relocation_entry);
86
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();
91       }
92     }
93   }
94
95   cell offset(void* addr) const { return (char*)addr - (char*)entry_point(); }
96
97   void* address_for_offset(cell offset) const {
98     return (void*)((char*)entry_point() + offset);
99   }
100
101   cell scan(factor_vm* vm, void* addr) const;
102   cell owner_quot() const;
103 };
104
105 VM_C_API void undefined_symbol(void);
106
107 inline code_block* word::code() const {
108   FACTOR_ASSERT(entry_point != NULL);
109   return (code_block*)entry_point - 1;
110 }
111
112 inline code_block* quotation::code() const {
113   FACTOR_ASSERT(entry_point != NULL);
114   return (code_block*)entry_point - 1;
115 }
116
117 }