3 void flush_icache_for(F_CODE_BLOCK
*compiled
)
5 CELL start
= (CELL
)(compiled
+ 1);
6 flush_icache(start
,compiled
->code_length
);
9 void iterate_relocations(F_CODE_BLOCK
*compiled
, RELOCATION_ITERATOR iter
)
11 if(compiled
->relocation
!= F
)
13 F_BYTE_ARRAY
*relocation
= untag_object(compiled
->relocation
);
15 F_REL
*rel
= (F_REL
*)(relocation
+ 1);
16 F_REL
*rel_end
= (F_REL
*)((char *)rel
+ byte_array_capacity(relocation
));
26 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
27 INLINE
void store_address_2_2(CELL cell
, CELL value
)
29 put(cell
- CELLS
,((get(cell
- CELLS
) & ~0xffff) | ((value
>> 16) & 0xffff)));
30 put(cell
,((get(cell
) & ~0xffff) | (value
& 0xffff)));
33 /* Store a value into a bitfield of a PowerPC instruction */
34 INLINE
void store_address_masked(CELL cell
, F_FIXNUM value
, CELL mask
, F_FIXNUM shift
)
36 /* This is unaccurate but good enough */
37 F_FIXNUM test
= (F_FIXNUM
)mask
>> 1;
38 if(value
<= -test
|| value
>= test
)
39 critical_error("Value does not fit inside relocation",0);
41 u32 original
= *(u32
*)cell
;
43 *(u32
*)cell
= (original
| ((value
>> shift
) & mask
));
46 /* Perform a fixup on a code block */
47 void store_address_in_code_block(CELL
class, CELL offset
, F_FIXNUM absolute_value
)
49 F_FIXNUM relative_value
= absolute_value
- offset
;
53 case RC_ABSOLUTE_CELL
:
54 put(offset
,absolute_value
);
57 *(u32
*)offset
= absolute_value
;
60 *(u32
*)offset
= relative_value
- sizeof(u32
);
62 case RC_ABSOLUTE_PPC_2_2
:
63 store_address_2_2(offset
,absolute_value
);
65 case RC_RELATIVE_PPC_2
:
66 store_address_masked(offset
,relative_value
,REL_RELATIVE_PPC_2_MASK
,0);
68 case RC_RELATIVE_PPC_3
:
69 store_address_masked(offset
,relative_value
,REL_RELATIVE_PPC_3_MASK
,0);
71 case RC_RELATIVE_ARM_3
:
72 store_address_masked(offset
,relative_value
- CELLS
* 2,
73 REL_RELATIVE_ARM_3_MASK
,2);
76 store_address_masked(offset
,relative_value
- CELLS
,
77 REL_INDIRECT_ARM_MASK
,0);
79 case RC_INDIRECT_ARM_PC
:
80 store_address_masked(offset
,relative_value
- CELLS
* 2,
81 REL_INDIRECT_ARM_MASK
,0);
84 critical_error("Bad rel class",class);
89 void update_literal_references_step(F_REL
*rel
, F_CODE_BLOCK
*compiled
)
91 if(REL_TYPE(rel
) == RT_IMMEDIATE
)
93 CELL offset
= rel
->offset
+ (CELL
)(compiled
+ 1);
94 F_ARRAY
*literals
= untag_object(compiled
->literals
);
95 F_FIXNUM absolute_value
= array_nth(literals
,REL_ARGUMENT(rel
));
96 store_address_in_code_block(REL_CLASS(rel
),offset
,absolute_value
);
100 /* Update pointers to literals from compiled code. */
101 void update_literal_references(F_CODE_BLOCK
*compiled
)
103 iterate_relocations(compiled
,update_literal_references_step
);
104 flush_icache_for(compiled
);
107 /* Copy all literals referenced from a code block to newspace. Only for
108 aging and nursery collections */
109 void copy_literal_references(F_CODE_BLOCK
*compiled
)
111 if(collecting_gen
>= compiled
->last_scan
)
113 if(collecting_accumulation_gen_p())
114 compiled
->last_scan
= collecting_gen
;
116 compiled
->last_scan
= collecting_gen
+ 1;
118 /* initialize chase pointer */
119 CELL scan
= newspace
->here
;
121 copy_handle(&compiled
->literals
);
122 copy_handle(&compiled
->relocation
);
124 /* do some tracing so that all reachable literals are now
125 at their final address */
126 copy_reachable_objects(scan
,&newspace
->here
);
128 update_literal_references(compiled
);
132 CELL
object_xt(CELL obj
)
134 if(type_of(obj
) == WORD_TYPE
)
135 return (CELL
)untag_word(obj
)->xt
;
137 return (CELL
)untag_quotation(obj
)->xt
;
140 void update_word_references_step(F_REL
*rel
, F_CODE_BLOCK
*compiled
)
142 if(REL_TYPE(rel
) == RT_XT
)
144 CELL offset
= rel
->offset
+ (CELL
)(compiled
+ 1);
145 F_ARRAY
*literals
= untag_object(compiled
->literals
);
146 CELL xt
= object_xt(array_nth(literals
,REL_ARGUMENT(rel
)));
147 store_address_in_code_block(REL_CLASS(rel
),offset
,xt
);
151 /* Relocate new code blocks completely; updating references to literals,
152 dlsyms, and words. For all other words in the code heap, we only need
153 to update references to other words, without worrying about literals
155 void update_word_references(F_CODE_BLOCK
*compiled
)
157 if(compiled
->needs_fixup
)
158 relocate_code_block(compiled
);
161 iterate_relocations(compiled
,update_word_references_step
);
162 flush_icache_for(compiled
);
166 /* Update references to words. This is done after a new code block
167 is added to the heap. */
169 /* Mark all literals referenced from a word XT. Only for tenured
171 void mark_code_block(F_CODE_BLOCK
*compiled
)
173 mark_block(compiled_to_block(compiled
));
175 copy_handle(&compiled
->literals
);
176 copy_handle(&compiled
->relocation
);
178 flush_icache_for(compiled
);
181 /* References to undefined symbols are patched up to call this function on
183 void undefined_symbol(void)
185 general_error(ERROR_UNDEFINED_SYMBOL
,F
,F
,NULL
);
188 /* Look up an external library symbol referenced by a compiled code block */
189 void *get_rel_symbol(F_REL
*rel
, F_ARRAY
*literals
)
191 CELL arg
= REL_ARGUMENT(rel
);
192 CELL symbol
= array_nth(literals
,arg
);
193 CELL library
= array_nth(literals
,arg
+ 1);
195 F_DLL
*dll
= (library
== F
? NULL
: untag_dll(library
));
197 if(dll
!= NULL
&& !dll
->dll
)
198 return undefined_symbol
;
200 if(type_of(symbol
) == BYTE_ARRAY_TYPE
)
202 F_SYMBOL
*name
= alien_offset(symbol
);
203 void *sym
= ffi_dlsym(dll
,name
);
208 else if(type_of(symbol
) == ARRAY_TYPE
)
211 F_ARRAY
*names
= untag_object(symbol
);
212 for(i
= 0; i
< array_capacity(names
); i
++)
214 F_SYMBOL
*name
= alien_offset(array_nth(names
,i
));
215 void *sym
= ffi_dlsym(dll
,name
);
222 return undefined_symbol
;
225 /* Compute an address to store at a relocation */
226 void relocate_code_block_step(F_REL
*rel
, F_CODE_BLOCK
*compiled
)
228 CELL offset
= rel
->offset
+ (CELL
)(compiled
+ 1);
229 F_ARRAY
*literals
= untag_object(compiled
->literals
);
230 F_FIXNUM absolute_value
;
232 switch(REL_TYPE(rel
))
235 absolute_value
= (CELL
)primitives
[REL_ARGUMENT(rel
)];
238 absolute_value
= (CELL
)get_rel_symbol(rel
,literals
);
241 absolute_value
= array_nth(literals
,REL_ARGUMENT(rel
));
244 absolute_value
= object_xt(array_nth(literals
,REL_ARGUMENT(rel
)));
247 absolute_value
= rel
->offset
+ (CELL
)(compiled
+ 1) + (short)REL_ARGUMENT(rel
);
250 absolute_value
= (CELL
)(compiled
+ 1) + REL_ARGUMENT(rel
);
253 absolute_value
= (CELL
)&stack_chain
;
256 critical_error("Bad rel type",rel
->type
);
257 return; /* Can't happen */
260 store_address_in_code_block(REL_CLASS(rel
),offset
,absolute_value
);
263 /* Perform all fixups on a code block */
264 void relocate_code_block(F_CODE_BLOCK
*compiled
)
266 compiled
->last_scan
= NURSERY
;
267 compiled
->needs_fixup
= false;
268 iterate_relocations(compiled
,relocate_code_block_step
);
269 flush_icache_for(compiled
);
272 /* Fixup labels. This is done at compile time, not image load time */
273 void fixup_labels(F_ARRAY
*labels
, CELL code_format
, F_CODE_BLOCK
*compiled
)
276 CELL size
= array_capacity(labels
);
278 for(i
= 0; i
< size
; i
+= 3)
280 CELL
class = to_fixnum(array_nth(labels
,i
));
281 CELL offset
= to_fixnum(array_nth(labels
,i
+ 1));
282 CELL target
= to_fixnum(array_nth(labels
,i
+ 2));
284 store_address_in_code_block(class,
285 offset
+ (CELL
)(compiled
+ 1),
286 target
+ (CELL
)(compiled
+ 1));
290 /* Write a sequence of integers to memory, with 'format' bytes per integer */
291 void deposit_integers(CELL here
, F_ARRAY
*array
, CELL format
)
293 CELL count
= array_capacity(array
);
296 for(i
= 0; i
< count
; i
++)
298 F_FIXNUM value
= to_fixnum(array_nth(array
,i
));
300 bput(here
+ i
,value
);
301 else if(format
== sizeof(unsigned int))
302 *(unsigned int *)(here
+ format
* i
) = value
;
303 else if(format
== sizeof(CELL
))
304 *(CELL
*)(here
+ format
* i
) = value
;
306 critical_error("Bad format in deposit_integers()",format
);
310 bool stack_traces_p(void)
312 return to_boolean(userenv
[STACK_TRACES_ENV
]);
315 CELL
compiled_code_format(void)
317 return untag_fixnum_fast(userenv
[JIT_CODE_FORMAT
]);
321 void *allot_code_block(CELL size
)
323 void *start
= heap_allot(&code_heap
,size
);
325 /* If allocation failed, do a code GC */
329 start
= heap_allot(&code_heap
,size
);
331 /* Insufficient room even after code GC, give up */
334 CELL used
, total_free
, max_free
;
335 heap_usage(&code_heap
,&used
,&total_free
,&max_free
);
337 print_string("Code heap stats:\n");
338 print_string("Used: "); print_cell(used
); nl();
339 print_string("Total free space: "); print_cell(total_free
); nl();
340 print_string("Largest free block: "); print_cell(max_free
); nl();
341 fatal_error("Out of memory in add-compiled-block",0);
349 F_CODE_BLOCK
*add_compiled_block(
356 CELL code_format
= compiled_code_format();
357 CELL code_length
= align8(array_capacity(code
) * code_format
);
359 REGISTER_ROOT(literals
);
360 REGISTER_ROOT(relocation
);
361 REGISTER_UNTAGGED(code
);
362 REGISTER_UNTAGGED(labels
);
364 F_CODE_BLOCK
*compiled
= allot_code_block(sizeof(F_CODE_BLOCK
) + code_length
);
366 UNREGISTER_UNTAGGED(labels
);
367 UNREGISTER_UNTAGGED(code
);
368 UNREGISTER_ROOT(relocation
);
369 UNREGISTER_ROOT(literals
);
371 /* compiled header */
372 compiled
->type
= type
;
373 compiled
->last_scan
= NURSERY
;
374 compiled
->needs_fixup
= true;
375 compiled
->code_length
= code_length
;
376 compiled
->literals
= literals
;
377 compiled
->relocation
= relocation
;
380 deposit_integers((CELL
)(compiled
+ 1),code
,code_format
);
383 if(labels
) fixup_labels(labels
,code_format
,compiled
);
385 /* next time we do a minor GC, we have to scan the code heap for
387 last_code_heap_scan
= NURSERY
;