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);
344 print_obj(symbol); nl(); fflush(stdout);
347 return (void *)undefined_symbol;
350 /* Compute an address to store at a relocation */
351 void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
354 type_check(ARRAY_TYPE,compiled->literals);
355 type_check(BYTE_ARRAY_TYPE,compiled->relocation);
358 CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
359 F_ARRAY *literals = untag_array_fast(compiled->literals);
360 F_FIXNUM absolute_value;
362 switch(REL_TYPE(rel))
365 absolute_value = (CELL)primitives[to_fixnum(array_nth(literals,index))];
368 absolute_value = (CELL)get_rel_symbol(literals,index);
371 absolute_value = array_nth(literals,index);
374 absolute_value = object_xt(array_nth(literals,index));
377 absolute_value = word_direct_xt(array_nth(literals,index));
380 absolute_value = offset + (short)to_fixnum(array_nth(literals,index));
383 absolute_value = (CELL)(compiled + 1);
386 absolute_value = (CELL)&stack_chain;
389 absolute_value = to_fixnum(array_nth(literals,index));
392 critical_error("Bad rel type",rel);
393 return; /* Can't happen */
396 store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
399 /* Perform all fixups on a code block */
400 void relocate_code_block(F_CODE_BLOCK *compiled)
402 compiled->block.last_scan = NURSERY;
403 compiled->block.needs_fixup = false;
404 iterate_relocations(compiled,relocate_code_block_step);
405 flush_icache_for(compiled);
408 /* Fixup labels. This is done at compile time, not image load time */
409 void fixup_labels(F_ARRAY *labels, F_CODE_BLOCK *compiled)
412 CELL size = array_capacity(labels);
414 for(i = 0; i < size; i += 3)
416 CELL klass = to_fixnum(array_nth(labels,i));
417 CELL offset = to_fixnum(array_nth(labels,i + 1));
418 CELL target = to_fixnum(array_nth(labels,i + 2));
420 store_address_in_code_block(klass,
421 offset + (CELL)(compiled + 1),
422 target + (CELL)(compiled + 1));
427 F_CODE_BLOCK *allot_code_block(CELL size)
429 F_BLOCK *block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
431 /* If allocation failed, do a code GC */
435 block = heap_allot(&code_heap,size + sizeof(F_CODE_BLOCK));
437 /* Insufficient room even after code GC, give up */
440 CELL used, total_free, max_free;
441 heap_usage(&code_heap,&used,&total_free,&max_free);
443 print_string("Code heap stats:\n");
444 print_string("Used: "); print_cell(used); nl();
445 print_string("Total free space: "); print_cell(total_free); nl();
446 print_string("Largest free block: "); print_cell(max_free); nl();
447 fatal_error("Out of memory in add-compiled-block",0);
451 return (F_CODE_BLOCK *)block;
455 F_CODE_BLOCK *add_code_block(
462 gc_root<F_BYTE_ARRAY> code(code_);
463 gc_root<F_OBJECT> labels(labels_);
464 gc_root<F_BYTE_ARRAY> relocation(relocation_);
465 gc_root<F_ARRAY> literals(literals_);
467 CELL code_length = align8(array_capacity(code.untagged()));
468 F_CODE_BLOCK *compiled = allot_code_block(code_length);
470 /* compiled header */
471 compiled->block.type = type;
472 compiled->block.last_scan = NURSERY;
473 compiled->block.needs_fixup = true;
474 compiled->relocation = relocation.value();
476 /* slight space optimization */
477 if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
478 compiled->literals = F;
480 compiled->literals = literals.value();
483 memcpy(compiled + 1,code.untagged() + 1,code_length);
486 if(labels.value() != F)
487 fixup_labels(labels.as<F_ARRAY>().untagged(),compiled);
489 /* next time we do a minor GC, we have to scan the code heap for
491 last_code_heap_scan = NURSERY;