[t] Refactor some namespace pmc tests to use throws_like
[parrot.git] / src / jit.c
blob8f1fd815a9114fab270eb9c547f10dd866717aa4
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/jit.c - JIT
9 =head1 DESCRIPTION
11 JIT (Just In Time) compilation converts bytecode to native machine code
12 instructions and executes the generated instruction sequence directly.
14 Actually it's not really just in time, it's just before this piece of code is
15 used and not per subroutine or even opcode, it works per bytecode segment.
17 =head2 Functions
19 =over 4
21 =cut
25 /* HEADERIZER HFILE: none */
26 /* HEADERIZER STOP */
28 #include <parrot/parrot.h>
29 #if PARROT_EXEC_CAPABLE
30 # include "parrot/exec.h"
31 #endif
32 #include "jit.h"
33 #define JIT_EMIT 0
34 #include "jit_emit.h"
35 #include "parrot/packfile.h"
36 #include "parrot/oplib/ops.h"
37 #include "pmc/pmc_sub.h"
38 #include "pmc/pmc_managedstruct.h"
40 #define JIT_SEGS 0
42 extern int jit_op_count(void);
44 * s. jit/$jitcpuarch/jit_emit.h for the meaning of these defs
47 #ifndef ALLOCATE_REGISTERS_PER_SECTION
48 # define ALLOCATE_REGISTERS_PER_SECTION 1
49 #endif
51 #if defined __GNUC__ || defined __IBMC__
52 void Parrot_jit_debug(PARROT_INTERP);
53 #endif
57 =item C<static void
58 insert_fixup_targets(PARROT_INTERP, char *branch,
59 size_t limit)>
61 Look at fixups, mark all fixup entries as branch target.
63 TODO: actually this is wrong: fixups belong only to one code segment.
64 The code below doesn't check, for which segments the fixups are
65 inserted.
67 =cut
71 static void
72 insert_fixup_targets(PARROT_INTERP, char *branch,
73 size_t limit)
75 PackFile_FixupTable *ft = interp->code->fixups;
76 int i;
78 if (!ft)
79 return;
81 for (i = 0; i < ft->fixup_count; i++) {
82 if (ft->fixups[i]->type == enum_fixup_label) {
83 if ((size_t)ft->fixups[i]->offset < limit)
84 branch[ft->fixups[i]->offset] |= JIT_BRANCH_TARGET;
91 =item C<static void
92 make_branch_list(PARROT_INTERP,
93 Parrot_jit_optimizer_t * optimizer,
94 opcode_t *code_start, opcode_t *code_end)>
96 C<< optimizer->map_branch >> parallels the opcodes with a list of
97 branch information and register mapping information
99 =over 4
101 =item branch instructions have C<JIT_BRANCH_SOURCE>
103 =item opcodes jumped to have C<JIT_BRANCH_TARGET>
105 =item mapped arguments have register type + 1 and finally
107 =item after register allocation these have the processor register that
108 got mapped
110 =back
112 =cut
116 static void
117 make_branch_list(PARROT_INTERP,
118 Parrot_jit_optimizer_t * optimizer,
119 opcode_t *code_start, opcode_t *code_end)
121 op_info_t *op_info;
122 char *branch;
123 opcode_t *cur_op;
125 cur_op = code_start;
127 /* Allocate space for the branch information and register map */
128 optimizer->map_branch = branch =
129 (char *)mem_sys_allocate_zeroed((size_t)(code_end - code_start + 1));
131 /* Allocate space for the branch list */
132 optimizer->branch_list = (opcode_t **)
133 mem_sys_allocate_zeroed(
134 (size_t)(code_end - code_start) * sizeof (opcode_t *));
136 /* If the opcode jumps we may:
138 * PARROT_JUMP_RELATIVE:
139 * The op jumps to an address relative to the current position,
140 * thus we mark the branch target and the branch source.
142 * PARROT_JUMP_ADDRESS:
143 * The op jumps to an absolute address, thus we mark the branch
144 * target.
146 * PARROT_JUMP_POP:
147 * The op pops the address to jump to, thus we don't mark the
148 * branch target, anyway it may probably use expr(NEXT)
150 * PARROT_JUMP_ENEXT:
151 * The op does something with expr(NEXT),
152 * XXX I'll assume that it's stored in the control stack for
153 * later returning since that's the only way it's used now
154 * but this should go away by the time we add some metadata
155 * to the ops.
156 * So we will mark the branch target.
158 * PARROT_JUMP_GNEXT:
159 * Means the opcode does some other kind of jump, and also
160 * might goto(NEXT)
162 * PARROT_JUMP_UNPREDICTABLE:
163 * The branch target is unpredictable.
164 * Things get a little tricky since it's not 100% true that the
165 * target is unpredictable because of the set_addr opcode, we
166 * need to find a solution for this, in the mean time, we will
167 * make each section have its own arena and try to avoid
168 * going in and out from them as much as possible.
170 * PARROT_JUMP_RESTART
171 * If the parrot program counter is zero, fall out of the
172 * run loop.
176 while (cur_op < code_end) {
177 opcode_t op = *cur_op;
178 int i, n;
179 size_t rel_offset;
182 /* Predereference the opcode information table for this opcode
183 * early since it's going to be used many times */
184 op_info = &interp->op_info_table[op];
186 /* if op_info->jump is not 0 this opcode may jump,
187 * so mark this opcode as a branch source */
188 rel_offset = cur_op - code_start;
190 n = op_info->op_count;
192 if (op == PARROT_OP_set_args_pc ||
193 op == PARROT_OP_set_returns_pc ||
194 op == PARROT_OP_get_results_pc)
195 goto no_branch;
196 if (op_info->jump)
197 branch[rel_offset] |= JIT_BRANCH_SOURCE;
198 for (i = 1; i < n; ++i) {
199 /* If it's not a constant, no joy */
200 if (op_info->types[i-1] == PARROT_ARG_IC && op_info->labels[i-1]) {
201 /* The branch target is relative,
202 * the offset is in the i argument
204 if (op_info->jump & PARROT_JUMP_RELATIVE) {
205 /* Set the branch target */
206 optimizer->branch_list[rel_offset] = cur_op + cur_op[i];
207 branch[rel_offset + cur_op[i]] |= JIT_BRANCH_TARGET;
209 /* The branch target is absolute,
210 * the address is in the i argument
212 else if (op_info->jump & PARROT_JUMP_ADDRESS) {
213 /* Set the branch target */
214 optimizer->branch_list[rel_offset] = cur_op + cur_op[i];
215 branch[cur_op[i]] |= JIT_BRANCH_TARGET;
217 /* the labels of set_addr and newsub are branch targets too
218 * this is needed e.g. for JIT_CGP
220 else {
221 branch[rel_offset + cur_op[i]] |= JIT_BRANCH_TARGET;
225 /* The address of the next opcode */
226 if ((op_info->jump & PARROT_JUMP_ENEXT) ||
227 (op_info->jump & PARROT_JUMP_GNEXT))
228 branch[rel_offset + n] |= JIT_BRANCH_TARGET;
229 if (op_info->jump & PARROT_JUMP_UNPREDICTABLE) {
231 * TODO
232 * this flag is currently not used or set
233 * and: if we have a branch that isn't going to a constant
234 * target like a calculated branch used by rx_ opcodes
235 * we are totally lost WRT register preservation.
236 * If we don't know, that the code is a branch target, inside
237 * a JITted code section, mapped registers might be
238 * not up to date WRT Parrot registers.
240 optimizer->has_unpredictable_jump = 1;
242 no_branch:
243 /* Move to the next opcode */
244 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
245 cur_op += n;
247 insert_fixup_targets(interp, branch, code_end - code_start);
252 =item C<static void
253 set_register_usage(PARROT_INTERP,
254 Parrot_jit_info_t *jit_info,
255 Parrot_jit_optimizer_section_ptr cur_section,
256 op_info_t *op_info, opcode_t *cur_op, opcode_t *code_start)>
258 Sets the register usage counts.
260 =cut
264 static void
265 set_register_usage(PARROT_INTERP,
266 Parrot_jit_info_t *jit_info,
267 Parrot_jit_optimizer_section_ptr cur_section,
268 op_info_t *op_info, opcode_t *cur_op, opcode_t *code_start)
270 int argn, args, argt;
271 int typ;
272 Parrot_jit_register_usage_t *ru = cur_section->ru;
273 Parrot_jit_optimizer_t * optimizer = jit_info->optimizer;
274 char * const map = optimizer->map_branch;
276 /* For each argument that has the opcode increment the usage count,
277 * We move from the end since we need to check if the first opcode
278 * using the register will read or write it.
280 * registers are set per their type [IPSN]
281 * */
282 args = argt = op_info->op_count;
283 ADD_OP_VAR_PART(interp, interp->code, cur_op, argt);
284 for (argn = argt - 1; argn > 0; argn--) {
285 /* TODO check the argn-1 entries */
286 int idx = *(cur_op + argn);
287 int arg_type;
288 PMC *sig;
289 if (argn >= args) {
290 sig = Parrot_pcc_get_pmc_constant(interp, CURRENT_CONTEXT(interp), cur_op[1]);
291 arg_type = VTABLE_get_integer_keyed_int(interp,
292 sig, argn - args);
293 arg_type &= (PARROT_ARG_TYPE_MASK | PARROT_ARG_CONSTANT);
295 else
296 arg_type = op_info->types[argn - 1];
298 switch (arg_type) {
299 case PARROT_ARG_I:
300 case PARROT_ARG_KI:
301 typ = 0;
303 * if the register number is negative, the register mapping
304 * was done by imcc/jit.c, which used negative numbers
305 * for allocated CPU registers. That's currently not
306 * functional because of changed register allocation
307 * strategy inside imcc.
308 * The code is still here and should probably be reactivated
309 * later, when things are stable: imcc has all the
310 * necessary information like basic blocks and loop depth
311 * calculated already. A lot is duplicated here to regain this
312 * information.
314 if (idx < 0)
315 idx = -1 - idx;
316 break;
317 case PARROT_ARG_P:
318 case PARROT_ARG_K:
320 * P and S regs aren't currently used at all. That's not
321 * really optimal. If we have plenty of mappable registers
322 * and if we can call vtables or MMD functions directly
323 * we should finally allocate P and S regs too.
325 typ = 1;
326 break;
327 case PARROT_ARG_S:
328 typ = 2;
329 break;
330 case PARROT_ARG_N:
331 if (idx < 0)
332 idx = -1 - idx;
333 typ = 3;
334 break;
335 default:
336 typ = -1;
337 break;
340 * JIT structures are NUM_REGISTERS big
341 * we can currently allocate only that much
343 if (typ >= 0 && idx < NUM_REGISTERS) {
344 /* remember the register typ (+1) for this op argument
345 * for register allocation */
346 map[cur_op + argn - code_start] = typ + 1;
347 if ((!ru[typ].reg_count[idx]++) &&
348 (op_info->dirs[argn-1] & PARROT_ARGDIR_IN))
349 ru[typ].reg_dir[idx] |= PARROT_ARGDIR_IN;
350 if (op_info->dirs[argn-1] & PARROT_ARGDIR_OUT) {
351 ru[typ].reg_dir[idx] |= PARROT_ARGDIR_OUT;
354 /* key constants may have register keys */
355 else if (arg_type == PARROT_ARG_KC) {
356 PMC *key = interp->code->const_table->constants[idx]->u.key;
357 while (key) {
358 const UINTVAL flags = PObj_get_FLAGS(key);
359 if (flags & KEY_register_FLAG) {
360 INTVAL n = 0;
361 if (flags & KEY_integer_FLAG) {
362 n = VTABLE_get_integer(interp, key);
363 typ = 0;
364 if (n < 0)
365 n = -1 - n;
367 else if (flags & KEY_pmc_FLAG)
368 typ = 1;
369 else if (flags & KEY_string_FLAG)
370 typ = 2;
372 if (n < NUM_REGISTERS && !ru[typ].reg_count[n]++)
373 ru[typ].reg_dir[n] |= PARROT_ARGDIR_IN;
375 key = VTABLE_shift_pmc(interp, key);
383 =item C<static void
384 init_regusage(PARROT_INTERP,
385 Parrot_jit_optimizer_section_ptr cur_section)>
387 Init all register usage to Parrot register usage. Used when JITting
388 subroutines to registers only
390 =cut
394 static void
395 init_regusage(PARROT_INTERP, Parrot_jit_optimizer_section_ptr cur_section)
397 int typ;
399 cur_section->ru[0].registers_used = Parrot_pcc_get_regs_used(interp,
400 CURRENT_CONTEXT(interp), REGNO_INT);
401 cur_section->ru[3].registers_used = Parrot_pcc_get_regs_used(interp,
402 CURRENT_CONTEXT(interp), REGNO_NUM);
403 cur_section->ru[1].registers_used = cur_section->ru[2].registers_used = 0;
405 for (typ = 0; typ < 4; typ++) {
406 int j;
407 for (j = 0; j < cur_section->ru[typ].registers_used; j++)
408 cur_section->ru[typ].reg_usage[j] = j;
414 =item C<static void make_sections(PARROT_INTERP,
415 Parrot_jit_info_t *jit_info,
416 opcode_t *code_start, opcode_t *code_end)>
418 I386 has JITed vtables, which have the vtable# in extcall.
420 This C<Parrot_jit_vtable_n_op()> does use register mappings.
422 =cut
426 #ifndef EXTCALL
427 # define EXTCALL(op) (op_jit[(op)].extcall >= 1 || (op) >= jit_op_count())
428 # define CALLS_C_CODE(op) (op_func[(op)].extcall == -1)
429 #endif
431 static void
432 make_sections(PARROT_INTERP,
433 Parrot_jit_info_t *jit_info,
434 opcode_t *code_start, opcode_t *code_end)
436 Parrot_jit_optimizer_section_ptr cur_section, t_section, prev_section;
437 opcode_t *next_op;
438 op_info_t *op_info;
439 char *branch;
440 int branched, start_new;
441 opcode_t *cur_op;
442 Parrot_jit_optimizer_t * optimizer;
444 optimizer = jit_info->optimizer;
445 branch = optimizer->map_branch;
447 /* Allocate the first section */
448 cur_section = optimizer->sections = (Parrot_jit_optimizer_section_t *)
449 mem_sys_allocate_zeroed(sizeof (Parrot_jit_optimizer_section_t));
450 cur_section->begin = code_start;
451 prev_section = cur_section;
453 cur_op = code_start;
454 /* set all regs to Parrot's */
455 if (jit_info->code_type == JIT_CODE_SUB_REGS_ONLY)
456 init_regusage(interp, cur_section);
457 while (cur_section) {
458 opcode_t op = *cur_op;
459 branched = start_new = 0;
460 /* Predereference the opcode information for this opcode
461 * early since it's going to be used many times */
462 op_info = &interp->op_info_table[op];
464 /* Calculate the next pc */
465 next_op = cur_op + op_info->op_count;
466 ADD_OP_VAR_PART(interp, interp->code, cur_op, next_op);
468 /* Update op_count */
469 cur_section->op_count++;
471 /* set register usage for this section */
472 set_register_usage(interp, jit_info, cur_section,
473 op_info, cur_op, code_start);
476 * End a section:
477 * If this opcode is jitted and next is a C function */
478 if (!EXTCALL(op)) {
479 cur_section->jit_op_count++;
481 if (next_op < code_end && EXTCALL(*next_op))
482 start_new = 1;
484 else
485 /* or if current section is not jitted, and the next opcode
486 * is. */
487 if (next_op < code_end && !EXTCALL(*next_op))
488 start_new = 1;
490 /* or when the current opcode is a branch source,
491 * in other words if the opcode jumps, or if the next opcode is
492 * a branch target, allocate a new section only if it's not the
493 * last opcode */
494 if ((branch[cur_op - code_start] & JIT_BRANCH_SOURCE)
495 || (next_op < code_end &&
496 (branch[next_op - code_start] & JIT_BRANCH_TARGET))
497 || (next_op >= code_end)) {
498 /* remember to start a new block */
499 branched = 1;
500 start_new = 1;
503 if (start_new) {
504 /* Set the type, depending on whether the current
505 * instruction is external or jitted. */
506 cur_section->isjit = !EXTCALL(op);
508 /* Save the address where the section ends */
509 cur_section->end = cur_op;
511 if (next_op < code_end) {
512 /* Allocate a new section */
513 t_section = (Parrot_jit_optimizer_section_t *)
514 mem_sys_allocate_zeroed(
515 sizeof (Parrot_jit_optimizer_section_t));
516 /* Add it to the double linked list */
517 cur_section->next = t_section;
518 t_section->prev = cur_section;
519 /* Make the new section be the current one */
520 cur_section = t_section;
521 /* set all regs to Parrot's */
522 if (jit_info->code_type == JIT_CODE_SUB_REGS_ONLY)
523 init_regusage(interp, cur_section);
525 /* registers get either allocated per section or
526 * per basic block (i.e. one or more sections divided
527 * by branches. When allocation per block is done
528 * all sections in one block have the same block number
530 if (ALLOCATE_REGISTERS_PER_SECTION || branched) {
531 cur_section->block = prev_section->block + 1;
532 prev_section = cur_section;
534 else
535 cur_section->block = prev_section->block;
536 /* Save the address where the section begins */
537 cur_section->begin = next_op;
539 else {
540 cur_section = NULL;
544 /* Move to the next opcode */
545 cur_op = next_op;
551 =item C<static void
552 make_branch_targets(
553 Parrot_jit_optimizer_t *optimizer, opcode_t * code_start)>
555 Makes the branch targets.
557 =cut
561 static void
562 make_branch_targets(Parrot_jit_optimizer_t *optimizer, const opcode_t * code_start)
564 Parrot_jit_optimizer_section_ptr cur_section, t_section;
565 /* Set the branch target of this section, that is the section where
566 * the program execution continues, if it ends in a branch source we
567 * use the branch target and not the next section. */
568 cur_section = optimizer->sections;
569 while (cur_section) {
570 if (optimizer->branch_list[cur_section->end - code_start]) {
571 /* If the branch target is to a section before the current one
572 * move from the start, otherwise from the current section */
573 if (optimizer->branch_list[cur_section->end - code_start] <
574 cur_section->begin)
575 t_section = optimizer->sections;
576 else
577 t_section = cur_section;
579 while (t_section) {
580 /* If we find the section attach it to the current one. */
581 if (t_section->begin ==
582 optimizer->branch_list[cur_section->end - code_start]) {
583 cur_section->branch_target = t_section;
584 break;
586 /* If not move to the next. */
587 t_section = t_section->next;
591 /* Move to the next section */
592 cur_section = cur_section->next;
598 =item C<static void
599 sort_registers(Parrot_jit_info_t *jit_info)>
601 Sorts the Parrot registers prior to mapping them to actual hardware registers.
603 =cut
607 static void
608 sort_registers(Parrot_jit_info_t *jit_info)
610 Parrot_jit_optimizer_t *optimizer;
611 Parrot_jit_optimizer_section_ptr cur_section, next;
612 int any, k, typ, code_type;
613 int max_count, max_i = 0;
614 int to_map[] = { 0, 0, 0, 0 };
616 code_type = jit_info->code_type;
617 to_map[0] = jit_info->arch_info->regs[code_type].n_mapped_I;
618 to_map[3] = jit_info->arch_info->regs[code_type].n_mapped_F;
620 optimizer = jit_info->optimizer;
621 /* Start from the first section */
622 cur_section = optimizer->sections;
624 while (cur_section) {
625 Parrot_jit_register_usage_t *ru = cur_section->ru;
626 /* sum up register usage for one block, don't change
627 * reg_dir. If allocation is done per section, block numbers
628 * are different, so this is a nop
630 next = cur_section->next;
631 while (next && next->block == cur_section->block) {
632 const Parrot_jit_register_usage_t * const nru = next->ru;
633 for (typ = 0; typ < 4; typ++) {
634 int i;
635 for (i = 0; i < NUM_REGISTERS; i++)
636 ru[typ].reg_count[i] += nru[typ].reg_count[i];
638 next = next->next;
641 /* now sort registers by their usage count */
642 for (typ = 0; typ < 4; typ++) {
643 /* find most used register */
644 int i;
645 for (i = max_count = 0; i < NUM_REGISTERS; i++) {
646 if (cur_section->ru[typ].reg_count[i] > max_count) {
647 max_count = cur_section->ru[typ].reg_count[i];
648 max_i = i;
651 /* start from this register and set usage */
652 k = ru[typ].registers_used = 0;
653 /* no usage, go on with next type */
654 if (max_count == 0 || !to_map[typ])
655 continue;
656 /* as long as we map registers for this typ */
657 while (1) {
658 if (max_i >= 0)
659 ru[typ].reg_usage[k++] = max_i;
660 /* all mapped? */
661 if (k == to_map[typ])
662 break;
663 /* now check for equal usage starting after maxi */
664 for (any = 0, i = max_i + 1; i < NUM_REGISTERS; i++) {
665 if (ru[typ].reg_count[i] == max_count) {
666 max_i = i;
667 any = 1;
668 break;
671 /* if same usage not found, look for lower usage */
672 if (any == 0) {
673 if (max_count > 1) {
674 max_count--;
675 max_i = -1;
676 continue;
678 break;
681 ru[typ].registers_used = k;
683 next = cur_section->next;
684 /* duplicate usage to all sections of block */
685 while (next && next->block == cur_section->block) {
686 Parrot_jit_register_usage_t * const nru = next->ru;
687 for (typ = 0; typ < 4; typ++) {
688 int i;
689 for (i = 0; i < ru[typ].registers_used; i++) {
690 nru[typ].reg_count[i] = ru[typ].reg_count[i];
691 nru[typ].reg_usage[i] = ru[typ].reg_usage[i];
693 nru[typ].registers_used = ru[typ].registers_used;
695 next = next->next;
697 /* Move to the next section */
698 cur_section = next;
704 =item C<static void
705 assign_registers(PARROT_INTERP,
706 Parrot_jit_info_t *jit_info,
707 Parrot_jit_optimizer_section_ptr cur_section,
708 opcode_t * code_start, int from_imcc)>
710 Called by C<map_registers()> to actually assign the Parrot registers to
711 hardware registers.
713 TODO
715 Before actually assigning registers, we should optimize a bit:
717 1) calculate max use count of register types for all sections
719 2) calculate costs for register preserving and restoring
720 for two different allocation strategies:
722 a) allocate non-volatiles first
723 overhead for jit_begin, jit_end:
724 - 2 * max_used_non_volatile registers
725 overhead for register preserving around non-jitted sections:
726 - only used IN arguments are saved
727 - only OUT non-volatile arguments are restored
728 b) allocate volatiles first
729 no overhead for jit_begin, jit_end
730 overhead per JITed op that calls a C function:
731 - 2 * n_used_volatiles_to_preserve for each call
732 overhead for register preserving around non-jitted sections:
733 - all volatiles are saved and restored around non-jitted sections
735 NB for all cost estimations size does matter: a 64bit double counts as
736 two 32bit ints. Opcode count is assumed to be just one.
738 3) depending on costs from 2) use one of the strategies
739 That does still not account for any usage patterns. Imcc has loop
740 nesting depth, but that's not available here. OTOH smaller code tends
741 to perform better because of better cache usage.
743 Usage analysis could show that a mixture of both strategies is best, e.g:
744 allocate 2-4 non-volatiles and the rest from volatiles. But that would
745 complicate the allocation code a bit.
747 =cut
751 static void
752 assign_registers(PARROT_INTERP,
753 Parrot_jit_info_t *jit_info,
754 Parrot_jit_optimizer_section_ptr cur_section,
755 opcode_t * code_start, int from_imcc)
757 char *map;
758 Parrot_jit_optimizer_t *optimizer;
759 int i;
760 opcode_t * cur_op;
761 const char * maps[] = {0, 0, 0, 0};
762 const int code_type = jit_info->code_type;
764 maps[0] = jit_info->arch_info->regs[code_type].map_I;
765 maps[3] = jit_info->arch_info->regs[code_type].map_F;
767 optimizer = jit_info->optimizer;
768 map = optimizer->map_branch;
769 /* For each opcode in this section */
770 cur_op = cur_section->begin;
771 while (cur_op <= cur_section->end) {
772 const opcode_t op = *cur_op;
773 const op_info_t * const op_info = &interp->op_info_table[op];
774 int op_arg;
775 int n;
777 /* For each argument of the current opcode */
778 n = op_info->op_count;
779 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
780 for (op_arg = 1; op_arg < n; op_arg++) {
781 /* get the register typ */
782 int typ = map[cur_op + op_arg - code_start];
783 /* clear the register typ/map */
784 map[cur_op + op_arg - code_start] = 0;
785 /* if not JITted, don't map */
786 if (!cur_section->isjit)
787 continue;
788 if (typ > 0) {
789 typ--; /* types are + 1 */
790 if (!maps[typ])
791 continue;
792 /* If the argument is in most used list for this typ */
793 for (i = 0; i < cur_section->ru[typ].registers_used; i++) {
794 opcode_t idx = cur_op[op_arg];
795 if (from_imcc)
796 idx = -1 - idx;
797 if (idx == (opcode_t)cur_section->ru[typ].reg_usage[i]) {
798 map[cur_op + op_arg - code_start] = maps[typ][i];
799 cur_section->maps++;
800 break;
806 /* Move to the next opcode */
807 cur_op += n;
813 =item C<static void
814 map_registers(PARROT_INTERP,
815 Parrot_jit_info_t *jit_info, opcode_t * code_start)>
817 Maps the most used Parrot registers to hardware registers.
819 =cut
823 static void
824 map_registers(PARROT_INTERP,
825 Parrot_jit_info_t *jit_info,
826 opcode_t * code_start)
828 /* Start from the first section */
829 Parrot_jit_optimizer_section_ptr cur_section = jit_info->optimizer->sections;
831 /* While there is section */
832 while (cur_section) {
834 assign_registers(interp, jit_info, cur_section, code_start, 0);
836 /* Move to the next section */
837 cur_section = cur_section->next;
842 #define JIT_DEBUG 0
844 #if JIT_DEBUG
847 =item C<static void
848 debug_sections(PARROT_INTERP,
849 Parrot_jit_optimizer_t *optimizer, opcode_t * code_start)>
851 Prints out debugging info.
853 =cut
857 static void
858 debug_sections(PARROT_INTERP,
859 Parrot_jit_optimizer_t *optimizer, opcode_t * code_start)
861 Parrot_jit_optimizer_section_ptr cur_section;
862 # if JIT_DEBUG > 1
863 char * map = optimizer->map_branch;
864 # endif
865 int n;
866 const char types[] = "IPSN";
867 int types_to_list[] = {0, 3};
869 cur_section = optimizer->sections;
870 while (cur_section) {
871 opcode_t * cur_op;
872 unsigned int j;
873 Parrot_jit_register_usage_t *ru = cur_section->ru;
875 Parrot_io_eprintf(interp, "\nSection:\n");
876 Parrot_io_eprintf(interp, "%s block %d\n",
877 (cur_section->isjit) ? "JITTED" : "NOT JITTED",
878 cur_section->block);
879 for (cur_op = cur_section->begin; cur_op <= cur_section->end;) {
880 char instr[256];
881 const opcode_t op = *cur_op;
882 const op_info_t * const op_info = &interp->op_info_table[op];
884 PDB_disassemble_op(interp, instr, sizeof (instr),
885 op_info, cur_op, NULL, code_start, 0);
886 Parrot_io_eprintf(interp, "\t\tOP%vu: ext %3d\t%s\n",
887 cur_op - code_start, op_jit[*cur_op].extcall, instr);
888 n = op_info->op_count;
889 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
890 # if JIT_DEBUG > 1
891 Parrot_io_eprintf(interp, "\t\t\tmap_branch: ");
892 for (i = 0; i < n; i++)
893 Parrot_io_eprintf(interp, "%02x ", map[cur_op-code_start+i]);
894 Parrot_io_eprintf(interp, "\n");
895 # endif
896 cur_op += n;
898 Parrot_io_eprintf(interp, "\tbegin:\t%#p\t(%Ou)\n",
899 cur_section->begin, *cur_section->begin);
900 Parrot_io_eprintf(interp, "\tend:\t%#p\t(%Ou)\n",
901 cur_section->end, *cur_section->end);
903 for (j = 0; j < sizeof (types_to_list)/sizeof (int); j++) {
904 const int typ = types_to_list[j];
905 const char t = types[typ];
906 Parrot_io_eprintf(interp, "\t%c registers used:\t%i\n",
907 t, ru[typ].registers_used);
908 if (ru[typ].registers_used) {
909 int i;
910 Parrot_io_eprintf(interp, "\t%c register count:\t", t);
911 for (i = 0; i < NUM_REGISTERS; i++)
912 Parrot_io_eprintf(interp, "%i ", ru[typ].reg_count[i]);
913 Parrot_io_eprintf(interp, "\n\t%c register usage:\t", t);
914 for (i = 0; i < NUM_REGISTERS; i++)
915 Parrot_io_eprintf(interp, "%i ", ru[typ].reg_usage[i]);
916 Parrot_io_eprintf(interp, "\n\t%c register direction:\t", t);
917 for (i = 0; i < NUM_REGISTERS; i++)
918 Parrot_io_eprintf(interp, "%i ", (int)ru[typ].reg_dir[i]);
919 Parrot_io_eprintf(interp, "\n");
922 Parrot_io_eprintf(interp, "\tJit opcodes:\t%u\n",
923 cur_section->jit_op_count);
924 Parrot_io_eprintf(interp, "\tTotal opcodes:\t%u\n",
925 cur_section->op_count);
926 if (cur_section->branch_target)
927 Parrot_io_eprintf(interp, "\tBranch target:\tOP%u\n",
928 cur_section->branch_target->begin - code_start);
930 cur_section = cur_section->next;
933 #endif
937 =item C<static Parrot_jit_optimizer_t *
938 optimize_jit(PARROT_INTERP,
939 Parrot_jit_info_t *jit_info,
940 opcode_t *code_start, opcode_t *code_end)>
942 Called by C<parrot_build_asm()> to run the optimizer.
944 =cut
948 static void
949 optimize_jit(PARROT_INTERP,
950 Parrot_jit_info_t *jit_info,
951 opcode_t *code_start, opcode_t *code_end)
953 Parrot_jit_optimizer_t *optimizer;
955 /* Allocate space for the optimizer */
956 jit_info->optimizer =
957 optimizer = (Parrot_jit_optimizer_t *)
958 mem_sys_allocate_zeroed(sizeof (Parrot_jit_optimizer_t));
960 /* Look, which opcodes might branch */
961 make_branch_list(interp, optimizer, code_start, code_end);
963 /* ok, let's loop again and generate the sections */
964 make_sections(interp, jit_info, code_start, code_end);
966 /* look where a section jumps to */
967 make_branch_targets(optimizer, code_start);
969 /* This is where we start deciding which Parrot registers get
970 * mapped to a hardware one in each different section. */
972 #if JIT_DEBUG > 2
973 debug_sections(interp, optimizer, code_start);
974 #endif
975 if (jit_info->code_type != JIT_CODE_SUB_REGS_ONLY)
976 sort_registers(jit_info);
977 map_registers(interp, jit_info, code_start);
979 #if JIT_DEBUG
980 debug_sections(interp, optimizer, code_start);
981 #endif
986 =item C<static Parrot_jit_optimizer_t *
987 optimize_imcc_jit(PARROT_INTERP,
988 Parrot_jit_info_t *jit_info,
989 opcode_t *code_start, opcode_t *code_end,
990 PackFile_Segment *jit_seg)>
992 Generate optimizer stuff from the C<_JIT> section in the packfile.
994 =cut
998 static void
999 optimize_imcc_jit(PARROT_INTERP,
1000 Parrot_jit_info_t *jit_info,
1001 opcode_t *code_start, opcode_t *code_end,
1002 PackFile_Segment *jit_seg)
1004 Parrot_jit_optimizer_t *optimizer;
1005 size_t size, i, typ, n;
1006 int j;
1007 opcode_t *ptr, offs;
1008 Parrot_jit_optimizer_section_ptr section, prev;
1009 char *branch;
1010 opcode_t *cur_op;
1012 /* Allocate space for the optimizer */
1013 jit_info->optimizer =
1014 optimizer = (Parrot_jit_optimizer_t *)
1015 mem_sys_allocate_zeroed(sizeof (Parrot_jit_optimizer_t));
1017 * TODO: pass the whole map_branch in the PBC
1018 * this would save two runs through all the opcode
1020 optimizer->map_branch = branch =
1021 (char *)mem_sys_allocate_zeroed((size_t)(code_end - code_start));
1022 ptr = jit_seg->data;
1023 size = jit_seg->size;
1024 PARROT_ASSERT(jit_seg->itype == 0);
1025 PARROT_ASSERT((size % 6) == 0);
1026 cur_op = code_start;
1027 for (prev = NULL, i = 0; i < size/6; i++, prev = section) {
1028 section = (Parrot_jit_optimizer_section_t *)
1029 mem_sys_allocate_zeroed(sizeof (Parrot_jit_optimizer_section_t));
1030 if (prev)
1031 prev->next = section;
1032 else
1033 optimizer->sections = section;
1034 section->prev = prev;
1035 section->block = i;
1036 offs = *ptr++;
1037 if (offs & 0x80000000) {
1038 offs &= ~0x80000000;
1039 branch[offs] = JIT_BRANCH_TARGET;
1041 section->begin = code_start + offs;
1042 section->end = code_start + *ptr++;
1043 section->isjit = 1;
1044 for (typ = 0; typ < 4; typ++) {
1045 section->ru[typ].registers_used = *ptr++;
1046 for (j = 0; j < section->ru[typ].registers_used; j++)
1047 section->ru[typ].reg_usage[j] = j;
1050 while (cur_op <= section->end) {
1051 const opcode_t op = *cur_op;
1052 op_info_t * const op_info = &interp->op_info_table[op];
1053 set_register_usage(interp, jit_info, section,
1054 op_info, cur_op, code_start);
1055 section->op_count++;
1056 n = op_info->op_count;
1057 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
1058 cur_op += n;
1060 assign_registers(interp, jit_info, section, code_start, 1);
1062 insert_fixup_targets(interp, branch, code_end - code_start);
1063 #if JIT_DEBUG
1064 debug_sections(interp, optimizer, code_start);
1065 #endif
1070 =item C<size_t reg_offs(int typ, int i)>
1072 Returns the offset of register C<typ[i]>.
1074 F<src/jit/arch/jit_emit.h> has to define C<Parrot_jit_emit_get_base_reg_no(pc)>
1076 =cut
1080 /* we always are using offsets */
1083 static size_t
1084 reg_offs(int typ, int i)
1086 switch (typ) {
1087 case 0:
1088 return REG_OFFS_INT(i);
1089 case 3:
1090 return REG_OFFS_NUM(i);
1091 default:
1092 return 0;
1098 =item C<static void
1099 Parrot_jit_load_registers(Parrot_jit_info_t *jit_info,
1100 PARROT_INTERP, int volatiles)>
1102 Load registers for the current section from parrot to processor registers.
1103 If C<volatiles> is true, this code is used to restore these registers in
1104 JITted code that calls out to Parrot.
1106 =cut
1110 static void
1111 Parrot_jit_load_registers(Parrot_jit_info_t *jit_info,
1112 PARROT_INTERP, int volatiles)
1114 Parrot_jit_optimizer_section_t *sect = jit_info->optimizer->cur_section;
1115 Parrot_jit_register_usage_t *ru = sect->ru;
1116 int typ;
1117 size_t offs;
1118 int base_reg = 0; /* -O3 warning */
1119 int lasts[] = { 0, 0, 0, 0 };
1120 const char * maps[] = {0, 0, 0, 0};
1121 int first = 1;
1122 const int code_type = jit_info->code_type;
1123 const jit_arch_info * const arch_info = jit_info->arch_info;
1124 const jit_arch_regs * const reg_info = arch_info->regs + code_type;
1126 maps[0] = reg_info->map_I;
1127 maps[3] = reg_info->map_F;
1128 lasts[0] = reg_info->n_preserved_I;
1129 lasts[3] = reg_info->n_preserved_F;
1131 for (typ = 0; typ < 4; typ++) {
1132 if (maps[typ]) {
1133 int i;
1134 for (i = ru[typ].registers_used-1; i >= 0; --i) {
1135 const int us = ru[typ].reg_usage[i];
1136 const int is_used = i >= lasts[typ] && ru[typ].reg_dir[us];
1137 if ((is_used && volatiles) ||
1138 (!volatiles &&
1139 ((ru[typ].reg_dir[us] & PARROT_ARGDIR_IN)))) {
1140 if (first) {
1141 base_reg = Parrot_jit_emit_get_base_reg_no(
1142 jit_info->native_ptr);
1143 first = 0;
1145 offs = reg_offs(typ, us);
1146 if (typ == 3)
1147 (arch_info->mov_RM_n)(interp, jit_info,
1148 maps[typ][i], base_reg, offs);
1149 else
1150 (arch_info->mov_RM_i)(interp, jit_info,
1151 maps[typ][i], base_reg, offs);
1158 /* The total size of the loads. This is used for branches to
1159 * the same section - these skip the load asm bytes */
1160 sect->load_size = jit_info->native_ptr -
1161 (jit_info->arena.start +
1162 jit_info->arena.op_map[jit_info->op_i].offset);
1167 =item C<static void
1168 Parrot_jit_save_registers(Parrot_jit_info_t *jit_info,
1169 PARROT_INTERP, int volatiles)>
1171 Save registers for the current section.
1172 If C<volatiles> is true, this code is used to preserve these registers in
1173 JITted code that calls out to Parrot.
1175 =cut
1179 static void
1180 Parrot_jit_save_registers(Parrot_jit_info_t *jit_info,
1181 PARROT_INTERP, int volatiles)
1183 Parrot_jit_optimizer_section_t *sect = jit_info->optimizer->cur_section;
1184 Parrot_jit_register_usage_t *ru = sect->ru;
1185 int i, typ;
1186 size_t offs;
1187 int base_reg = 0; /* -O3 warning */
1188 int lasts[] = { 0, 0, 0, 0 };
1189 const char * maps[] = {0, 0, 0, 0};
1190 int first = 1;
1191 int code_type;
1192 const jit_arch_info *arch_info;
1193 const jit_arch_regs *reg_info;
1195 arch_info = jit_info->arch_info;
1196 code_type = jit_info->code_type;
1197 reg_info = arch_info->regs + code_type;
1198 maps[0] = reg_info->map_I;
1199 maps[3] = reg_info->map_F;
1200 lasts[0] = reg_info->n_preserved_I;
1201 lasts[3] = reg_info->n_preserved_F;
1203 for (typ = 0; typ < 4; typ++) {
1204 if (maps[typ])
1205 for (i = 0; i < ru[typ].registers_used; ++i) {
1206 const int us = ru[typ].reg_usage[i];
1207 const int is_used = i >= lasts[typ] && ru[typ].reg_dir[us];
1208 if ((is_used && volatiles) ||
1209 (!volatiles &&
1210 (ru[typ].reg_dir[us] & PARROT_ARGDIR_OUT))) {
1211 if (first) {
1212 base_reg = Parrot_jit_emit_get_base_reg_no(
1213 jit_info->native_ptr);
1214 first = 0;
1217 offs = reg_offs(typ, us);
1218 if (typ == 3)
1219 (arch_info->mov_MR_n)(interp, jit_info,
1220 base_reg, offs, maps[typ][i]);
1221 else
1222 (arch_info->mov_MR_i)(interp, jit_info,
1223 base_reg, offs, maps[typ][i]);
1232 =item C<void
1233 Parrot_destroy_jit(void *ptr)>
1235 Frees the memory used by the JIT subsystem.
1237 =cut
1241 void
1242 Parrot_destroy_jit(void *ptr)
1244 Parrot_jit_optimizer_t *optimizer;
1245 Parrot_jit_optimizer_section_ptr cur_section, next;
1246 Parrot_jit_fixup_t *fixup, *next_f;
1247 Parrot_jit_info_t *jit_info = (Parrot_jit_info_t *)ptr;
1249 if (!jit_info)
1250 return;
1251 /* delete sections */
1252 optimizer = jit_info->optimizer;
1253 cur_section = optimizer->sections;
1254 while (cur_section) {
1255 next = cur_section->next;
1256 mem_sys_free(cur_section);
1257 cur_section = next;
1259 /* arena stuff */
1260 mem_sys_free(jit_info->arena.op_map);
1261 mem_free_executable(jit_info->arena.start, jit_info->arena.size);
1262 fixup = jit_info->arena.fixups;
1263 while (fixup) {
1264 next_f = fixup->next;
1265 mem_sys_free(fixup);
1266 fixup = next_f;
1268 /* optimizer stuff */
1269 mem_sys_free(optimizer->map_branch);
1270 mem_sys_free(optimizer->branch_list);
1271 mem_sys_free(optimizer);
1273 free(jit_info);
1277 * see TODO below
1278 * - locate Sub according to pc
1279 * - set register usage in context
1281 static void
1282 set_reg_usage(PARROT_INTERP, const opcode_t *pc)
1284 PackFile_ByteCode * const seg = interp->code;
1285 PackFile_FixupTable * const ft = seg->fixups;
1286 PackFile_ConstTable * const ct = seg->const_table;
1288 int i;
1290 if (!ft)
1291 return;
1293 if (!ct)
1294 return;
1296 for (i = 0; i < ft->fixup_count; i++) {
1297 if (ft->fixups[i]->type == enum_fixup_sub) {
1298 const int ci = ft->fixups[i]->offset;
1299 PMC * const sub_pmc = ct->constants[ci]->u.key;
1300 Parrot_Sub_attributes *sub;
1301 size_t offs;
1302 int i;
1304 PMC_get_sub(interp, sub_pmc, sub);
1305 offs = pc - sub->seg->base.data;
1307 if (offs >= sub->start_offs && offs < sub->end_offs) {
1308 for (i = 0; i < 4; i++)
1309 Parrot_pcc_set_regs_used(interp, CURRENT_CONTEXT(interp),
1310 i, sub->n_regs_used[i]);
1312 return;
1320 =item C<Parrot_jit_info_t *
1321 parrot_build_asm(PARROT_INTERP,
1322 opcode_t *code_start, opcode_t *code_end,
1323 void *objfile, enum_jit_code_type)>
1325 This is the main function of the JIT code generator.
1327 It loops over the bytecode, calling the code generating routines for
1328 each opcode.
1330 The information obtained is used to perform certain types of fixups on
1331 native code, as well as by the native code itself to convert bytecode
1332 program counters values to hardware program counter values.
1334 Finally this code here is used to generate native executables (or better
1335 object files that are linked to executables), if EXEC_CAPABLE is defined.
1336 This functionality is triggered by
1338 parrot -o foo.o foo.pir
1340 which uses the JIT engine to translate to native code inside the object
1341 file.
1343 =cut
1347 Parrot_jit_info_t *
1348 parrot_build_asm(PARROT_INTERP, ARGIN(opcode_t *code_start), ARGIN(opcode_t *code_end),
1349 ARGIN(void *objfile), INTVAL jit_type)
1351 int n;
1352 UINTVAL i;
1353 char *new_arena;
1354 Parrot_jit_info_t *jit_info = NULL;
1355 opcode_t cur_opcode_byte;
1356 opcode_t *cur_op;
1357 PackFile_Segment *jit_seg;
1358 char *map;
1359 Parrot_jit_fn_info_t *op_func;
1360 INTVAL n_regs_used[4]; /* INSP in PBC */
1361 op_info_t *op_info;
1362 const jit_arch_info *arch_info;
1363 int needs_fs; /* fetch/store */
1365 /* XXX
1366 * no longer referenced due to disabled code below
1367 char *name;
1370 Parrot_jit_optimizer_section_ptr cur_section;
1372 #if EXEC_CAPABLE
1373 Parrot_exec_objfile_t *obj = (Parrot_exec_objfile_t *)objfile;
1374 #endif
1376 jit_info = interp->code->jit_info = mem_allocate_typed(Parrot_jit_info_t);
1378 jit_info->flags = jit_type & JIT_CODE_RECURSIVE;
1379 jit_type &= ~ JIT_CODE_RECURSIVE;
1380 jit_info->code_type = jit_type;
1381 needs_fs = jit_type
1382 != JIT_CODE_SUB_REGS_ONLY;
1384 #if EXEC_CAPABLE
1385 if (objfile) {
1386 op_func = op_exec;
1387 jit_info->objfile = obj;
1389 else
1390 #endif
1392 op_func = op_jit;
1393 jit_info->objfile = NULL;
1396 /* reset some extcall bits - all is JITed
1398 if (jit_type == JIT_CODE_SUB_REGS_ONLY) {
1399 op_func[PARROT_OP_set_returns_pc].extcall = 0;
1400 op_func[PARROT_OP_get_params_pc].extcall = 0;
1401 op_func[PARROT_OP_get_params_pc].extcall = 0;
1402 op_func[PARROT_OP_invokecc_p].extcall = 0;
1405 /* get register mappings and such */
1406 arch_info = jit_info->arch_info = Parrot_jit_init(interp);
1409 * check if IMCC did all the work. If yes, we have a PF segment with
1410 * register allocation information inside.
1411 * See imcc/jit.c for more
1413 #if JIT_SEGS
1414 /* RT #45055
1415 * JIT segs are currently not built
1416 * the find_segments also segfaults on PPC eval_2
1417 * maybe something not initialized correctly
1418 * - disabled --leo
1420 name = mem_sys_allocate(strlen(interp->code->base.name) + 5);
1421 sprintf(name, "%s_JIT", interp->code->base.name);
1422 jit_seg = PackFile_find_segment(interp,
1423 interp->code->base.dir, name, 0);
1424 mem_sys_free(name);
1425 #else
1426 jit_seg = NULL;
1427 #endif
1429 /* remember register usage */
1430 for (i = 0; i < 4; i++)
1431 n_regs_used[i] = Parrot_pcc_get_regs_used(interp, CURRENT_CONTEXT(interp), i);
1433 set_reg_usage(interp, code_start);
1435 #if JIT_SEGS
1436 optimize_imcc_jit(interp, jit_info, code_start, code_end, jit_seg);
1437 #else
1438 optimize_jit(interp, jit_info, code_start, code_end);
1439 #endif
1441 /* Byte code size in opcode_t's */
1442 jit_info->arena.map_size = (code_end - code_start) + 1;
1443 jit_info->arena.op_map =
1444 (Parrot_jit_opmap_t *)mem_sys_allocate_zeroed(
1445 jit_info->arena.map_size * sizeof (* (jit_info->arena.op_map)));
1447 #if REQUIRES_CONSTANT_POOL
1448 Parrot_jit_init_arenas(jit_info);
1449 #else
1450 jit_info->arena.size = 1024;
1452 /* estimate size needed
1453 * 10 times pbc code size seems to be enough for i386
1455 if ((size_t)jit_info->arena.map_size * 20 > (size_t)jit_info->arena.size)
1456 jit_info->arena.size = jit_info->arena.map_size * 20;
1457 jit_info->native_ptr = jit_info->arena.start =
1458 (char *)mem_alloc_executable((size_t)jit_info->arena.size);
1460 # if EXEC_CAPABLE
1461 if (obj)
1462 jit_info->objfile->text.code = jit_info->arena.start;
1463 # endif
1464 #endif
1466 jit_info->op_i = 0;
1467 jit_info->arena.fixups = NULL;
1469 /* The first section */
1470 cur_section = jit_info->optimizer->cur_section
1471 = jit_info->optimizer->sections;
1472 map = jit_info->optimizer->map_branch;
1475 * from C's ABI all the emitted code here is one (probably big)
1476 * function. So we have to generate an appropriate function
1477 * prologue, that makes all this look like a normal function ;)
1479 jit_info->cur_op = cur_section->begin;
1480 (arch_info->regs[jit_type].jit_begin)(jit_info, interp);
1483 * op_map holds the offset from arena.start
1484 * of the parrot op at the given opcode index
1486 * Set the offset of the first opcode
1488 jit_info->arena.op_map[jit_info->op_i].offset =
1489 jit_info->native_ptr - jit_info->arena.start;
1492 * the function epilog can basically be anywhere, that's done
1493 * by the Parrot_end opcode somewhere in core.jit
1496 while (jit_info->optimizer->cur_section) {
1497 /* the code emitting functions need cur_op and cur_section
1498 * so these vars are in jit_info too
1502 * TODO
1504 * Register offsets depend on n_regs_used, which is per
1505 * subroutine. JIT code is currently generated for a whole
1506 * PBC. We can either:
1507 * 1) create JIT per subroutine or
1508 * 2) track the sub we are currently in, set register usage
1509 * in the interpreter context and restore it at end
1511 * for now we use 2) - longterm plan is 1)
1514 /* The first opcode for this section */
1515 cur_op = jit_info->cur_op = cur_section->begin;
1517 set_reg_usage(interp, cur_op);
1519 /* Load mapped registers for this section, if JIT */
1520 if (!jit_seg && cur_section->isjit && needs_fs)
1521 Parrot_jit_load_registers(jit_info, interp, 0);
1523 /* The first opcode of each section doesn't have a previous one since
1524 * it's impossible to be sure which was it */
1525 jit_info->prev_op = NULL;
1527 while (cur_op <= cur_section->end) {
1528 /* Grow the arena early */
1529 if (jit_info->arena.size <
1530 (jit_info->arena.op_map[jit_info->op_i].offset + 200)) {
1531 #if REQUIRES_CONSTANT_POOL
1532 Parrot_jit_extend_arena(jit_info);
1533 #else
1534 new_arena = (char *)mem_realloc_executable(jit_info->arena.start,
1535 jit_info->arena.size, (size_t)jit_info->arena.size * 2);
1536 jit_info->arena.size *= 2;
1537 jit_info->native_ptr = new_arena +
1538 (jit_info->native_ptr - jit_info->arena.start);
1539 jit_info->arena.start = new_arena;
1540 # if EXEC_CAPABLE
1541 if (obj)
1542 obj->text.code = new_arena;
1543 # endif
1544 #endif
1547 cur_opcode_byte = *cur_op;
1549 /* Need to save the registers if there is a branch and is not to
1550 * the same section, I admit I don't like this, and it should be
1551 * really checking if the target section has the same registers
1552 * mapped too.
1554 * Yep so: TODO
1555 * during register allocation try to use the same registers, if
1556 * its a loop or a plain branch and if register usage doesn't
1557 * differ too much. This could save a lot of register reloads.
1559 * --
1561 * save also, if we have a jitted sections and encounter
1562 * an "end" opcode, e.g. in evaled code
1564 if (needs_fs) {
1565 if ((((map[cur_op - code_start] == JIT_BRANCH_SOURCE) &&
1566 (cur_section->branch_target != cur_section)) ||
1567 !cur_opcode_byte) &&
1568 cur_section->isjit &&
1569 !jit_seg) {
1570 Parrot_jit_save_registers(jit_info, interp, 0);
1572 else if (CALLS_C_CODE(cur_opcode_byte)) {
1574 * a JITted function with a function call, we have to
1575 * save volatile registers but
1576 * TODO not if the previous opcode was also one
1577 * that called C code
1579 Parrot_jit_save_registers(jit_info, interp, 1);
1584 * for all opcodes that are dynamically loaded, we can't have
1585 * a JITted version, so we execute the function incarnation
1586 * via the wrapper opcode, which just runs one opcode
1587 * see ops/core.ops for more
1589 if (cur_opcode_byte >= jit_op_count())
1590 cur_opcode_byte = CORE_OPS_wrapper__;
1592 (op_func[cur_opcode_byte].fn) (jit_info, interp);
1594 if (CALLS_C_CODE(cur_opcode_byte) && needs_fs) {
1596 * restore volatiles only - and TODO only if next
1597 * wouldn't load registers anyway
1599 Parrot_jit_load_registers(jit_info, interp, 1);
1601 /* Update the previous opcode */
1602 jit_info->prev_op = cur_op;
1604 op_info = &interp->op_info_table[*cur_op];
1605 n = op_info->op_count;
1606 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
1607 cur_op += n;
1609 /* update op_i and cur_op accordingly */
1610 jit_info->op_i += n;
1611 jit_info->cur_op += n;
1613 if (*jit_info->prev_op == PARROT_OP_set_args_pc &&
1614 jit_type == JIT_CODE_SUB_REGS_ONLY) {
1615 PARROT_ASSERT(*cur_op == PARROT_OP_set_p_pc);
1617 /* skip it */
1618 cur_op += 3;
1619 jit_info->op_i += 3;
1620 jit_info->cur_op += 3;
1622 jit_info->arena.op_map[jit_info->op_i].offset =
1623 jit_info->native_ptr - jit_info->arena.start;
1625 PARROT_ASSERT(*cur_op == PARROT_OP_get_results_pc);
1627 /* now emit the call - use special op for this */
1628 (op_func[PARROT_OP_pic_callr___pc].fn)(jit_info, interp);
1630 /* and the get_results */
1631 (op_func[*cur_op].fn)(jit_info, interp);
1633 op_info = &interp->op_info_table[*cur_op];
1634 n = op_info->op_count;
1635 ADD_OP_VAR_PART(interp, interp->code, cur_op, n);
1637 cur_op += n;
1639 /* update op_i and cur_op accordingly */
1640 jit_info->op_i += n;
1641 jit_info->cur_op += n;
1643 jit_info->arena.op_map[jit_info->op_i].offset =
1644 jit_info->native_ptr - jit_info->arena.start;
1646 /* now at invoke */
1647 PARROT_ASSERT(*cur_op == PARROT_OP_invokecc_p);
1649 cur_op += 2; /* skip it */
1650 jit_info->op_i += 2;
1651 jit_info->cur_op += 2;
1654 /* if this is a branch target, align it */
1655 #ifdef jit_emit_noop
1656 # if JUMP_ALIGN
1657 if (((!cur_section->next && cur_op <= cur_section->end) ||
1658 cur_section->next) &&
1659 map[cur_op - code_start] == JIT_BRANCH_TARGET) {
1660 while ((long)jit_info->native_ptr & ((1<<JUMP_ALIGN) - 1))
1661 jit_emit_noop(jit_info->native_ptr);
1663 # endif
1664 #endif
1665 /* set the offset */
1666 jit_info->arena.op_map[jit_info->op_i].offset =
1667 jit_info->native_ptr - jit_info->arena.start;
1670 /* Save mapped registers back to the Parrot registers */
1671 if (!jit_seg && cur_section->isjit && needs_fs)
1672 Parrot_jit_save_registers(jit_info, interp, 0);
1674 /* update the offset for saved registers */
1675 jit_info->arena.op_map[jit_info->op_i].offset =
1676 jit_info->native_ptr - jit_info->arena.start;
1678 /* Move to the next section */
1679 cur_section = jit_info->optimizer->cur_section =
1680 cur_section->next;
1683 /* restore register usage */
1684 for (i = 0; i < 4; i++)
1685 Parrot_pcc_set_regs_used(interp, CURRENT_CONTEXT(interp), i, n_regs_used[i]);
1687 /* Do fixups before converting offsets */
1688 (arch_info->jit_dofixup)(jit_info, interp);
1690 /* Convert offsets to pointers */
1691 if (!objfile)
1692 for (i = 0; i < jit_info->arena.map_size; i++) {
1694 /* Assuming native code chunks contain some initialization code,
1695 * the first op (and every other op) is at an offset > 0
1697 if (jit_info->arena.op_map[i].offset) {
1698 jit_info->arena.op_map[i].ptr = (char *)jit_info->arena.start +
1699 jit_info->arena.op_map[i].offset;
1703 jit_info->arena.size =
1704 (ptrdiff_t)(jit_info->native_ptr - jit_info->arena.start);
1705 #if JIT_DEBUG
1706 Parrot_io_eprintf(interp, "\nTotal size %u bytes\n",
1707 (unsigned int)(jit_info->native_ptr - jit_info->arena.start));
1708 #endif
1711 * sync data cache if needed - we are executing it as code in some usecs
1713 if (arch_info->jit_flush_cache)
1714 (arch_info->jit_flush_cache)(jit_info, interp);
1716 /* assume gdb is available: generate symbol information */
1717 #if defined __GNUC__ || defined __IBMC__
1718 if (Interp_debug_TEST(interp, PARROT_JIT_DEBUG_FLAG)) {
1720 * TODO same like above here e.g. create ASM listing of code
1721 * if real debug support isn't available
1723 if (jit_type == JIT_CODE_FILE) {
1724 interp->code->jit_info = jit_info;
1725 Parrot_jit_debug(interp);
1728 #endif
1730 return jit_info;
1735 =item C<void
1736 Parrot_jit_newfixup(Parrot_jit_info_t *jit_info)>
1738 Remember the current position in the native code for later update.
1740 =cut
1744 void
1745 Parrot_jit_newfixup(Parrot_jit_info_t *jit_info)
1747 Parrot_jit_fixup_t *fixup;
1749 fixup = mem_allocate_zeroed_typed(Parrot_jit_fixup_t);
1751 /* Insert fixup at the head of the list */
1752 fixup->next = jit_info->arena.fixups;
1753 jit_info->arena.fixups = fixup;
1755 /* Fill in the native code offset */
1756 fixup->native_offset =
1757 (ptrdiff_t)(jit_info->native_ptr - jit_info->arena.start);
1762 =item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>
1764 This is a callback to implement the proper freeing semantics. It is called by
1765 the ManagedStruct PMC as it is garbage collected.
1767 =cut
1771 void
1772 Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)
1774 const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv;
1775 mem_free_executable(ptr, jit->size);
1776 free(priv);
1781 =item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>
1783 This is a callback to implement the proper cloning semantics for jit buffers.
1784 It is called by the ManagedStruct PMC's clone() function.
1786 =cut
1790 PMC *
1791 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)
1793 PMC * const rv = pmc_new(interp, pmc->vtable->base_type);
1795 VTABLE_init(interp, rv);
1796 /* copy the attributes */
1798 void (*tmpfreefunc)(PARROT_INTERP, void*, void*);
1799 GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc);
1800 SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc);
1803 PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*);
1804 GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc);
1805 SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc);
1809 void *freepriv, *clonepriv;
1810 GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv);
1811 GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv);
1812 if (freepriv) {
1813 void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
1814 memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data));
1815 SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp);
1816 if (clonepriv == freepriv) {
1817 /* clonepriv is a copy of freepriv, make it a copy in the clone too. */
1818 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
1819 clonepriv = NULL; /* disable the clonepriv copying below */
1822 if (clonepriv) {
1823 void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
1824 memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data));
1825 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
1829 /* copy the execmem buffer */
1830 if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
1831 struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
1832 void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;
1833 void *newptr = mem_alloc_executable(jit->size);
1834 memcpy(newptr, ptr, jit->size);
1835 PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;
1838 return rv;
1844 =back
1846 =head1 SEE ALSO
1848 F<src/jit.h>, F<docs/jit.pod>, F<src/jit_debug.c>,
1849 F<src/jit/$jitcpuarch/jit_emit.h>, F<jit/$jitcpuarch/core.jit>.
1851 =cut
1857 * Local variables:
1858 * c-file-style: "parrot"
1859 * End:
1860 * vim: expandtab shiftwidth=4: