parrotcode: JIT | |
Contents | C |
src/jit.c - JIT
JIT (Just In Time) compilation converts bytecode to native machine code instructions and executes the generated instruction sequence directly.
Actually it's not really just in time, it's just before this piece of code is used and not per subroutine or even opcode, it works per bytecode segment.
static void insert_fixup_targets(PARROT_INTERP, char *branch, size_t limit)
static void make_branch_list(PARROT_INTERP, Parrot_jit_optimizer_t *optimizer, opcode_t *code_start, opcode_t *code_end)
optimizer->map_branch
parallels the opcodes with a list of branch information and register mapping information
JIT_BRANCH_SOURCE
JIT_BRANCH_TARGET
static void set_register_usage(PARROT_INTERP, Parrot_jit_info_t *jit_info, Parrot_jit_optimizer_section_ptr cur_section, op_info_t *op_info, opcode_t *cur_op, opcode_t *code_start)
static void init_regusage(PARROT_INTERP, Parrot_jit_optimizer_section_ptr cur_section)
static void make_sections(PARROT_INTERP, Parrot_jit_info_t *jit_info, opcode_t *code_start, opcode_t *code_end)
Parrot_jit_vtable_n_op()
does use register mappings.
static void make_branch_targets( Parrot_jit_optimizer_t *optimizer, opcode_t *code_start)
static void sort_registers(Parrot_jit_info_t *jit_info)
static void assign_registers(PARROT_INTERP, Parrot_jit_info_t *jit_info, Parrot_jit_optimizer_section_ptr cur_section, opcode_t *code_start, int from_imcc)
map_registers()
to actually assign the Parrot registers to hardware registers.TODOBefore actually assigning registers,
we should optimize a bit:1) calculate max use count of register types for all sections2) calculate costs for register preserving and restoring for two different allocation strategies:
a) allocate non-volatiles first overhead for jit_begin, jit_end: - 2 * max_used_non_volatile registers overhead for register preserving around non-jitted sections: - only used IN arguments are saved - only OUT non-volatile arguments are restored b) allocate volatiles first no overhead for jit_begin, jit_end overhead per JITed op that calls a C function: - 2 * n_used_volatiles_to_preserve for each call overhead for register preserving around non-jitted sections: - all volatiles are saved and restored around non-jitted sectionsNB for all cost estimations size does matter: a 64bit double counts as two 32bit ints. Opcode count is assumed to be just one.3) depending on costs from 2) use one of the strategies That does still not account for any usage patterns. Imcc has loop nesting depth, but that's not available here. OTOH smaller code tends to perform better because of better cache usage.Usage analysis could show that a mixture of both strategies is best, e.g: allocate 2-4 non-volatiles and the rest from volatiles. But that would complicate the allocation code a bit.
static void map_registers(PARROT_INTERP, Parrot_jit_info_t *jit_info, opcode_t *code_start)
static void debug_sections(PARROT_INTERP, Parrot_jit_optimizer_t *optimizer, opcode_t *code_start)
static Parrot_jit_optimizer_t *optimize_jit(PARROT_INTERP, Parrot_jit_info_t *jit_info, opcode_t *code_start, opcode_t *code_end)
parrot_build_asm()
to run the optimizer.
static Parrot_jit_optimizer_t *optimize_imcc_jit(PARROT_INTERP, Parrot_jit_info_t *jit_info, opcode_t *code_start, opcode_t *code_end, PackFile_Segment *jit_seg)
_JIT
section in the packfile.
size_t reg_offs(int typ, int i)
typ[i]
.src/jit/arch/jit_emit.h has to define Parrot_jit_emit_get_base_reg_no(pc)
static void Parrot_jit_load_registers(Parrot_jit_info_t *jit_info, PARROT_INTERP, int volatiles)
volatiles
is true, this code is used to restore these registers in JITted code that calls out to Parrot.
static void Parrot_jit_save_registers(Parrot_jit_info_t *jit_info, PARROT_INTERP, int volatiles)
volatiles
is true, this code is used to preserve these registers in JITted code that calls out to Parrot.
void Parrot_destroy_jit(void *ptr)
Parrot_jit_info_t *parrot_build_asm(PARROT_INTERP, opcode_t *code_start, opcode_t *code_end, void *objfile, enum_jit_code_type)
parrot -o foo.o foo.pirwhich uses the JIT engine to translate to native code inside the object file.
void Parrot_jit_newfixup(Parrot_jit_info_t *jit_info)
src/jit.h, docs/jit.pod, src/jit_debug.c, src/jit/$jitcpuarch/jit_emit.h, jit/$jitcpuarch/core.jit.
|