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_byte_array_fast(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 + array_capacity(relocation));
21 iter(*rel,index,compiled);
23 switch(REL_TYPE(*rel))
40 critical_error("Bad rel type",*rel);
41 return; /* Can't happen */
49 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
50 INLINE void store_address_2_2(CELL cell, CELL value)
52 put(cell - CELLS,((get(cell - CELLS) & ~0xffff) | ((value >> 16) & 0xffff)));
53 put(cell,((get(cell) & ~0xffff) | (value & 0xffff)));
56 /* Store a value into a bitfield of a PowerPC instruction */
57 INLINE void store_address_masked(CELL cell, F_FIXNUM value, CELL mask, F_FIXNUM shift)
59 /* This is unaccurate but good enough */
60 F_FIXNUM test = (F_FIXNUM)mask >> 1;
61 if(value <= -test || value >= test)
62 critical_error("Value does not fit inside relocation",0);
64 u32 original = *(u32*)cell;
66 *(u32*)cell = (original | ((value >> shift) & mask));
69 /* Perform a fixup on a code block */
70 void store_address_in_code_block(CELL klass, CELL offset, F_FIXNUM absolute_value)
72 F_FIXNUM relative_value = absolute_value - offset;
76 case RC_ABSOLUTE_CELL:
77 put(offset,absolute_value);
80 *(u32*)offset = absolute_value;
83 *(u32*)offset = relative_value - sizeof(u32);
85 case RC_ABSOLUTE_PPC_2_2:
86 store_address_2_2(offset,absolute_value);
88 case RC_RELATIVE_PPC_2:
89 store_address_masked(offset,relative_value,REL_RELATIVE_PPC_2_MASK,0);
91 case RC_RELATIVE_PPC_3:
92 store_address_masked(offset,relative_value,REL_RELATIVE_PPC_3_MASK,0);
94 case RC_RELATIVE_ARM_3:
95 store_address_masked(offset,relative_value - CELLS * 2,
96 REL_RELATIVE_ARM_3_MASK,2);
99 store_address_masked(offset,relative_value - CELLS,
100 REL_INDIRECT_ARM_MASK,0);
102 case RC_INDIRECT_ARM_PC:
103 store_address_masked(offset,relative_value - CELLS * 2,
104 REL_INDIRECT_ARM_MASK,0);
107 critical_error("Bad rel class",klass);
112 void update_literal_references_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
114 if(REL_TYPE(rel) == RT_IMMEDIATE)
116 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
117 F_ARRAY *literals = untag_array_fast(compiled->literals);
118 F_FIXNUM absolute_value = array_nth(literals,index);
119 store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
123 /* Update pointers to literals from compiled code. */
124 void update_literal_references(F_CODE_BLOCK *compiled)
126 iterate_relocations(compiled,update_literal_references_step);
127 flush_icache_for(compiled);
130 /* Copy all literals referenced from a code block to newspace. Only for
131 aging and nursery collections */
132 void copy_literal_references(F_CODE_BLOCK *compiled)
134 if(collecting_gen >= compiled->block.last_scan)
136 if(collecting_accumulation_gen_p())
137 compiled->block.last_scan = collecting_gen;
139 compiled->block.last_scan = collecting_gen + 1;
141 /* initialize chase pointer */
142 CELL scan = newspace->here;
144 copy_handle(&compiled->literals);
145 copy_handle(&compiled->relocation);
147 /* do some tracing so that all reachable literals are now
148 at their final address */
149 copy_reachable_objects(scan,&newspace->here);
151 update_literal_references(compiled);
155 CELL object_xt(CELL obj)
157 if(TAG(obj) == QUOTATION_TYPE)
159 F_QUOTATION *quot = untag_quotation_fast(obj);
160 return (CELL)quot->xt;
164 F_WORD *word = untag_word_fast(obj);
165 return (CELL)word->xt;
169 CELL word_direct_xt(CELL obj)
171 F_WORD *word = untag_word_fast(obj);
172 CELL quot = word->direct_entry_def;
173 if(quot == F || max_pic_size == 0)
174 return (CELL)word->xt;
177 F_QUOTATION *untagged = untag_quotation_fast(quot);
178 if(untagged->compiledp == F)
179 return (CELL)word->xt;
181 return (CELL)untagged->xt;
185 void update_word_references_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
187 F_RELTYPE type = REL_TYPE(rel);
188 if(type == RT_XT || type == RT_XT_DIRECT)
190 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
191 F_ARRAY *literals = untag_array_fast(compiled->literals);
192 CELL obj = array_nth(literals,index);
198 xt = word_direct_xt(obj);
200 store_address_in_code_block(REL_CLASS(rel),offset,xt);
204 /* Relocate new code blocks completely; updating references to literals,
205 dlsyms, and words. For all other words in the code heap, we only need
206 to update references to other words, without worrying about literals
208 void update_word_references(F_CODE_BLOCK *compiled)
210 if(compiled->block.needs_fixup)
211 relocate_code_block(compiled);
212 /* update_word_references() is always applied to every block in
213 the code heap. Since it resets all call sites to point to
214 their canonical XT (cold entry point for non-tail calls,
215 standard entry point for tail calls), it means that no PICs
216 are referenced after this is done. So instead of polluting
217 the code heap with dead PICs that will be freed on the next
218 GC, we add them to the free list immediately. */
219 else if(compiled->block.type == PIC_TYPE)
222 heap_free(&code_heap,&compiled->block);
226 iterate_relocations(compiled,update_word_references_step);
227 flush_icache_for(compiled);
231 void update_literal_and_word_references(F_CODE_BLOCK *compiled)
233 update_literal_references(compiled);
234 update_word_references(compiled);
237 INLINE void check_code_address(CELL address)
240 assert(address >= code_heap.segment->start && address < code_heap.segment->end);
244 /* Update references to words. This is done after a new code block
245 is added to the heap. */
247 /* Mark all literals referenced from a word XT. Only for tenured
249 void mark_code_block(F_CODE_BLOCK *compiled)
251 check_code_address((CELL)compiled);
253 mark_block(&compiled->block);
255 copy_handle(&compiled->literals);
256 copy_handle(&compiled->relocation);
259 void mark_stack_frame_step(F_STACK_FRAME *frame)
261 mark_code_block(frame_code(frame));
264 /* Mark code blocks executing in currently active stack frames. */
265 void mark_active_blocks(F_CONTEXT *stacks)
267 if(collecting_gen == TENURED)
269 CELL top = (CELL)stacks->callstack_top;
270 CELL bottom = (CELL)stacks->callstack_bottom;
272 iterate_callstack(top,bottom,mark_stack_frame_step);
276 void mark_object_code_block(CELL scan)
285 word = (F_WORD *)scan;
287 mark_code_block(word->code);
289 mark_code_block(word->profiling);
292 quot = (F_QUOTATION *)scan;
293 if(quot->compiledp != F)
294 mark_code_block(quot->code);
297 stack = (F_CALLSTACK *)scan;
298 iterate_callstack_object(stack,mark_stack_frame_step);
303 /* References to undefined symbols are patched up to call this function on
305 void undefined_symbol(void)
307 general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL);
310 /* Look up an external library symbol referenced by a compiled code block */
311 void *get_rel_symbol(F_ARRAY *literals, CELL index)
313 CELL symbol = array_nth(literals,index);
314 CELL library = array_nth(literals,index + 1);
316 F_DLL *dll = (library == F ? NULL : untag_dll(library));
318 if(dll != NULL && !dll->dll)
319 return (void *)undefined_symbol;
321 if(type_of(symbol) == BYTE_ARRAY_TYPE)
323 F_SYMBOL *name = alien_offset(symbol);
324 void *sym = ffi_dlsym(dll,name);
329 else if(type_of(symbol) == ARRAY_TYPE)
332 F_ARRAY *names = untag_array_fast(symbol);
333 for(i = 0; i < array_capacity(names); i++)
335 F_SYMBOL *name = alien_offset(array_nth(names,i));
336 void *sym = ffi_dlsym(dll,name);
343 return (void *)undefined_symbol;
346 /* Compute an address to store at a relocation */
347 void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
350 type_check(ARRAY_TYPE,compiled->literals);
351 type_check(BYTE_ARRAY_TYPE,compiled->relocation);
354 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
355 F_ARRAY *literals = untag_array_fast(compiled->literals);
356 F_FIXNUM absolute_value;
358 switch(REL_TYPE(rel))
361 absolute_value = (CELL)primitives[to_fixnum(array_nth(literals,index))];
364 absolute_value = (CELL)get_rel_symbol(literals,index);
367 absolute_value = array_nth(literals,index);
370 absolute_value = object_xt(array_nth(literals,index));
373 absolute_value = word_direct_xt(array_nth(literals,index));
376 absolute_value = offset + (short)to_fixnum(array_nth(literals,index));
379 absolute_value = (CELL)(compiled + 1);
382 absolute_value = (CELL)&stack_chain;
385 absolute_value = to_fixnum(array_nth(literals,index));
388 critical_error("Bad rel type",rel);
389 return; /* Can't happen */
392 store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
395 /* Perform all fixups on a code block */
396 void relocate_code_block(F_CODE_BLOCK *compiled)
398 compiled->block.last_scan = NURSERY;
399 compiled->block.needs_fixup = false;
400 iterate_relocations(compiled,relocate_code_block_step);
401 flush_icache_for(compiled);
404 /* Fixup labels. This is done at compile time, not image load time */
405 void fixup_labels(F_ARRAY *labels, F_CODE_BLOCK *compiled)
408 CELL size = array_capacity(labels);
410 for(i = 0; i < size; i += 3)
412 CELL klass = to_fixnum(array_nth(labels,i));
413 CELL offset = to_fixnum(array_nth(labels,i + 1));
414 CELL target = to_fixnum(array_nth(labels,i + 2));
416 store_address_in_code_block(klass,
417 offset + (CELL)(compiled + 1),
418 target + (CELL)(compiled + 1));
423 F_CODE_BLOCK *allot_code_block(CELL size)
425 F_BLOCK *block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
427 /* If allocation failed, do a code GC */
431 block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
433 /* Insufficient room even after code GC, give up */
436 CELL used, total_free, max_free;
437 heap_usage(&code_heap,&used,&total_free,&max_free);
439 print_string("Code heap stats:\n");
440 print_string("Used: "); print_cell(used); nl();
441 print_string("Total free space: "); print_cell(total_free); nl();
442 print_string("Largest free block: "); print_cell(max_free); nl();
443 fatal_error("Out of memory in add-compiled-block",0);
447 return (F_CODE_BLOCK *)block;
451 F_CODE_BLOCK *add_code_block(
458 gc_root<F_BYTE_ARRAY> code(code_);
459 gc_root<F_OBJECT> labels(labels_);
460 gc_root<F_BYTE_ARRAY> relocation(relocation_);
461 gc_root<F_ARRAY> literals(literals_);
463 CELL code_length = align8(array_capacity(code.untagged()));
464 F_CODE_BLOCK *compiled = allot_code_block(code_length);
466 /* compiled header */
467 compiled->block.type = type;
468 compiled->block.last_scan = NURSERY;
469 compiled->block.needs_fixup = true;
470 compiled->relocation = relocation.value();
472 /* slight space optimization */
473 if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
474 compiled->literals = F;
476 compiled->literals = literals.value();
479 memcpy(compiled + 1,code.untagged() + 1,code_length);
482 if(labels.value() != F)
483 fixup_labels(labels.as<F_ARRAY>().untagged(),compiled);
485 /* next time we do a minor GC, we have to scan the code heap for
487 last_code_heap_scan = NURSERY;