]> gitweb.factorcode.org Git - factor.git/blob - vm/jit.cpp
vm: Add more comments about functions that allocate.
[factor.git] / vm / jit.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Simple code generator used by:
7 - quotation compiler (quotations.cpp),
8 - megamorphic caches (dispatch.cpp),
9 - polymorphic inline caches (inline_cache.cpp) */
10
11 /* Allocates memory */
12 jit::jit(code_block_type type_, cell owner_, factor_vm *vm)
13         : type(type_),
14           owner(owner_,vm),
15           code(vm),
16           relocation(vm),
17           parameters(vm),
18           literals(vm),
19           computing_offset_p(false),
20           position(0),
21           offset(0),
22           parent(vm)
23 {
24         fixnum old_count = atomic::fetch_add(&parent->current_jit_count, 1);
25         FACTOR_ASSERT(old_count >= 0);
26         (void)old_count;
27 }
28
29 jit::~jit()
30 {
31         fixnum old_count = atomic::fetch_subtract(&parent->current_jit_count, 1);
32         FACTOR_ASSERT(old_count >= 1);
33         (void)old_count;
34 }
35
36 void jit::emit_relocation(cell relocation_template_)
37 {
38         data_root<byte_array> relocation_template(relocation_template_,parent);
39         cell capacity = array_capacity(relocation_template.untagged())
40                 / sizeof(relocation_entry);
41         relocation_entry *relocations = relocation_template->data<relocation_entry>();
42         for(cell i = 0; i < capacity; i++)
43         {
44                 relocation_entry entry = relocations[i];
45                 relocation_entry new_entry(entry.rel_type(), entry.rel_class(),
46                         entry.rel_offset() + code.count);
47                 relocation.append_bytes(&new_entry,sizeof(relocation_entry));
48         }
49 }
50
51 /* Allocates memory */
52 void jit::emit(cell code_template_)
53 {
54         data_root<array> code_template(code_template_,parent);
55
56         emit_relocation(array_nth(code_template.untagged(),0));
57
58         data_root<byte_array> insns(array_nth(code_template.untagged(),1),parent);
59
60         if(computing_offset_p)
61         {
62                 cell size = array_capacity(insns.untagged());
63
64                 if(offset == 0)
65                 {
66                         position--;
67                         computing_offset_p = false;
68                 }
69                 else if(offset < size)
70                 {
71                         position++;
72                         computing_offset_p = false;
73                 }
74                 else
75                         offset -= size;
76         }
77
78         code.append_byte_array(insns.value());
79 }
80
81 /* Allocates memory */
82 void jit::emit_with_literal(cell code_template_, cell argument_) {
83         data_root<array> code_template(code_template_,parent);
84         data_root<object> argument(argument_,parent);
85         literal(argument.value());
86         emit(code_template.value());
87 }
88
89 /* Allocates memory */
90 void jit::emit_with_parameter(cell code_template_, cell argument_) {
91         data_root<array> code_template(code_template_,parent);
92         data_root<object> argument(argument_,parent);
93         parameter(argument.value());
94         emit(code_template.value());
95 }
96
97 /* Allocates memory */
98 bool jit::emit_subprimitive(cell word_, bool tail_call_p, bool stack_frame_p)
99 {
100         data_root<word> word(word_,parent);
101         data_root<array> code_template(word->subprimitive,parent);
102         parameters.append(untag<array>(array_nth(code_template.untagged(),0)));
103         literals.append(untag<array>(array_nth(code_template.untagged(),1)));
104         emit(array_nth(code_template.untagged(),2));
105
106         if(array_capacity(code_template.untagged()) == 5)
107         {
108                 if(tail_call_p)
109                 {
110                         if(stack_frame_p) emit(parent->special_objects[JIT_EPILOG]);
111                         emit(array_nth(code_template.untagged(),4));
112                         return true;
113                 }
114                 else
115                         emit(array_nth(code_template.untagged(),3));
116         }
117         return false;
118 }
119         
120 /* Facility to convert compiled code offsets to quotation offsets.
121 Call jit_compute_offset() with the compiled code offset, then emit
122 code, and at the end jit->position is the quotation position. */
123 void jit::compute_position(cell offset_)
124 {
125         computing_offset_p = true;
126         position = 0;
127         offset = offset_;
128 }
129
130 /* Allocates memory */
131 code_block *jit::to_code_block(cell frame_size)
132 {
133         /* Emit dummy GC info */
134         code.grow_bytes(alignment_for(code.count + 4,data_alignment));
135         u32 dummy_gc_info = 0;
136         code.append_bytes(&dummy_gc_info,sizeof(u32));
137
138         code.trim();
139         relocation.trim();
140         parameters.trim();
141         literals.trim();
142
143         return parent->add_code_block(
144                 type,
145                 code.elements.value(),
146                 false_object, /* no labels */
147                 owner.value(),
148                 relocation.elements.value(),
149                 parameters.elements.value(),
150                 literals.elements.value(),
151                 frame_size);
152 }
153
154 }