3 void flush_icache_for(F_CODE_BLOCK *block)
5 flush_icache((CELL)block,block->block.size);
8 void iterate_relocations(F_CODE_BLOCK *compiled, RELOCATION_ITERATOR iter)
10 if(compiled->relocation != F)
12 F_BYTE_ARRAY *relocation = untag_object(compiled->relocation);
14 CELL index = stack_traces_p() ? 1 : 0;
16 F_REL *rel = (F_REL *)(relocation + 1);
17 F_REL *rel_end = (F_REL *)((char *)rel + byte_array_capacity(relocation));
21 iter(*rel,index,compiled);
23 switch(REL_TYPE(*rel))
38 critical_error("Bad rel type",*rel);
39 return; /* Can't happen */
47 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
48 INLINE void store_address_2_2(CELL cell, CELL value)
50 put(cell - CELLS,((get(cell - CELLS) & ~0xffff) | ((value >> 16) & 0xffff)));
51 put(cell,((get(cell) & ~0xffff) | (value & 0xffff)));
54 /* Store a value into a bitfield of a PowerPC instruction */
55 INLINE void store_address_masked(CELL cell, F_FIXNUM value, CELL mask, F_FIXNUM shift)
57 /* This is unaccurate but good enough */
58 F_FIXNUM test = (F_FIXNUM)mask >> 1;
59 if(value <= -test || value >= test)
60 critical_error("Value does not fit inside relocation",0);
62 u32 original = *(u32*)cell;
64 *(u32*)cell = (original | ((value >> shift) & mask));
67 /* Perform a fixup on a code block */
68 void store_address_in_code_block(CELL class, CELL offset, F_FIXNUM absolute_value)
70 F_FIXNUM relative_value = absolute_value - offset;
74 case RC_ABSOLUTE_CELL:
75 put(offset,absolute_value);
78 *(u32*)offset = absolute_value;
81 *(u32*)offset = relative_value - sizeof(u32);
83 case RC_ABSOLUTE_PPC_2_2:
84 store_address_2_2(offset,absolute_value);
86 case RC_RELATIVE_PPC_2:
87 store_address_masked(offset,relative_value,REL_RELATIVE_PPC_2_MASK,0);
89 case RC_RELATIVE_PPC_3:
90 store_address_masked(offset,relative_value,REL_RELATIVE_PPC_3_MASK,0);
92 case RC_RELATIVE_ARM_3:
93 store_address_masked(offset,relative_value - CELLS * 2,
94 REL_RELATIVE_ARM_3_MASK,2);
97 store_address_masked(offset,relative_value - CELLS,
98 REL_INDIRECT_ARM_MASK,0);
100 case RC_INDIRECT_ARM_PC:
101 store_address_masked(offset,relative_value - CELLS * 2,
102 REL_INDIRECT_ARM_MASK,0);
105 critical_error("Bad rel class",class);
110 void update_literal_references_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
112 if(REL_TYPE(rel) == RT_IMMEDIATE)
114 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
115 F_ARRAY *literals = untag_object(compiled->literals);
116 F_FIXNUM absolute_value = array_nth(literals,index);
117 store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
121 /* Update pointers to literals from compiled code. */
122 void update_literal_references(F_CODE_BLOCK *compiled)
124 iterate_relocations(compiled,update_literal_references_step);
125 flush_icache_for(compiled);
128 /* Copy all literals referenced from a code block to newspace. Only for
129 aging and nursery collections */
130 void copy_literal_references(F_CODE_BLOCK *compiled)
132 if(collecting_gen >= compiled->block.last_scan)
134 if(collecting_accumulation_gen_p())
135 compiled->block.last_scan = collecting_gen;
137 compiled->block.last_scan = collecting_gen + 1;
139 /* initialize chase pointer */
140 CELL scan = newspace->here;
142 copy_handle(&compiled->literals);
143 copy_handle(&compiled->relocation);
145 /* do some tracing so that all reachable literals are now
146 at their final address */
147 copy_reachable_objects(scan,&newspace->here);
149 update_literal_references(compiled);
153 CELL object_xt(CELL obj)
155 if(type_of(obj) == WORD_TYPE)
156 return (CELL)untag_word(obj)->xt;
158 return (CELL)untag_quotation(obj)->xt;
161 void update_word_references_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
163 if(REL_TYPE(rel) == RT_XT)
165 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
166 F_ARRAY *literals = untag_object(compiled->literals);
167 CELL xt = object_xt(array_nth(literals,index));
168 store_address_in_code_block(REL_CLASS(rel),offset,xt);
172 /* Relocate new code blocks completely; updating references to literals,
173 dlsyms, and words. For all other words in the code heap, we only need
174 to update references to other words, without worrying about literals
176 void update_word_references(F_CODE_BLOCK *compiled)
178 if(compiled->block.needs_fixup)
179 relocate_code_block(compiled);
182 iterate_relocations(compiled,update_word_references_step);
183 flush_icache_for(compiled);
187 /* Update references to words. This is done after a new code block
188 is added to the heap. */
190 /* Mark all literals referenced from a word XT. Only for tenured
192 void mark_code_block(F_CODE_BLOCK *compiled)
194 mark_block(&compiled->block);
196 copy_handle(&compiled->literals);
197 copy_handle(&compiled->relocation);
200 void mark_stack_frame_step(F_STACK_FRAME *frame)
202 mark_code_block(frame_code(frame));
205 /* Mark code blocks executing in currently active stack frames. */
206 void mark_active_blocks(F_CONTEXT *stacks)
208 if(collecting_gen == TENURED)
210 CELL top = (CELL)stacks->callstack_top;
211 CELL bottom = (CELL)stacks->callstack_bottom;
213 iterate_callstack(top,bottom,mark_stack_frame_step);
217 void mark_object_code_block(CELL scan)
226 word = (F_WORD *)scan;
228 mark_code_block(word->code);
230 mark_code_block(word->profiling);
233 quot = (F_QUOTATION *)scan;
234 if(quot->compiledp != F)
235 mark_code_block(quot->code);
238 stack = (F_CALLSTACK *)scan;
239 iterate_callstack_object(stack,mark_stack_frame_step);
244 /* References to undefined symbols are patched up to call this function on
246 void undefined_symbol(void)
248 general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL);
251 /* Look up an external library symbol referenced by a compiled code block */
252 void *get_rel_symbol(F_ARRAY *literals, CELL index)
254 CELL symbol = array_nth(literals,index);
255 CELL library = array_nth(literals,index + 1);
257 F_DLL *dll = (library == F ? NULL : untag_dll(library));
259 if(dll != NULL && !dll->dll)
260 return undefined_symbol;
262 if(type_of(symbol) == BYTE_ARRAY_TYPE)
264 F_SYMBOL *name = alien_offset(symbol);
265 void *sym = ffi_dlsym(dll,name);
270 else if(type_of(symbol) == ARRAY_TYPE)
273 F_ARRAY *names = untag_object(symbol);
274 for(i = 0; i < array_capacity(names); i++)
276 F_SYMBOL *name = alien_offset(array_nth(names,i));
277 void *sym = ffi_dlsym(dll,name);
284 return undefined_symbol;
287 /* Compute an address to store at a relocation */
288 void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
290 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
291 F_ARRAY *literals = untag_object(compiled->literals);
292 F_FIXNUM absolute_value;
294 switch(REL_TYPE(rel))
297 absolute_value = (CELL)primitives[to_fixnum(array_nth(literals,index))];
300 absolute_value = (CELL)get_rel_symbol(literals,index);
303 absolute_value = array_nth(literals,index);
306 absolute_value = object_xt(array_nth(literals,index));
309 absolute_value = offset + (short)to_fixnum(array_nth(literals,index));
312 absolute_value = (CELL)(compiled + 1);
315 absolute_value = (CELL)&stack_chain;
318 critical_error("Bad rel type",rel);
319 return; /* Can't happen */
322 store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
325 /* Perform all fixups on a code block */
326 void relocate_code_block(F_CODE_BLOCK *compiled)
328 compiled->block.last_scan = NURSERY;
329 compiled->block.needs_fixup = false;
330 iterate_relocations(compiled,relocate_code_block_step);
331 flush_icache_for(compiled);
334 /* Fixup labels. This is done at compile time, not image load time */
335 void fixup_labels(F_ARRAY *labels, CELL code_format, F_CODE_BLOCK *compiled)
338 CELL size = array_capacity(labels);
340 for(i = 0; i < size; i += 3)
342 CELL class = to_fixnum(array_nth(labels,i));
343 CELL offset = to_fixnum(array_nth(labels,i + 1));
344 CELL target = to_fixnum(array_nth(labels,i + 2));
346 store_address_in_code_block(class,
347 offset + (CELL)(compiled + 1),
348 target + (CELL)(compiled + 1));
352 /* Write a sequence of integers to memory, with 'format' bytes per integer */
353 void deposit_integers(CELL here, F_ARRAY *array, CELL format)
355 CELL count = array_capacity(array);
358 for(i = 0; i < count; i++)
360 F_FIXNUM value = to_fixnum(array_nth(array,i));
362 bput(here + i,value);
363 else if(format == sizeof(unsigned int))
364 *(unsigned int *)(here + format * i) = value;
365 else if(format == sizeof(CELL))
366 *(CELL *)(here + format * i) = value;
368 critical_error("Bad format in deposit_integers()",format);
372 CELL compiled_code_format(void)
374 return untag_fixnum_fast(userenv[JIT_CODE_FORMAT]);
378 F_CODE_BLOCK *allot_code_block(CELL size)
380 F_BLOCK *block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
382 /* If allocation failed, do a code GC */
386 block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
388 /* Insufficient room even after code GC, give up */
391 CELL used, total_free, max_free;
392 heap_usage(&code_heap,&used,&total_free,&max_free);
394 print_string("Code heap stats:\n");
395 print_string("Used: "); print_cell(used); nl();
396 print_string("Total free space: "); print_cell(total_free); nl();
397 print_string("Largest free block: "); print_cell(max_free); nl();
398 fatal_error("Out of memory in add-compiled-block",0);
402 return (F_CODE_BLOCK *)block;
406 F_CODE_BLOCK *add_code_block(
413 CELL code_format = compiled_code_format();
414 CELL code_length = align8(array_capacity(code) * code_format);
416 REGISTER_ROOT(literals);
417 REGISTER_ROOT(relocation);
418 REGISTER_UNTAGGED(code);
419 REGISTER_UNTAGGED(labels);
421 F_CODE_BLOCK *compiled = allot_code_block(code_length);
423 UNREGISTER_UNTAGGED(labels);
424 UNREGISTER_UNTAGGED(code);
425 UNREGISTER_ROOT(relocation);
426 UNREGISTER_ROOT(literals);
428 /* slight space optimization */
429 if(type_of(literals) == ARRAY_TYPE && array_capacity(untag_object(literals)) == 0)
432 /* compiled header */
433 compiled->block.type = type;
434 compiled->block.last_scan = NURSERY;
435 compiled->block.needs_fixup = true;
436 compiled->literals = literals;
437 compiled->relocation = relocation;
440 deposit_integers((CELL)(compiled + 1),code,code_format);
443 if(labels) fixup_labels(labels,code_format,compiled);
445 /* next time we do a minor GC, we have to scan the code heap for
447 last_code_heap_scan = NURSERY;