6 relocation_type factorvm::relocation_type_of(relocation_entry r)
8 return (relocation_type)((r & 0xf0000000) >> 28);
11 relocation_class factorvm::relocation_class_of(relocation_entry r)
13 return (relocation_class)((r & 0x0f000000) >> 24);
16 cell factorvm::relocation_offset_of(relocation_entry r)
18 return (r & 0x00ffffff);
21 void factorvm::flush_icache_for(code_block *block)
23 flush_icache((cell)block,block->size);
26 int factorvm::number_of_parameters(relocation_type type)
42 case RT_MEGAMORPHIC_CACHE_HITS:
46 critical_error("Bad rel type",type);
47 return -1; /* Can't happen */
51 void *factorvm::object_xt(cell obj)
53 switch(tagged<object>(obj).type())
56 return untag<word>(obj)->xt;
58 return untag<quotation>(obj)->xt;
60 critical_error("Expected word or quotation",obj);
65 void *factorvm::xt_pic(word *w, cell tagged_quot)
67 if(tagged_quot == F || max_pic_size == 0)
71 quotation *quot = untag<quotation>(tagged_quot);
79 void *factorvm::word_xt_pic(word *w)
81 return xt_pic(w,w->pic_def);
84 void *factorvm::word_xt_pic_tail(word *w)
86 return xt_pic(w,w->pic_tail_def);
89 /* References to undefined symbols are patched up to call this function on
91 void factorvm::undefined_symbol()
93 general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL);
96 void undefined_symbol(factorvm *myvm)
98 return myvm->undefined_symbol();
101 /* Look up an external library symbol referenced by a compiled code block */
102 void *factorvm::get_rel_symbol(array *literals, cell index)
104 cell symbol = array_nth(literals,index);
105 cell library = array_nth(literals,index + 1);
107 dll *d = (library == F ? NULL : untag<dll>(library));
109 if(d != NULL && !d->dll)
110 return (void *)factor::undefined_symbol;
112 switch(tagged<object>(symbol).type())
114 case BYTE_ARRAY_TYPE:
116 symbol_char *name = alien_offset(symbol);
117 void *sym = ffi_dlsym(d,name);
123 return (void *)factor::undefined_symbol;
129 array *names = untag<array>(symbol);
130 for(i = 0; i < array_capacity(names); i++)
132 symbol_char *name = alien_offset(array_nth(names,i));
133 void *sym = ffi_dlsym(d,name);
138 return (void *)factor::undefined_symbol;
141 critical_error("Bad symbol specifier",symbol);
142 return (void *)factor::undefined_symbol;
146 cell factorvm::compute_relocation(relocation_entry rel, cell index, code_block *compiled)
148 array *literals = untag<array>(compiled->literals);
149 cell offset = relocation_offset_of(rel) + (cell)compiled->xt();
151 #define ARG array_nth(literals,index)
153 switch(relocation_type_of(rel))
156 return (cell)primitives[untag_fixnum(ARG)];
158 return (cell)get_rel_symbol(literals,index);
162 return (cell)object_xt(ARG);
164 return (cell)word_xt_pic(untag<word>(ARG));
166 return (cell)word_xt_pic_tail(untag<word>(ARG));
169 fixnum arg = untag_fixnum(ARG);
170 return (arg >= 0 ? offset + arg : (cell)(compiled +1) - arg);
173 return (cell)(compiled + 1);
175 return (cell)&stack_chain;
177 return untag_fixnum(ARG);
178 case RT_MEGAMORPHIC_CACHE_HITS:
179 return (cell)&megamorphic_cache_hits;
183 critical_error("Bad rel type",rel);
184 return 0; /* Can't happen */
190 void factorvm::iterate_relocations(code_block *compiled, relocation_iterator iter)
192 if(compiled->relocation != F)
194 byte_array *relocation = untag<byte_array>(compiled->relocation);
196 cell index = stack_traces_p() ? 1 : 0;
198 cell length = array_capacity(relocation) / sizeof(relocation_entry);
199 for(cell i = 0; i < length; i++)
201 relocation_entry rel = relocation->data<relocation_entry>()[i];
202 iter(rel,index,compiled,this);
203 index += number_of_parameters(relocation_type_of(rel));
208 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
209 void factorvm::store_address_2_2(cell *ptr, cell value)
211 ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
212 ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
215 /* Store a value into a bitfield of a PowerPC instruction */
216 void factorvm::store_address_masked(cell *ptr, fixnum value, cell mask, fixnum shift)
218 /* This is unaccurate but good enough */
219 fixnum test = (fixnum)mask >> 1;
220 if(value <= -test || value >= test)
221 critical_error("Value does not fit inside relocation",0);
223 *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
226 /* Perform a fixup on a code block */
227 void factorvm::store_address_in_code_block(cell klass, cell offset, fixnum absolute_value)
229 fixnum relative_value = absolute_value - offset;
233 case RC_ABSOLUTE_CELL:
234 *(cell *)offset = absolute_value;
237 *(u32*)offset = absolute_value;
240 *(u32*)offset = relative_value - sizeof(u32);
242 case RC_ABSOLUTE_PPC_2_2:
243 store_address_2_2((cell *)offset,absolute_value);
245 case RC_ABSOLUTE_PPC_2:
246 store_address_masked((cell *)offset,absolute_value,rel_absolute_ppc_2_mask,0);
248 case RC_RELATIVE_PPC_2:
249 store_address_masked((cell *)offset,relative_value,rel_relative_ppc_2_mask,0);
251 case RC_RELATIVE_PPC_3:
252 store_address_masked((cell *)offset,relative_value,rel_relative_ppc_3_mask,0);
254 case RC_RELATIVE_ARM_3:
255 store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
256 rel_relative_arm_3_mask,2);
258 case RC_INDIRECT_ARM:
259 store_address_masked((cell *)offset,relative_value - sizeof(cell),
260 rel_indirect_arm_mask,0);
262 case RC_INDIRECT_ARM_PC:
263 store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
264 rel_indirect_arm_mask,0);
267 critical_error("Bad rel class",klass);
272 void factorvm::update_literal_references_step(relocation_entry rel, cell index, code_block *compiled)
274 if(relocation_type_of(rel) == RT_IMMEDIATE)
276 cell offset = relocation_offset_of(rel) + (cell)(compiled + 1);
277 array *literals = untag<array>(compiled->literals);
278 fixnum absolute_value = array_nth(literals,index);
279 store_address_in_code_block(relocation_class_of(rel),offset,absolute_value);
283 void update_literal_references_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
285 return myvm->update_literal_references_step(rel,index,compiled);
288 /* Update pointers to literals from compiled code. */
289 void factorvm::update_literal_references(code_block *compiled)
291 if(!compiled->needs_fixup)
293 iterate_relocations(compiled,factor::update_literal_references_step);
294 flush_icache_for(compiled);
298 /* Copy all literals referenced from a code block to newspace. Only for
299 aging and nursery collections */
300 void factorvm::copy_literal_references(code_block *compiled)
302 if(collecting_gen >= compiled->last_scan)
304 if(collecting_accumulation_gen_p())
305 compiled->last_scan = collecting_gen;
307 compiled->last_scan = collecting_gen + 1;
309 /* initialize chase pointer */
310 cell scan = newspace->here;
312 copy_handle(&compiled->literals);
313 copy_handle(&compiled->relocation);
315 /* do some tracing so that all reachable literals are now
316 at their final address */
317 copy_reachable_objects(scan,&newspace->here);
319 update_literal_references(compiled);
323 void copy_literal_references(code_block *compiled, factorvm *myvm)
325 return myvm->copy_literal_references(compiled);
328 /* Compute an address to store at a relocation */
329 void factorvm::relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled)
332 tagged<array>(compiled->literals).untag_check(this);
333 tagged<byte_array>(compiled->relocation).untag_check(this);
336 store_address_in_code_block(relocation_class_of(rel),
337 relocation_offset_of(rel) + (cell)compiled->xt(),
338 compute_relocation(rel,index,compiled));
341 void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
343 return myvm->relocate_code_block_step(rel,index,compiled);
346 void factorvm::update_word_references_step(relocation_entry rel, cell index, code_block *compiled)
348 relocation_type type = relocation_type_of(rel);
349 if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
350 relocate_code_block_step(rel,index,compiled);
353 void update_word_references_step(relocation_entry rel, cell index, code_block *compiled, factorvm *myvm)
355 return myvm->update_word_references_step(rel,index,compiled);
358 /* Relocate new code blocks completely; updating references to literals,
359 dlsyms, and words. For all other words in the code heap, we only need
360 to update references to other words, without worrying about literals
362 void factorvm::update_word_references(code_block *compiled)
364 if(compiled->needs_fixup)
365 relocate_code_block(compiled);
366 /* update_word_references() is always applied to every block in
367 the code heap. Since it resets all call sites to point to
368 their canonical XT (cold entry point for non-tail calls,
369 standard entry point for tail calls), it means that no PICs
370 are referenced after this is done. So instead of polluting
371 the code heap with dead PICs that will be freed on the next
372 GC, we add them to the free list immediately. */
373 else if(compiled->type == PIC_TYPE)
374 heap_free(&code,compiled);
377 iterate_relocations(compiled,factor::update_word_references_step);
378 flush_icache_for(compiled);
382 void update_word_references(code_block *compiled, factorvm *myvm)
384 return myvm->update_word_references(compiled);
387 void factorvm::update_literal_and_word_references(code_block *compiled)
389 update_literal_references(compiled);
390 update_word_references(compiled);
393 void update_literal_and_word_references(code_block *compiled, factorvm *myvm)
395 return myvm->update_literal_and_word_references(compiled);
398 void factorvm::check_code_address(cell address)
401 assert(address >= code.seg->start && address < code.seg->end);
405 /* Update references to words. This is done after a new code block
406 is added to the heap. */
408 /* Mark all literals referenced from a word XT. Only for tenured
410 void factorvm::mark_code_block(code_block *compiled)
412 check_code_address((cell)compiled);
414 mark_block(compiled);
416 copy_handle(&compiled->literals);
417 copy_handle(&compiled->relocation);
420 void factorvm::mark_stack_frame_step(stack_frame *frame)
422 mark_code_block(frame_code(frame));
425 void mark_stack_frame_step(stack_frame *frame, factorvm *myvm)
427 return myvm->mark_stack_frame_step(frame);
430 /* Mark code blocks executing in currently active stack frames. */
431 void factorvm::mark_active_blocks(context *stacks)
433 if(collecting_gen == data->tenured())
435 cell top = (cell)stacks->callstack_top;
436 cell bottom = (cell)stacks->callstack_bottom;
438 iterate_callstack(top,bottom,factor::mark_stack_frame_step);
442 void factorvm::mark_object_code_block(object *object)
444 switch(object->h.hi_tag())
448 word *w = (word *)object;
450 mark_code_block(w->code);
452 mark_code_block(w->profiling);
457 quotation *q = (quotation *)object;
459 mark_code_block(q->code);
464 callstack *stack = (callstack *)object;
465 iterate_callstack_object(stack,factor::mark_stack_frame_step);
471 /* Perform all fixups on a code block */
472 void factorvm::relocate_code_block(code_block *compiled)
474 compiled->last_scan = data->nursery();
475 compiled->needs_fixup = false;
476 iterate_relocations(compiled,factor::relocate_code_block_step);
477 flush_icache_for(compiled);
480 void relocate_code_block(code_block *compiled, factorvm *myvm)
482 return myvm->relocate_code_block(compiled);
485 /* Fixup labels. This is done at compile time, not image load time */
486 void factorvm::fixup_labels(array *labels, code_block *compiled)
489 cell size = array_capacity(labels);
491 for(i = 0; i < size; i += 3)
493 cell klass = untag_fixnum(array_nth(labels,i));
494 cell offset = untag_fixnum(array_nth(labels,i + 1));
495 cell target = untag_fixnum(array_nth(labels,i + 2));
497 store_address_in_code_block(klass,
498 offset + (cell)(compiled + 1),
499 target + (cell)(compiled + 1));
504 code_block *factorvm::allot_code_block(cell size)
506 heap_block *block = heap_allot(&code,size + sizeof(code_block));
508 /* If allocation failed, do a code GC */
512 block = heap_allot(&code,size + sizeof(code_block));
514 /* Insufficient room even after code GC, give up */
517 cell used, total_free, max_free;
518 heap_usage(&code,&used,&total_free,&max_free);
520 print_string("Code heap stats:\n");
521 print_string("Used: "); print_cell(used); nl();
522 print_string("Total free space: "); print_cell(total_free); nl();
523 print_string("Largest free block: "); print_cell(max_free); nl();
524 fatal_error("Out of memory in add-compiled-block",0);
528 return (code_block *)block;
532 code_block *factorvm::add_code_block(cell type, cell code_, cell labels_, cell relocation_, cell literals_)
534 gc_root<byte_array> code(code_,this);
535 gc_root<object> labels(labels_,this);
536 gc_root<byte_array> relocation(relocation_,this);
537 gc_root<array> literals(literals_,this);
539 cell code_length = align8(array_capacity(code.untagged()));
540 code_block *compiled = allot_code_block(code_length);
542 /* compiled header */
543 compiled->type = type;
544 compiled->last_scan = data->nursery();
545 compiled->needs_fixup = true;
546 compiled->relocation = relocation.value();
548 /* slight space optimization */
549 if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
550 compiled->literals = F;
552 compiled->literals = literals.value();
555 memcpy(compiled + 1,code.untagged() + 1,code_length);
558 if(labels.value() != F)
559 fixup_labels(labels.as<array>().untagged(),compiled);
561 /* next time we do a minor GC, we have to scan the code heap for
563 last_code_heap_scan = data->nursery();