3 /* References to undefined symbols are patched up to call this function on
5 void undefined_symbol(void)
7 general_error(ERROR_UNDEFINED_SYMBOL
,F
,F
,NULL
);
10 INLINE CELL
get_literal(CELL literals_start
, CELL num
)
12 return get(CREF(literals_start
,num
));
15 /* Look up an external library symbol referenced by a compiled code block */
16 void *get_rel_symbol(F_REL
*rel
, CELL literals_start
)
18 CELL arg
= REL_ARGUMENT(rel
);
19 CELL symbol
= get_literal(literals_start
,arg
);
20 CELL library
= get_literal(literals_start
,arg
+ 1);
22 F_DLL
*dll
= (library
== F
? NULL
: untag_dll(library
));
24 if(dll
!= NULL
&& !dll
->dll
)
25 return undefined_symbol
;
27 if(type_of(symbol
) == BYTE_ARRAY_TYPE
)
29 F_SYMBOL
*name
= alien_offset(symbol
);
30 void *sym
= ffi_dlsym(dll
,name
);
35 else if(type_of(symbol
) == ARRAY_TYPE
)
38 F_ARRAY
*names
= untag_object(symbol
);
39 for(i
= 0; i
< array_capacity(names
); i
++)
41 F_SYMBOL
*name
= alien_offset(array_nth(names
,i
));
42 void *sym
= ffi_dlsym(dll
,name
);
49 return undefined_symbol
;
52 /* Compute an address to store at a relocation */
53 INLINE CELL
compute_code_rel(F_REL
*rel
,
54 CELL code_start
, CELL literals_start
)
61 return (CELL
)primitives
[REL_ARGUMENT(rel
)];
63 return (CELL
)get_rel_symbol(rel
,literals_start
);
65 return get(CREF(literals_start
,REL_ARGUMENT(rel
)));
67 obj
= get(CREF(literals_start
,REL_ARGUMENT(rel
)));
68 if(type_of(obj
) == WORD_TYPE
)
69 return (CELL
)untag_word(obj
)->xt
;
71 return (CELL
)untag_quotation(obj
)->xt
;
73 return rel
->offset
+ code_start
+ (short)REL_ARGUMENT(rel
);
75 return code_start
+ REL_ARGUMENT(rel
);
77 return (CELL
)&stack_chain
;
79 critical_error("Bad rel type",rel
->type
);
80 return -1; /* Can't happen */
84 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
85 INLINE
void reloc_set_2_2(CELL cell
, CELL value
)
87 put(cell
- CELLS
,((get(cell
- CELLS
) & ~0xffff) | ((value
>> 16) & 0xffff)));
88 put(cell
,((get(cell
) & ~0xffff) | (value
& 0xffff)));
91 /* Store a value into a bitfield of a PowerPC instruction */
92 INLINE
void reloc_set_masked(CELL cell
, F_FIXNUM value
, CELL mask
, F_FIXNUM shift
)
94 /* This is unaccurate but good enough */
95 F_FIXNUM test
= (F_FIXNUM
)mask
>> 1;
96 if(value
<= -test
|| value
>= test
)
97 critical_error("Value does not fit inside relocation",0);
99 u32 original
= *(u32
*)cell
;
101 *(u32
*)cell
= (original
| ((value
>> shift
) & mask
));
104 /* Perform a fixup on a code block */
105 void apply_relocation(CELL
class, CELL offset
, F_FIXNUM absolute_value
)
107 F_FIXNUM relative_value
= absolute_value
- offset
;
111 case RC_ABSOLUTE_CELL
:
112 put(offset
,absolute_value
);
115 *(u32
*)offset
= absolute_value
;
118 *(u32
*)offset
= relative_value
- sizeof(u32
);
120 case RC_ABSOLUTE_PPC_2_2
:
121 reloc_set_2_2(offset
,absolute_value
);
123 case RC_RELATIVE_PPC_2
:
124 reloc_set_masked(offset
,relative_value
,REL_RELATIVE_PPC_2_MASK
,0);
126 case RC_RELATIVE_PPC_3
:
127 reloc_set_masked(offset
,relative_value
,REL_RELATIVE_PPC_3_MASK
,0);
129 case RC_RELATIVE_ARM_3
:
130 reloc_set_masked(offset
,relative_value
- CELLS
* 2,
131 REL_RELATIVE_ARM_3_MASK
,2);
133 case RC_INDIRECT_ARM
:
134 reloc_set_masked(offset
,relative_value
- CELLS
,
135 REL_INDIRECT_ARM_MASK
,0);
137 case RC_INDIRECT_ARM_PC
:
138 reloc_set_masked(offset
,relative_value
- CELLS
* 2,
139 REL_INDIRECT_ARM_MASK
,0);
142 critical_error("Bad rel class",class);
147 /* Perform all fixups on a code block */
148 void relocate_code_block(F_COMPILED
*compiled
, CELL code_start
, CELL literals_start
)
150 compiled
->last_scan
= NURSERY
;
152 if(compiled
->relocation
!= F
)
154 F_BYTE_ARRAY
*relocation
= untag_object(compiled
->relocation
);
156 F_REL
*rel
= (F_REL
*)(relocation
+ 1);
157 F_REL
*rel_end
= (F_REL
*)((char *)rel
+ byte_array_capacity(relocation
));
161 CELL offset
= rel
->offset
+ code_start
;
163 F_FIXNUM absolute_value
= compute_code_rel(
164 rel
,code_start
,literals_start
);
166 apply_relocation(REL_CLASS(rel
),offset
,absolute_value
);
172 flush_icache(code_start
,literals_start
- code_start
);
175 /* Fixup labels. This is done at compile time, not image load time */
176 void fixup_labels(F_ARRAY
*labels
, CELL code_format
, CELL code_start
)
179 CELL size
= array_capacity(labels
);
181 for(i
= 0; i
< size
; i
+= 3)
183 CELL
class = to_fixnum(array_nth(labels
,i
));
184 CELL offset
= to_fixnum(array_nth(labels
,i
+ 1));
185 CELL target
= to_fixnum(array_nth(labels
,i
+ 2));
187 apply_relocation(class,
189 target
+ code_start
);
193 /* Write a sequence of integers to memory, with 'format' bytes per integer */
194 void deposit_integers(CELL here
, F_ARRAY
*array
, CELL format
)
196 CELL count
= array_capacity(array
);
199 for(i
= 0; i
< count
; i
++)
201 F_FIXNUM value
= to_fixnum(array_nth(array
,i
));
203 bput(here
+ i
,value
);
204 else if(format
== sizeof(unsigned int))
205 *(unsigned int *)(here
+ format
* i
) = value
;
206 else if(format
== CELLS
)
207 put(CREF(here
,i
),value
);
209 critical_error("Bad format in deposit_integers()",format
);
213 /* Write a sequence of tagged pointers to memory */
214 void deposit_objects(CELL here
, F_ARRAY
*array
)
216 memcpy((void*)here
,array
+ 1,array_capacity(array
) * CELLS
);
219 bool stack_traces_p(void)
221 return to_boolean(userenv
[STACK_TRACES_ENV
]);
224 CELL
compiled_code_format(void)
226 return untag_fixnum_fast(userenv
[JIT_CODE_FORMAT
]);
229 CELL
allot_code_block(CELL size
)
231 CELL start
= heap_allot(&code_heap
,size
);
233 /* If allocation failed, do a code GC */
237 start
= heap_allot(&code_heap
,size
);
239 /* Insufficient room even after code GC, give up */
242 CELL used
, total_free
, max_free
;
243 heap_usage(&code_heap
,&used
,&total_free
,&max_free
);
245 print_string("Code heap stats:\n");
246 print_string("Used: "); print_cell(used
); nl();
247 print_string("Total free space: "); print_cell(total_free
); nl();
248 print_string("Largest free block: "); print_cell(max_free
); nl();
249 fatal_error("Out of memory in add-compiled-block",0);
257 F_COMPILED
*add_compiled_block(
264 CELL code_format
= compiled_code_format();
266 CELL code_length
= align8(array_capacity(code
) * code_format
);
267 CELL literals_length
= array_capacity(literals
) * CELLS
;
269 REGISTER_ROOT(relocation
);
270 REGISTER_UNTAGGED(code
);
271 REGISTER_UNTAGGED(labels
);
272 REGISTER_UNTAGGED(literals
);
274 CELL here
= allot_code_block(sizeof(F_COMPILED
) + code_length
+ literals_length
);
276 UNREGISTER_UNTAGGED(literals
);
277 UNREGISTER_UNTAGGED(labels
);
278 UNREGISTER_UNTAGGED(code
);
279 UNREGISTER_ROOT(relocation
);
281 /* compiled header */
282 F_COMPILED
*header
= (void *)here
;
284 header
->last_scan
= NURSERY
;
285 header
->code_length
= code_length
;
286 header
->literals_length
= literals_length
;
287 header
->relocation
= relocation
;
289 here
+= sizeof(F_COMPILED
);
291 CELL code_start
= here
;
294 deposit_integers(here
,code
,code_format
);
298 deposit_objects(here
,literals
);
299 here
+= literals_length
;
303 fixup_labels(labels
,code_format
,code_start
);
305 /* next time we do a minor GC, we have to scan the code heap for
307 last_code_heap_scan
= NURSERY
;
312 void set_word_code(F_WORD
*word
, F_COMPILED
*compiled
)
314 if(compiled
->type
!= WORD_TYPE
)
315 critical_error("bad param to set_word_xt",(CELL
)compiled
);
317 word
->code
= compiled
;
321 /* Allocates memory */
322 void default_word_code(F_WORD
*word
, bool relocate
)
324 REGISTER_UNTAGGED(word
);
325 jit_compile(word
->def
,relocate
);
326 UNREGISTER_UNTAGGED(word
);
328 word
->code
= untag_quotation(word
->def
)->code
;
332 void primitive_modify_code_heap(void)
334 bool rescan_code_heap
= to_boolean(dpop());
335 F_ARRAY
*alist
= untag_array(dpop());
337 CELL count
= untag_fixnum_fast(alist
->capacity
);
339 for(i
= 0; i
< count
; i
++)
341 F_ARRAY
*pair
= untag_array(array_nth(alist
,i
));
343 F_WORD
*word
= untag_word(array_nth(pair
,0));
345 CELL data
= array_nth(pair
,1);
349 REGISTER_UNTAGGED(alist
);
350 REGISTER_UNTAGGED(word
);
351 default_word_code(word
,false);
352 UNREGISTER_UNTAGGED(word
);
353 UNREGISTER_UNTAGGED(alist
);
357 F_ARRAY
*compiled_code
= untag_array(data
);
359 F_ARRAY
*literals
= untag_array(array_nth(compiled_code
,0));
360 CELL relocation
= array_nth(compiled_code
,1);
361 F_ARRAY
*labels
= untag_array(array_nth(compiled_code
,2));
362 F_ARRAY
*code
= untag_array(array_nth(compiled_code
,3));
364 REGISTER_UNTAGGED(alist
);
365 REGISTER_UNTAGGED(word
);
367 F_COMPILED
*compiled
= add_compiled_block(
374 UNREGISTER_UNTAGGED(word
);
375 UNREGISTER_UNTAGGED(alist
);
377 set_word_code(word
,compiled
);
380 REGISTER_UNTAGGED(alist
);
381 update_word_xt(word
);
382 UNREGISTER_UNTAGGED(alist
);
385 /* If there were any interned words in the set, we relocate all XT
386 references in the entire code heap. But if all the words are
387 uninterned, it is impossible that other words reference them, so we
388 only have to relocate the new words. This makes compile-call much
391 iterate_code_heap(relocate_code_block
);
394 for(i
= 0; i
< count
; i
++)
396 F_ARRAY
*pair
= untag_array(array_nth(alist
,i
));
397 F_WORD
*word
= untag_word(array_nth(pair
,0));
399 iterate_code_heap_step(word
->code
,relocate_code_block
);