5 // Simple code generator used by:
6 // - quotation compiler (quotations.cpp),
7 // - megamorphic caches (dispatch.cpp),
8 // - polymorphic inline caches (inline_cache.cpp)
10 // Allocates memory (`code` and `relocation` initializers create
11 // growable_byte_array)
12 jit::jit(cell owner
, factor_vm
* vm
)
18 computing_offset_p(false),
22 fixnum old_count
= atomic::fetch_add(&parent
->current_jit_count
, 1);
23 FACTOR_ASSERT(old_count
>= 0);
28 fixnum old_count
= atomic::fetch_subtract(&parent
->current_jit_count
, 1);
29 FACTOR_ASSERT(old_count
>= 1);
34 void jit::emit_relocation(cell relocation_template_
) {
35 data_root
<byte_array
> relocation_template(relocation_template_
, parent
);
37 array_capacity(relocation_template
.untagged()) / sizeof(relocation_entry
);
38 relocation_entry
* relocations
= relocation_template
->data
<relocation_entry
>();
39 for (cell i
= 0; i
< capacity
; i
++) {
40 relocation_entry entry
= relocations
[i
];
41 relocation_entry
new_entry(entry
.type(), entry
.klass(),
42 entry
.offset() + code
.count
);
43 relocation
.append_bytes(&new_entry
, sizeof(relocation_entry
));
48 void jit::emit(cell code_template_
) {
49 data_root
<array
> code_template(code_template_
, parent
);
51 emit_relocation(array_nth(code_template
.untagged(), 0));
53 data_root
<byte_array
> insns(array_nth(code_template
.untagged(), 1), parent
);
55 if (computing_offset_p
) {
56 cell size
= array_capacity(insns
.untagged());
60 computing_offset_p
= false;
61 } else if (offset
< size
) {
63 computing_offset_p
= false;
68 code
.append_byte_array(insns
.value());
72 void jit::emit_with_literal(cell code_template_
, cell argument_
) {
73 data_root
<array
> code_template(code_template_
, parent
);
74 data_root
<object
> argument(argument_
, parent
);
75 literal(argument
.value());
76 emit(code_template
.value());
80 void jit::emit_with_parameter(cell code_template_
, cell argument_
) {
81 data_root
<array
> code_template(code_template_
, parent
);
82 data_root
<object
> argument(argument_
, parent
);
83 parameter(argument
.value());
84 emit(code_template
.value());
88 bool jit::emit_subprimitive(cell word_
, bool tail_call_p
, bool stack_frame_p
) {
89 data_root
<word
> word(word_
, parent
);
90 data_root
<array
> code_template(word
->subprimitive
, parent
);
91 parameters
.append(untag
<array
>(array_nth(code_template
.untagged(), 0)));
92 literals
.append(untag
<array
>(array_nth(code_template
.untagged(), 1)));
93 emit(array_nth(code_template
.untagged(), 2));
95 if (array_capacity(code_template
.untagged()) == 5) {
98 emit(parent
->special_objects
[JIT_EPILOG
]);
99 emit(array_nth(code_template
.untagged(), 4));
102 emit(array_nth(code_template
.untagged(), 3));
107 // Facility to convert compiled code offsets to quotation offsets.
108 // Call jit_compute_offset() with the compiled code offset, then emit
109 // code, and at the end jit->position is the quotation position.
110 void jit::compute_position(cell offset_
) {
111 computing_offset_p
= true;
116 // Allocates memory (trim(), add_code_block)
117 code_block
* jit::to_code_block(code_block_type type
, cell frame_size
) {
118 // Emit dummy GC info
119 code
.grow_bytes(alignment_for(code
.count
+ 4, data_alignment
));
120 uint32_t dummy_gc_info
= 0;
121 code
.append_bytes(&dummy_gc_info
, sizeof(uint32_t));
128 return parent
->add_code_block(
129 type
, code
.elements
.value(), false_object
, // no labels
130 owner
.value(), relocation
.elements
.value(), parameters
.elements
.value(),
131 literals
.elements
.value(), frame_size
);