2 Copyright (C) 2001-2009, Parrot Foundation.
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.
25 /* HEADERIZER HFILE: none */
28 #include <parrot/parrot.h>
29 #if PARROT_EXEC_CAPABLE
30 # include "parrot/exec.h"
35 #include "parrot/packfile.h"
36 #include "parrot/oplib/ops.h"
37 #include "pmc/pmc_sub.h"
38 #include "pmc/pmc_managedstruct.h"
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
51 #if defined __GNUC__ || defined __IBMC__
52 void Parrot_jit_debug(PARROT_INTERP
);
58 insert_fixup_targets(PARROT_INTERP, char *branch,
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
72 insert_fixup_targets(PARROT_INTERP
, char *branch
,
75 PackFile_FixupTable
*ft
= interp
->code
->fixups
;
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
;
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
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
117 make_branch_list(PARROT_INTERP
,
118 Parrot_jit_optimizer_t
* optimizer
,
119 opcode_t
*code_start
, opcode_t
*code_end
)
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
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)
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
156 * So we will mark the branch target.
159 * Means the opcode does some other kind of jump, and also
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
176 while (cur_op
< code_end
) {
177 opcode_t op
= *cur_op
;
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
)
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
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
) {
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;
243 /* Move to the next opcode */
244 ADD_OP_VAR_PART(interp
, interp
->code
, cur_op
, n
);
247 insert_fixup_targets(interp
, branch
, code_end
- code_start
);
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.
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
;
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]
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
);
290 sig
= Parrot_pcc_get_pmc_constant(interp
, CURRENT_CONTEXT(interp
), cur_op
[1]);
291 arg_type
= VTABLE_get_integer_keyed_int(interp
,
293 arg_type
&= (PARROT_ARG_TYPE_MASK
| PARROT_ARG_CONSTANT
);
296 arg_type
= op_info
->types
[argn
- 1];
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
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.
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
;
358 const UINTVAL flags
= PObj_get_FLAGS(key
);
359 if (flags
& KEY_register_FLAG
) {
361 if (flags
& KEY_integer_FLAG
) {
362 n
= VTABLE_get_integer(interp
, key
);
367 else if (flags
& KEY_pmc_FLAG
)
369 else if (flags
& KEY_string_FLAG
)
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
);
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
395 init_regusage(PARROT_INTERP
, Parrot_jit_optimizer_section_ptr cur_section
)
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
++) {
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.
427 # define EXTCALL(op) (op_jit[(op)].extcall >= 1 || (op) >= jit_op_count())
428 # define CALLS_C_CODE(op) (op_func[(op)].extcall == -1)
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
;
440 int branched
, start_new
;
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
;
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
);
477 * If this opcode is jitted and next is a C function */
479 cur_section
->jit_op_count
++;
481 if (next_op
< code_end
&& EXTCALL(*next_op
))
485 /* or if current section is not jitted, and the next opcode
487 if (next_op
< code_end
&& !EXTCALL(*next_op
))
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
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 */
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
;
535 cur_section
->block
= prev_section
->block
;
536 /* Save the address where the section begins */
537 cur_section
->begin
= next_op
;
544 /* Move to the next opcode */
553 Parrot_jit_optimizer_t *optimizer, opcode_t * code_start)>
555 Makes the branch targets.
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
] <
575 t_section
= optimizer
->sections
;
577 t_section
= cur_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
;
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
;
599 sort_registers(Parrot_jit_info_t *jit_info)>
601 Sorts the Parrot registers prior to mapping them to actual hardware registers.
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
++) {
635 for (i
= 0; i
< NUM_REGISTERS
; i
++)
636 ru
[typ
].reg_count
[i
] += nru
[typ
].reg_count
[i
];
641 /* now sort registers by their usage count */
642 for (typ
= 0; typ
< 4; typ
++) {
643 /* find most used register */
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
];
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
])
656 /* as long as we map registers for this typ */
659 ru
[typ
].reg_usage
[k
++] = max_i
;
661 if (k
== to_map
[typ
])
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
) {
671 /* if same usage not found, look for lower usage */
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
++) {
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
;
697 /* Move to the next section */
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
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.
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
)
758 Parrot_jit_optimizer_t
*optimizer
;
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
];
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
)
789 typ
--; /* types are + 1 */
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
];
797 if (idx
== (opcode_t
)cur_section
->ru
[typ
].reg_usage
[i
]) {
798 map
[cur_op
+ op_arg
- code_start
] = maps
[typ
][i
];
806 /* Move to the next opcode */
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.
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
;
848 debug_sections(PARROT_INTERP,
849 Parrot_jit_optimizer_t *optimizer, opcode_t * code_start)>
851 Prints out debugging info.
858 debug_sections(PARROT_INTERP
,
859 Parrot_jit_optimizer_t
*optimizer
, opcode_t
* code_start
)
861 Parrot_jit_optimizer_section_ptr cur_section
;
863 char * map
= optimizer
->map_branch
;
866 const char types
[] = "IPSN";
867 int types_to_list
[] = {0, 3};
869 cur_section
= optimizer
->sections
;
870 while (cur_section
) {
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",
879 for (cur_op
= cur_section
->begin
; cur_op
<= cur_section
->end
;) {
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
);
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");
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
) {
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
;
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.
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. */
973 debug_sections(interp
, optimizer
, code_start
);
975 if (jit_info
->code_type
!= JIT_CODE_SUB_REGS_ONLY
)
976 sort_registers(jit_info
);
977 map_registers(interp
, jit_info
, code_start
);
980 debug_sections(interp
, optimizer
, code_start
);
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.
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
;
1007 opcode_t
*ptr
, offs
;
1008 Parrot_jit_optimizer_section_ptr section
, prev
;
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
));
1031 prev
->next
= section
;
1033 optimizer
->sections
= section
;
1034 section
->prev
= prev
;
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
++;
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
);
1060 assign_registers(interp
, jit_info
, section
, code_start
, 1);
1062 insert_fixup_targets(interp
, branch
, code_end
- code_start
);
1064 debug_sections(interp
, optimizer
, code_start
);
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)>
1080 /* we always are using offsets */
1084 reg_offs(int typ
, int i
)
1088 return REG_OFFS_INT(i
);
1090 return REG_OFFS_NUM(i
);
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.
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
;
1118 int base_reg
= 0; /* -O3 warning */
1119 int lasts
[] = { 0, 0, 0, 0 };
1120 const char * maps
[] = {0, 0, 0, 0};
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
++) {
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
) ||
1139 ((ru
[typ
].reg_dir
[us
] & PARROT_ARGDIR_IN
)))) {
1141 base_reg
= Parrot_jit_emit_get_base_reg_no(
1142 jit_info
->native_ptr
);
1145 offs
= reg_offs(typ
, us
);
1147 (arch_info
->mov_RM_n
)(interp
, jit_info
,
1148 maps
[typ
][i
], base_reg
, offs
);
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
);
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.
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
;
1187 int base_reg
= 0; /* -O3 warning */
1188 int lasts
[] = { 0, 0, 0, 0 };
1189 const char * maps
[] = {0, 0, 0, 0};
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
++) {
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
) ||
1210 (ru
[typ
].reg_dir
[us
] & PARROT_ARGDIR_OUT
))) {
1212 base_reg
= Parrot_jit_emit_get_base_reg_no(
1213 jit_info
->native_ptr
);
1217 offs
= reg_offs(typ
, us
);
1219 (arch_info
->mov_MR_n
)(interp
, jit_info
,
1220 base_reg
, offs
, maps
[typ
][i
]);
1222 (arch_info
->mov_MR_i
)(interp
, jit_info
,
1223 base_reg
, offs
, maps
[typ
][i
]);
1233 Parrot_destroy_jit(void *ptr)>
1235 Frees the memory used by the JIT subsystem.
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
;
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
);
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
;
1264 next_f
= fixup
->next
;
1265 mem_sys_free(fixup
);
1268 /* optimizer stuff */
1269 mem_sys_free(optimizer
->map_branch
);
1270 mem_sys_free(optimizer
->branch_list
);
1271 mem_sys_free(optimizer
);
1278 * - locate Sub according to pc
1279 * - set register usage in context
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
;
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
;
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
]);
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
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
1348 parrot_build_asm(PARROT_INTERP
, ARGIN(opcode_t
*code_start
), ARGIN(opcode_t
*code_end
),
1349 ARGIN(void *objfile
), INTVAL jit_type
)
1354 Parrot_jit_info_t
*jit_info
= NULL
;
1355 opcode_t cur_opcode_byte
;
1357 PackFile_Segment
*jit_seg
;
1359 Parrot_jit_fn_info_t
*op_func
;
1360 INTVAL n_regs_used
[4]; /* INSP in PBC */
1362 const jit_arch_info
*arch_info
;
1363 int needs_fs
; /* fetch/store */
1366 * no longer referenced due to disabled code below
1370 Parrot_jit_optimizer_section_ptr cur_section
;
1373 Parrot_exec_objfile_t
*obj
= (Parrot_exec_objfile_t
*)objfile
;
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
;
1382 != JIT_CODE_SUB_REGS_ONLY
;
1387 jit_info
->objfile
= obj
;
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
1415 * JIT segs are currently not built
1416 * the find_segments also segfaults on PPC eval_2
1417 * maybe something not initialized correctly
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);
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
);
1436 optimize_imcc_jit(interp
, jit_info
, code_start
, code_end
, jit_seg
);
1438 optimize_jit(interp
, jit_info
, code_start
, code_end
);
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
);
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
);
1462 jit_info
->objfile
->text
.code
= jit_info
->arena
.start
;
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
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
);
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
;
1542 obj
->text
.code
= new_arena
;
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
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.
1561 * save also, if we have a jitted sections and encounter
1562 * an "end" opcode, e.g. in evaled code
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
&&
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
);
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
);
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
);
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
;
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
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
);
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
=
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 */
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
);
1706 Parrot_io_eprintf(interp
, "\nTotal size %u bytes\n",
1707 (unsigned int)(jit_info
->native_ptr
- jit_info
->arena
.start
));
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
);
1736 Parrot_jit_newfixup(Parrot_jit_info_t *jit_info)>
1738 Remember the current position in the native code for later update.
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.
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
);
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.
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
);
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 */
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
;
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>.
1858 * c-file-style: "parrot"
1860 * vim: expandtab shiftwidth=4: