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