6 relocation_type factorvm::relocation_type_of(relocation_entry r)
8 return (relocation_type)((r & 0xf0000000) >> 28);
12 relocation_class factorvm::relocation_class_of(relocation_entry r)
14 return (relocation_class)((r & 0x0f000000) >> 24);
18 cell factorvm::relocation_offset_of(relocation_entry r)
20 return (r & 0x00ffffff);
24 void factorvm::flush_icache_for(code_block *block)
26 flush_icache((cell)block,block->size);
30 int factorvm::number_of_parameters(relocation_type type)
46 case RT_MEGAMORPHIC_CACHE_HITS:
50 critical_error("Bad rel type",type);
51 return -1; /* Can't happen */
56 void *factorvm::object_xt(cell obj)
58 switch(tagged<object>(obj).type())
61 return untag<word>(obj)->xt;
63 return untag<quotation>(obj)->xt;
65 critical_error("Expected word or quotation",obj);
71 void *factorvm::xt_pic(word *w, cell tagged_quot)
73 if(tagged_quot == F || max_pic_size == 0)
77 quotation *quot = untag<quotation>(tagged_quot);
86 void *factorvm::word_xt_pic(word *w)
88 return xt_pic(w,w->pic_def);
92 void *factorvm::word_xt_pic_tail(word *w)
94 return xt_pic(w,w->pic_tail_def);
98 /* References to undefined symbols are patched up to call this function on
100 void factorvm::undefined_symbol()
102 general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL);
105 void undefined_symbol(factorvm *myvm)
107 return myvm->undefined_symbol();
110 /* Look up an external library symbol referenced by a compiled code block */
111 void *factorvm::get_rel_symbol(array *literals, cell index)
113 cell symbol = array_nth(literals,index);
114 cell library = array_nth(literals,index + 1);
116 dll *d = (library == F ? NULL : untag<dll>(library));
118 if(d != NULL && !d->dll)
119 return (void *)factor::undefined_symbol;
121 switch(tagged<object>(symbol).type())
123 case BYTE_ARRAY_TYPE:
125 symbol_char *name = alien_offset(symbol);
126 void *sym = ffi_dlsym(d,name);
132 return (void *)factor::undefined_symbol;
138 array *names = untag<array>(symbol);
139 for(i = 0; i < array_capacity(names); i++)
141 symbol_char *name = alien_offset(array_nth(names,i));
142 void *sym = ffi_dlsym(d,name);
147 return (void *)factor::undefined_symbol;
150 critical_error("Bad symbol specifier",symbol);
151 return (void *)factor::undefined_symbol;
156 cell factorvm::compute_relocation(relocation_entry rel, cell index, code_block *compiled)
158 array *literals = untag<array>(compiled->literals);
159 cell offset = relocation_offset_of(rel) + (cell)compiled->xt();
161 #define ARG array_nth(literals,index)
163 switch(relocation_type_of(rel))
166 return (cell)primitives[untag_fixnum(ARG)];
168 return (cell)get_rel_symbol(literals,index);
172 return (cell)object_xt(ARG);
174 return (cell)word_xt_pic(untag<word>(ARG));
176 return (cell)word_xt_pic_tail(untag<word>(ARG));
179 fixnum arg = untag_fixnum(ARG);
180 return (arg >= 0 ? offset + arg : (cell)(compiled +1) - arg);
183 return (cell)(compiled + 1);
185 return (cell)&stack_chain;
187 return untag_fixnum(ARG);
188 case RT_MEGAMORPHIC_CACHE_HITS:
189 return (cell)&megamorphic_cache_hits;
193 critical_error("Bad rel type",rel);
194 return 0; /* Can't happen */
201 void factorvm::iterate_relocations(code_block *compiled, relocation_iterator iter)
203 if(compiled->relocation != F)
205 byte_array *relocation = untag<byte_array>(compiled->relocation);
207 cell index = stack_traces_p() ? 1 : 0;
209 cell length = array_capacity(relocation) / sizeof(relocation_entry);
210 for(cell i = 0; i < length; i++)
212 relocation_entry rel = relocation->data<relocation_entry>()[i];
213 iter(rel,index,compiled,this);
214 index += number_of_parameters(relocation_type_of(rel));
220 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
221 void factorvm::store_address_2_2(cell *ptr, cell value)
223 ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
224 ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
228 /* Store a value into a bitfield of a PowerPC instruction */
229 void factorvm::store_address_masked(cell *ptr, fixnum value, cell mask, fixnum shift)
231 /* This is unaccurate but good enough */
232 fixnum test = (fixnum)mask >> 1;
233 if(value <= -test || value >= test)
234 critical_error("Value does not fit inside relocation",0);
236 *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
240 /* Perform a fixup on a code block */
241 void factorvm::store_address_in_code_block(cell klass, cell offset, fixnum absolute_value)
243 fixnum relative_value = absolute_value - offset;
247 case RC_ABSOLUTE_CELL:
248 *(cell *)offset = absolute_value;
251 *(u32*)offset = absolute_value;
254 *(u32*)offset = relative_value - sizeof(u32);
256 case RC_ABSOLUTE_PPC_2_2:
257 store_address_2_2((cell *)offset,absolute_value);
259 case RC_ABSOLUTE_PPC_2:
260 store_address_masked((cell *)offset,absolute_value,rel_absolute_ppc_2_mask,0);
262 case RC_RELATIVE_PPC_2:
263 store_address_masked((cell *)offset,relative_value,rel_relative_ppc_2_mask,0);
265 case RC_RELATIVE_PPC_3:
266 store_address_masked((cell *)offset,relative_value,rel_relative_ppc_3_mask,0);
268 case RC_RELATIVE_ARM_3:
269 store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
270 rel_relative_arm_3_mask,2);
272 case RC_INDIRECT_ARM:
273 store_address_masked((cell *)offset,relative_value - sizeof(cell),
274 rel_indirect_arm_mask,0);
276 case RC_INDIRECT_ARM_PC:
277 store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
278 rel_indirect_arm_mask,0);
281 critical_error("Bad rel class",klass);
287 void factorvm::update_literal_references_step(relocation_entry rel, cell index, code_block *compiled)
289 if(relocation_type_of(rel) == RT_IMMEDIATE)
291 cell offset = relocation_offset_of(rel) + (cell)(compiled + 1);
292 array *literals = untag<array>(compiled->literals);
293 fixnum absolute_value = array_nth(literals,index);
294 store_address_in_code_block(relocation_class_of(rel),offset,absolute_value);
298 void update_literal_references_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
300 return myvm->update_literal_references_step(rel,index,compiled);
303 /* Update pointers to literals from compiled code. */
304 void factorvm::update_literal_references(code_block *compiled)
306 if(!compiled->needs_fixup)
308 iterate_relocations(compiled,factor::update_literal_references_step);
309 flush_icache_for(compiled);
314 /* Copy all literals referenced from a code block to newspace. Only for
315 aging and nursery collections */
316 void factorvm::copy_literal_references(code_block *compiled)
318 if(collecting_gen >= compiled->last_scan)
320 if(collecting_accumulation_gen_p())
321 compiled->last_scan = collecting_gen;
323 compiled->last_scan = collecting_gen + 1;
325 /* initialize chase pointer */
326 cell scan = newspace->here;
328 copy_handle(&compiled->literals);
329 copy_handle(&compiled->relocation);
331 /* do some tracing so that all reachable literals are now
332 at their final address */
333 copy_reachable_objects(scan,&newspace->here);
335 update_literal_references(compiled);
339 void copy_literal_references(code_block *compiled, factorvm *myvm)
341 return myvm->copy_literal_references(compiled);
344 /* Compute an address to store at a relocation */
345 void factorvm::relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled)
348 tagged<array>(compiled->literals).untag_check(this);
349 tagged<byte_array>(compiled->relocation).untag_check(this);
352 store_address_in_code_block(relocation_class_of(rel),
353 relocation_offset_of(rel) + (cell)compiled->xt(),
354 compute_relocation(rel,index,compiled));
357 void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
359 return myvm->relocate_code_block_step(rel,index,compiled);
362 void factorvm::update_word_references_step(relocation_entry rel, cell index, code_block *compiled)
364 relocation_type type = relocation_type_of(rel);
365 if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
366 relocate_code_block_step(rel,index,compiled);
369 void update_word_references_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
371 return myvm->update_word_references_step(rel,index,compiled);
374 /* Relocate new code blocks completely; updating references to literals,
375 dlsyms, and words. For all other words in the code heap, we only need
376 to update references to other words, without worrying about literals
378 void factorvm::update_word_references(code_block *compiled)
380 if(compiled->needs_fixup)
381 relocate_code_block(compiled);
382 /* update_word_references() is always applied to every block in
383 the code heap. Since it resets all call sites to point to
384 their canonical XT (cold entry point for non-tail calls,
385 standard entry point for tail calls), it means that no PICs
386 are referenced after this is done. So instead of polluting
387 the code heap with dead PICs that will be freed on the next
388 GC, we add them to the free list immediately. */
389 else if(compiled->type == PIC_TYPE)
390 heap_free(&code,compiled);
393 iterate_relocations(compiled,factor::update_word_references_step);
394 flush_icache_for(compiled);
398 void update_word_references(code_block *compiled, factorvm *myvm)
400 return myvm->update_word_references(compiled);
403 void factorvm::update_literal_and_word_references(code_block *compiled)
405 update_literal_references(compiled);
406 update_word_references(compiled);
409 void update_literal_and_word_references(code_block *compiled, factorvm *myvm)
411 return myvm->update_literal_and_word_references(compiled);
414 void factorvm::check_code_address(cell address)
417 assert(address >= code.seg->start && address < code.seg->end);
422 /* Update references to words. This is done after a new code block
423 is added to the heap. */
425 /* Mark all literals referenced from a word XT. Only for tenured
427 void factorvm::mark_code_block(code_block *compiled)
429 check_code_address((cell)compiled);
431 mark_block(compiled);
433 copy_handle(&compiled->literals);
434 copy_handle(&compiled->relocation);
438 void factorvm::mark_stack_frame_step(stack_frame *frame)
440 mark_code_block(frame_code(frame));
443 void mark_stack_frame_step(stack_frame *frame, factorvm *myvm)
445 return myvm->mark_stack_frame_step(frame);
448 /* Mark code blocks executing in currently active stack frames. */
449 void factorvm::mark_active_blocks(context *stacks)
451 if(collecting_gen == data->tenured())
453 cell top = (cell)stacks->callstack_top;
454 cell bottom = (cell)stacks->callstack_bottom;
456 iterate_callstack(top,bottom,factor::mark_stack_frame_step);
461 void factorvm::mark_object_code_block(object *object)
463 switch(object->h.hi_tag())
467 word *w = (word *)object;
469 mark_code_block(w->code);
471 mark_code_block(w->profiling);
476 quotation *q = (quotation *)object;
478 mark_code_block(q->code);
483 callstack *stack = (callstack *)object;
484 iterate_callstack_object(stack,factor::mark_stack_frame_step);
491 /* Perform all fixups on a code block */
492 void factorvm::relocate_code_block(code_block *compiled)
494 compiled->last_scan = data->nursery();
495 compiled->needs_fixup = false;
496 iterate_relocations(compiled,factor::relocate_code_block_step);
497 flush_icache_for(compiled);
500 void relocate_code_block(code_block *compiled, factorvm *myvm)
502 return myvm->relocate_code_block(compiled);
505 /* Fixup labels. This is done at compile time, not image load time */
506 void factorvm::fixup_labels(array *labels, code_block *compiled)
509 cell size = array_capacity(labels);
511 for(i = 0; i < size; i += 3)
513 cell klass = untag_fixnum(array_nth(labels,i));
514 cell offset = untag_fixnum(array_nth(labels,i + 1));
515 cell target = untag_fixnum(array_nth(labels,i + 2));
517 store_address_in_code_block(klass,
518 offset + (cell)(compiled + 1),
519 target + (cell)(compiled + 1));
525 code_block *factorvm::allot_code_block(cell size)
527 heap_block *block = heap_allot(&code,size + sizeof(code_block));
529 /* If allocation failed, do a code GC */
533 block = heap_allot(&code,size + sizeof(code_block));
535 /* Insufficient room even after code GC, give up */
538 cell used, total_free, max_free;
539 heap_usage(&code,&used,&total_free,&max_free);
541 print_string("Code heap stats:\n");
542 print_string("Used: "); print_cell(used); nl();
543 print_string("Total free space: "); print_cell(total_free); nl();
544 print_string("Largest free block: "); print_cell(max_free); nl();
545 fatal_error("Out of memory in add-compiled-block",0);
549 return (code_block *)block;
554 code_block *factorvm::add_code_block(cell type,cell code_,cell labels_,cell relocation_,cell literals_)
556 gc_root<byte_array> code(code_,this);
557 gc_root<object> labels(labels_,this);
558 gc_root<byte_array> relocation(relocation_,this);
559 gc_root<array> literals(literals_,this);
561 cell code_length = align8(array_capacity(code.untagged()));
562 code_block *compiled = allot_code_block(code_length);
564 /* compiled header */
565 compiled->type = type;
566 compiled->last_scan = data->nursery();
567 compiled->needs_fixup = true;
568 compiled->relocation = relocation.value();
570 /* slight space optimization */
571 if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
572 compiled->literals = F;
574 compiled->literals = literals.value();
577 memcpy(compiled + 1,code.untagged() + 1,code_length);
580 if(labels.value() != F)
581 fixup_labels(labels.as<array>().untagged(),compiled);
583 /* next time we do a minor GC, we have to scan the code heap for
585 last_code_heap_scan = data->nursery();