]> gitweb.factorcode.org Git - factor.git/blob - vm/jit.cpp
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / vm / jit.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Simple code generator used by:
7 - profiler (profiler.cpp),
8 - quotation compiler (quotations.cpp),
9 - megamorphic caches (dispatch.cpp),
10 - polymorphic inline caches (inline_cache.cpp) */
11
12 /* Allocates memory */
13 jit::jit(cell type_, cell owner_, factor_vm *vm)
14         : type(type_),
15           owner(owner_,vm),
16           code(vm),
17           relocation(vm),
18           literals(vm),
19           computing_offset_p(false),
20           position(0),
21           offset(0),
22           parent_vm(vm)
23 {
24         if(parent_vm->stack_traces_p()) literal(owner.value());
25 }
26
27 void jit::emit_relocation(cell code_template_)
28 {
29         gc_root<array> code_template(code_template_,parent_vm);
30         cell capacity = array_capacity(code_template.untagged());
31         for(cell i = 1; i < capacity; i += 3)
32         {
33                 cell rel_class = array_nth(code_template.untagged(),i);
34                 cell rel_type = array_nth(code_template.untagged(),i + 1);
35                 cell offset = array_nth(code_template.untagged(),i + 2);
36
37                 relocation_entry new_entry
38                         = (untag_fixnum(rel_type) << 28)
39                         | (untag_fixnum(rel_class) << 24)
40                         | ((code.count + untag_fixnum(offset)));
41                 relocation.append_bytes(&new_entry,sizeof(relocation_entry));
42         }
43 }
44
45 /* Allocates memory */
46 void jit::emit(cell code_template_)
47 {
48         gc_root<array> code_template(code_template_,parent_vm);
49
50         emit_relocation(code_template.value());
51
52         gc_root<byte_array> insns(array_nth(code_template.untagged(),0),parent_vm);
53
54         if(computing_offset_p)
55         {
56                 cell size = array_capacity(insns.untagged());
57
58                 if(offset == 0)
59                 {
60                         position--;
61                         computing_offset_p = false;
62                 }
63                 else if(offset < size)
64                 {
65                         position++;
66                         computing_offset_p = false;
67                 }
68                 else
69                         offset -= size;
70         }
71
72         code.append_byte_array(insns.value());
73 }
74
75 void jit::emit_with(cell code_template_, cell argument_) {
76         gc_root<array> code_template(code_template_,parent_vm);
77         gc_root<object> argument(argument_,parent_vm);
78         literal(argument.value());
79         emit(code_template.value());
80 }
81
82 void jit::emit_class_lookup(fixnum index, cell type)
83 {
84         emit_with(parent_vm->userenv[PIC_LOAD],tag_fixnum(-index * sizeof(cell)));
85         emit(parent_vm->userenv[type]);
86 }
87
88 /* Facility to convert compiled code offsets to quotation offsets.
89 Call jit_compute_offset() with the compiled code offset, then emit
90 code, and at the end jit->position is the quotation position. */
91 void jit::compute_position(cell offset_)
92 {
93         computing_offset_p = true;
94         position = 0;
95         offset = offset_;
96 }
97
98 /* Allocates memory */
99 code_block *jit::to_code_block()
100 {
101         code.trim();
102         relocation.trim();
103         literals.trim();
104
105         return parent_vm->add_code_block(
106                 type,
107                 code.elements.value(),
108                 F, /* no labels */
109                 relocation.elements.value(),
110                 literals.elements.value());
111 }
112
113 }