61 #include "vm/jit/patcher.hpp"
67 #define BUILTIN_FLOAT_ARGS 1
72 #define REG_PV REG_PV_CALLEE
81 return (disp >= -4096) && (disp <= 4095);
103 s4 sign = (imm >> 12) & 0x1;
106 if ((imm & ~0xfff) == 0)
return true;
109 if ((imm & ~0xfff) + 0xfff == -1)
return true;
111 printf(
"immediate out-of-bounds: %ld\n", imm);
135 #if defined(ENABLE_THREADS)
137 cd->stackframesize++;
142 if (cd->stackframesize & 1)
143 cd->stackframesize++;
206 if (varindex == UNUSED)
227 int new_dest = p + 24;
231 for (i = 0; i < jd->
varcount; i++) {
241 if (
s2 == new_dest) {
248 if (
s2 == old_dest) {
358 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
446 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
460 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
484 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
498 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
522 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
536 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
728 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
748 if ((iptr->
sx.
val.
i >= 0) && (iptr->
sx.
val.
i <= 4095)) {
771 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
789 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
822 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
836 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
860 if ((iptr->
sx.
val.
i >= -4096) && (iptr->
sx.
val.
i <= 4095)) {
874 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1431 uf = iptr->
sx.
s23.s3.uf;
1438 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1439 fieldtype = fi->
type;
1443 codegen_add_patch_ref(cd, PATCHER_clinit, fi->
clazz, disp);
1448 switch (fieldtype) {
1479 uf = iptr->
sx.
s23.s3.uf;
1486 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1487 fieldtype = fi->
type;
1491 codegen_add_patch_ref(cd, PATCHER_clinit, fi->
clazz, disp);
1496 switch (fieldtype) {
1528 uf = iptr->
sx.
s23.s3.uf;
1535 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1536 fieldtype = fi->
type;
1540 codegen_add_patch_ref(cd, PATCHER_clinit, fi->
clazz, disp);
1545 switch (fieldtype) {
1574 uf = iptr->
sx.
s23.s3.uf;
1582 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1583 fieldtype = fi->
type;
1587 switch (fieldtype) {
1621 uf = iptr->
sx.
s23.s3.uf;
1627 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1628 fieldtype = fi->
type;
1640 switch (fieldtype) {
1642 M_IST(s2, s1, disp);
1645 M_STX(s2, s1, disp);
1648 M_AST(s2, s1, disp);
1651 M_FST(s2, s1, disp);
1654 M_DST(s2, s1, disp);
1687 fieldtype = fi->
type;
1693 switch (fieldtype) {
1732 emit_beqz(cd, iptr->
dst.
block, s1);
1734 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1749 emit_bltz(cd, iptr->
dst.
block, s1);
1751 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1766 emit_blez(cd, iptr->
dst.
block, s1);
1768 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1783 emit_bnez(cd, iptr->
dst.
block, s1);
1785 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1800 emit_bgtz(cd, iptr->
dst.
block, s1);
1802 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1817 emit_bgez(cd, iptr->
dst.
block, s1);
1819 if ((iptr->
sx.
val.
l >= -4096) && (iptr->
sx.
val.
l <= 4095)) {
1888 l = iptr->
sx.
s23.s2.tablelow;
1889 i = iptr->
sx.
s23.s3.tablehigh;
1895 else if (-l >= 4096 && -l <= 4095) {
1915 emit_bugt(cd, table[0].
block);
1941 bte = iptr->
sx.
s23.s3.bte;
1945 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
1947 s3 = md->paramcount;
1951 #ifdef BUILTIN_FLOAT_ARGS
1955 int num_fltregargs = 0;
1956 int fltregarg_inswap[16];
1958 for (s3 = s3 - 1; s3 >= 0; s3--) {
1959 var =
VAR(iptr->
sx.
s23.s2.args[s3]);
1962 if (!md->params[s3].inmemory) {
1967 fltregarg_inswap[num_fltregargs] =
s1;
1979 for (i = 0; i < num_fltregargs; i++) {
1980 s1 = fltregarg_inswap[
i];
1986 assert(md->argfltreguse == 0);
1994 if (!md->params[s3].inmemory) {
2007 bte = iptr->
sx.
s23.s3.bte;
2008 if (bte->
stub == NULL) {
2023 if (md->returntype.type ==
TYPE_FLT) {
2035 um = iptr->
sx.
s23.s3.um;
2042 lm = iptr->
sx.
s23.s3.fmiref->p.method;
2058 um = iptr->
sx.
s23.s3.um;
2064 lm = iptr->
sx.
s23.s3.fmiref->p.method;
2083 um = iptr->
sx.
s23.s3.um;
2090 lm = iptr->
sx.
s23.s3.fmiref->p.method;
2145 super = iptr->
sx.
s23.s3.c.cls;
2146 superindex = super->
index;
2153 if (super == NULL) {
2159 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2170 if (super == NULL) {
2200 if (super == NULL) {
2206 codegen_add_patch_ref(cd,
2207 PATCHER_checkcast_instanceof_class,
2233 if (super == NULL) {
2252 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2302 super = iptr->
sx.
s23.s3.c.cls;
2303 superindex = super->
index;
2304 supervftbl = super->
vftbl;
2318 if (super == NULL) {
2324 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2335 if (super == NULL) {
2364 if (super == NULL) {
2370 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2394 if (super == NULL) {
2411 var =
VAR(iptr->
sx.
s23.s2.args[s1]);
2432 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2433 iptr->
sx.
s23.s3.c.ref,
2463 vm_abort(
"Unknown ICMD %d during code generation", iptr->
opc);
2540 #if defined(ENABLE_GC_CACAO)
2648 #if defined(ENABLE_GC_CACAO)
2700 sizeof(stackframeinfo) / SIZEOF_VOID_P +
2724 #if !defined(NDEBUG)
2734 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
2744 fltregarg_offset[
i] =
s1;
2777 for (i = md->
paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
2896 #if !defined(NDEBUG)
void codegen_emit_instruction(jitdata *jd, instruction *iptr)
Generates machine code for one ICMD.
const s4 abi_registers_float_argument[]
s4 dseg_add_double(codegendata *cd, double value)
#define BUILTIN_FAST_canstore
s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
#define REG_RESULT_CALLEE
s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
#define M_ALD(a, b, disp)
#define REG_WINDOW_TRANSPOSE(reg)
#define M_SRAX_IMM(rs1, rs2, rd)
#define M_SRLX_IMM(rs1, rs2, rd)
#define PATCHER_invokeinterface
#define M_CMOVFEQ_IMM(rs, rd)
void emit_ble_xcc(codegendata *cd, basicblock *target)
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
void emit_bne_xcc(codegendata *cd, basicblock *target)
#define M_ILD(a, b, disp)
s4 dseg_add_unique_address(codegendata *cd, void *value)
#define BUILTIN_multianewarray
#define IS_INT_LNG_TYPE(a)
#define M_IST(a, b, disp)
#define PATCHER_get_putfield
const s4 abi_registers_integer_argument[]
#define M_FLD_INTERN(a, b, disp)
#define M_AADD_IMM(a, b, c)
#define M_ADD_IMM(d, a, i)
void emit_bgt_xcc(codegendata *cd, basicblock *target)
s4 dseg_add_address(codegendata *cd, void *value)
#define M_OR_IMM(a, b, c)
s4 dseg_add_unique_double(codegendata *cd, double value)
s4 dseg_add_unique_float(codegendata *cd, float value)
#define dseg_add_functionptr(cd, value)
#define M_IST_INTERN(a, b, disp)
void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
#define M_SLLX(rs1, rs2, rd)
#define M_STX_INTERN(rd, rs, disp)
#define M_STX(rd, rs, disp)
void emit_patcher_stubs(jitdata *jd)
void emit_arraystore_check(codegendata *cd, instruction *iptr)
#define M_FST(a, b, disp)
#define M_FLD(a, b, disp)
void dseg_add_target(codegendata *cd, basicblock *target)
#define M_LDX(rd, rs, disp)
java_object_t * codegen_finish_native_call(u1 *sp, u1 *pv)
#define M_SRAX(rs1, rs2, rd)
const s4 abi_registers_integer_saved[]
#define M_CMOVFGT_IMM(rs, rd)
JNIEnv jthread jobject jclass jlong size
void emit_bge_xcc(codegendata *cd, basicblock *target)
#define M_CMOVRNE_IMM(rs1, rs2, rd)
#define PATCHER_get_putstatic
static int code_is_leafmethod(codeinfo *code)
#define BUILTIN_arraycheckcast
#define M_MULX(rs1, rs2, rd)
void emit_blt_xcc(codegendata *cd, basicblock *target)
void vm_abort(const char *text,...)
void(* functionptr)(void)
#define M_SAVE(rs1, rs2, rd)
void emit_verbosecall_enter(jitdata *jd)
java_handle_t * codegen_start_native_call(u1 *sp, u1 *pv)
#define PATCHER_instanceof_interface
#define IS_2_WORD_TYPE(a)
void emit_exception_check(codegendata *cd, instruction *iptr)
s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
#define M_XOR_IMM(a, b, c)
#define M_SST(a, b, disp)
#define M_DIVX(rs1, rs2, rd)
constant_FMIref * fieldref
void emit_label_br(codegendata *cd, s4 label)
#define M_CMOVFLT_IMM(rs, rd)
s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
#define IS_FLT_DBL_TYPE(a)
void emit_beq_xcc(codegendata *cd, basicblock *target)
#define M_ALD_INTERN(a, b, disp)
#define M_SRL_IMM(a, b, c)
#define M_MULX_IMM(rs1, rs2, rd)
#define REG_RESULT_CALLER
#define M_SLLX_IMM(rs1, rs2, rd)
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
#define M_XCMOVGT_IMM(rs, rd)
s4 dseg_add_unique_s4(codegendata *cd, s4 value)
#define M_AST(a, b, disp)
union instruction::@12 sx
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
#define M_SUB_IMM(d, a, i)
void asm_handle_exception(void)
#define PATCHER_checkcast_interface
#define M_ASLL_IMM(a, b, c)
#define M_RETURN(rs1, imm)
void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
#define PATCHER_invokestatic_special
#define M_BST(a, b, disp)
#define M_FMOV_INTERN(rs, rd)
void codegen_emit_stub_compiler(jitdata *jd)
#define M_FST_INTERN(a, b, disp)
#define M_SRA_IMM(a, b, c)
#define M_AND_IMM(a, b, c)
#define PATCHER_invokevirtual
#define M_SLL_IMM(a, b, c)
static bool IS_INMEMORY(s4 flags)
void codegen_emit_epilog(jitdata *jd)
Generates machine code for the method epilog.
#define M_AST_INTERN(a, b, c)
void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
#define M_LDX_INTERN(rd, rs, disp)
void asm_handle_nat_exception(void)
#define M_BLDS(a, b, disp)
#define M_DLD_INTERN(a, b, disp)
static bool class_is_or_almost_initialized(classinfo *c)
static int code_is_synchronized(codeinfo *code)
#define M_RESTORE(rs1, rs2, rd)
#define M_DST(a, b, disp)
#define INSTRUCTION_IS_UNRESOLVED(iptr)
struct instruction::@12::@13 s23
#define M_XCMOVULE_IMM(rs, rd)
void codegen_emit_prolog(jitdata *jd)
Generates machine code for the method prolog.
const parseddesc_t parseddesc
static void emit_fmove(codegendata *cd, int s, int d)
Generates a float-move from register s to d.
#define M_XCMOVLT_IMM(rs, rd)
#define M_SRLX(rs1, rs2, rd)
void emit_label(codegendata *cd, s4 label)
#define M_SLDU(a, b, disp)
bool check_13bit_imm(s8 imm)
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
static void emit_dmove(codegendata *cd, int s, int d)
Generates an double-move from register s to d.
#define M_DLD(a, b, disp)
void emit_verbosecall_exit(jitdata *jd)
#define M_SAVE_REG(rs1, rs2, rd)
s4 dseg_add_float(codegendata *cd, float value)
#define M_SLDS(a, b, disp)
void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
bool codegen_emit(jitdata *jd)
Generates machine code.
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
static VM * get_current()
#define M_DST_INTERN(a, b, disp)
#define M_ILD_INTERN(a, b, disp)