# Copyright (C) 2001-2006, The Perl Foundation. # $Id: jit.pod 12981 2006-06-20 19:26:31Z bernhard $ =head1 NAME docs/jit.pod - Parrot JIT Subsystem =head1 ABSTRACT This PDD describes the Parrot Just In Time compilation subsystem. =head1 DESCRIPTION The Just In Time, or JIT, subsystem converts a bytecode file to native machine code instructions and executes the generated instruction sequence directly. =head1 IMPLEMENTATION Currently works on B, B, B, B, and B processor systems, on most operating systems. Currently only 32-bit INTVALs are supported. The initial step in generating native code is to invoke B, which generally provides architecture specific preamble code. For each parrot opcode in the bytecode, either a generic or opcode specific sequence of native code is generated. The F<.jit> files provide functions that generate native code for specific opcode functions, for a given instruction set architecture. If a function is not provided for a specific opcode, a generic sequence of native code is output which calls the interpreter C function that implements the opcode. Such opcode are handled by B. If the opcode can cause a control flow change, as in the case of a branch or call opcode, an extended or modified version of this generic code is used that tracks changes in the bytecode program counter with changes in the hardware program counter. This type of opcode is handled by B. While generating native code, certain offsets and absolute addresses may not be available. This occurs with forward opcode branches, as the native code corresponding to the branch target has not yet been generated. On some platforms, function calls are performed using program-counter relative addresses. Since the location of the buffer holding the native code may move as code is generated (due to growing of the buffer), these relative addresses may only be calculated once the buffer is guaranteed to no longer move. To handle these instances, the JIT subsystem uses "fixups", which record locations in native code where adjustments to the native code are required. =head1 FILES =over 4 =item jit/${jitcpuarch}/jit_emit.h This file defines B, B, B, B, B and optionally B. In addition, this file defines the macros and static functions used in F<.jit> files to produce binary representations of native instructions. For moving registers from processor to parrot and vice versa, the B functions have to be implemented. =item jit/${jitcpuarch}/core.jit The functions to generate native code for core parrot opcodes are specified here. To simplify the maintenance of these functions, they are specified in a format that is pre-processed by F to produce a valid C source file, F. See L below. =item src/jit.h This file contains definitions of generic structures used by the JIT subsystem. The B array of B structures, provides for each opcode, a pointer to the function that generates native code for the opcode, whether the generic B or B functions or an opcode specific function. B is like B with the addition to check for a zero program counter. The B functions are defined as B or B and may be implemented to do native vtable calls (s. F for an example). The B structure records the offset in native code where a fixup must be applied, the type of fixup required and the specific information needed to perform the parameters of the fixup. Currently, a fixup parameter is either an B value or a function pointer. The B structure holds data used while producing and executing native code. An important piece of data in this structure is the B array, which maps from opcode addresses to native code addresses. =item src/jit.c B() is the main routine of the code generator, which loops over the parrot bytecode, calling the code generating routines for each opcode while filling in the B array. This array is used by the JIT subsystem to perform certain types of fixups on native code, as well as by the native code itself to convert bytecode program counters values (opcode_t *'s) to hardware program counter values. The bytecode is considered an array of B sized elements, with parallel entries in B. B is initially populated with the offsets into the native code corresponding to the opcodes in the bytecode. Once code generation is complete and fixups have been applied, the native code offsets are converted to absolute addresses. This trades the low up-front cost of converting all offsets once, for the unknown cost of repeatedly converting these offsets while executing native code. See F for details. =item tools/build/jit2c.pl Preprocesses the .jit files to produce F. =back =head1 Defines in jit_emit.h The architecture specific F file communicates some defines and tables with F and F. The structure of the file and the defines must therefore follow a specific syntax. =head2 Overall structure #if JIT_EMIT ... emit code #else ... defines static const jit_arch_info arch_info = { ... initialization of maps ... and possibly private static functions } #endif See F for a more detailed explanation. =head2 Defines XXX most are moved into C now. =over 4 =item INT_REGISTERS_TO_MAP This is the amount of integer registers to be mapped to processor registers. The corresponding B has to have exactly this amount of register numbers. A register with the value of zero can not be in the list. =item FLOAT_REGISTERS_TO_MAP When this is defined, it works like above for floating point registers. =item PRESERVED_INT_REGS When this is defined, it's the amount of integer registers, that are preserved over function calls. These preserved registers have to be first in B. When this is not defined, it is assumed that B registers are preserved over function calls. =item PRESERVED_FLOAT_REGS Same for floating point registers. =item jit_emit_noop(pc) =item JUMP_ALIGN If these are defined, B should be a small number stating the desired alignment of jump targets is B<1 << JUMP_ALIGN>. The B gets called with the unaligned B repeatedly, until the B has the desired alignment. So the function can either emit a one byte B instruction, or a B like instruction (sequence) with the desired size, to achieve the necessary padding. The emitted code must not have any side effects. =item ALLOCATE_REGISTERS_PER_SECTION Normally F does register allocation per section, but there is a somewhat experimental feature, to allocate registers per basic block. =item MAP Jit code generated by the F JIT optimizer used negative numbers for mapped registers and positive numbers for non mapped parrot registers. To use this feature, the definition of mapped registers can be redefined like so: #define MAP(i) OMAP(i) #undef MAP #define MAP(i) (i) >= 0 ? 0 : OMAP(i) =item Parrot_jit_emit_get_base_reg_no(pc) This macro should return the register number of the register base pointer. =back See F for actual usage of these defines. =head1 Format of .jit Files Jit files are interpreted as follows: =over 4 =item I { \n I \n } Where I is the name of the Parrot opcode, and I consists of C syntax code which may contain any of the identifiers listed in the following section. The closing curly brace has to be in the first column. =item Comment lines Comments are marked with a I<;> in the first column. These and empty lines are ignored. =item Identifiers In general, prefixing an identifier with I<&> yields an address. The I<*> prefix specifies a value. Since Parrot register values vary during code execution, their values can not be obtained through identifier substitution alone, therefore offsets are used for accessing registers. To obtain register offsets, a set of macros exists, that have C in their names: B ... B ... B Gets replaced by the C constant specified in the Ith argument. B Gets replaced by the C constant specified in the Ith argument. B The Ith integer or floating processor register, mapped in this section. Note: The register with the physical number zero can not be mapped. =begin unimp B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. B Gets replaced by C of the C constant specified in the Ith argument. =end unimp B Gets replaced by the current native program counter. B<*CUR_OPCODE[n]> Gets replaced by the address of the current opcode in the Parrot bytecode. B B The Ith integer or floating point scratch register. =item B