/* * Check the contents of a register for NULL and re-execute * the current instruction in the interpreter if it is. * If null check elmination is enabled, this function does nothing. */ static void CheckForNull(MDUnroll *unroll, int reg, unsigned char *pc, unsigned char *label, int popReg) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_inst_ptr patch; /* Check the register's contents against NULL */ md_reg_is_null(unroll->out, reg); patch = unroll->out; #ifdef CVM_X86 x86_branch8(unroll->out, X86_CC_NE, 0, 0); #else md_branch_ne(unroll->out); #endif /* Re-execute the current instruction in the interpreter */ if(popReg) { --(unroll->pseudoStackSize); ReExecute(unroll, pc, label); ++(unroll->pseudoStackSize); } else { ReExecute(unroll, pc, label); } /* Continue with real execution here */ md_patch(patch, unroll->out); #endif }
static void Divide(MDUnroll *unroll, int isSigned, int wantRemainder, unsigned char *pc, unsigned char *label) { #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) #define IL_NEED_DIVIDE_REEXECUTE 1 #endif int reg, reg2; #ifdef IL_NEED_DIVIDE_REEXECUTE md_inst_ptr patch1 = NULL; md_inst_ptr patch2 = NULL; md_inst_ptr patch3 = NULL; #endif GetTopTwoWordRegisters(unroll, ®, ®2, MD_REG1_32BIT | MD_REG2_32BIT); #ifdef IL_NEED_DIVIDE_REEXECUTE md_reg_is_zero(unroll->out, reg2); patch1 = unroll->out; md_branch_eq(unroll->out); if(isSigned) { md_cmp_reg_imm_word_32(unroll->out, MD_CC_EQ, reg2, -1); patch2 = unroll->out; md_branch_ne(unroll->out); md_cmp_reg_imm_word_32(unroll->out, MD_CC_EQ, reg, IL_MIN_INT32); patch3 = unroll->out; md_branch_ne(unroll->out); } md_patch(patch1, unroll->out); ReExecute(unroll, pc, label); if(isSigned) { md_patch(patch2, unroll->out); md_patch(patch3, unroll->out); } #endif if(wantRemainder) { if(isSigned) { md_rem_reg_reg_word_32(unroll->out, reg, reg2); } else { md_urem_reg_reg_word_32(unroll->out, reg, reg2); } } else { if(isSigned) { md_div_reg_reg_word_32(unroll->out, reg, reg2); } else { md_udiv_reg_reg_word_32(unroll->out, reg, reg2); } } FreeTopRegister(unroll, -1); }
/* * Check an array access operation for exception conditions. */ static void CheckArrayAccess(MDUnroll *unroll, int reg, int reg2, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_inst_ptr patch1; #endif md_inst_ptr patch2; #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Check the array reference against NULL */ md_reg_is_null(unroll->out, reg); patch1 = unroll->out; #ifdef CVM_X86 x86_branch8(unroll->out, X86_CC_EQ, 0, 0); #else md_branch_eq(unroll->out); #endif #endif /* Check the array bounds */ md_bounds_check(unroll->out, reg, reg2); patch2 = unroll->out; md_branch_lt_un(unroll->out); #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Re-execute the current instruction in the interpreter */ md_patch(patch1, unroll->out); #endif ReExecute(unroll, pc, label); /* Continue with real execution here */ md_patch(patch2, unroll->out); }
/* * Check a 2D array access operation for exception conditions. */ static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_inst_ptr patch1; #endif md_inst_ptr patch2; md_inst_ptr patch3; #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Check the array reference against NULL */ arm_test_reg_imm8(unroll->out, ARM_CMP, reg, 0); patch1 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_EQ, 0); #endif /* Check the array bounds. We assume that we can use the link register as a work register because "lr" would have been saved on entry to "_ILCVMInterpreter" */ arm_load_membase(unroll->out, ARM_WORK, reg, 12); arm_alu_reg_reg(unroll->out, ARM_SUB, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, ARM_LINK, reg, 16); arm_test_reg_reg(unroll->out, ARM_CMP, reg2, ARM_LINK); patch2 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_LT_UN, 0); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, ARM_WORK); patch3 = unroll->out; arm_jump_imm(unroll->out, 0); arm_patch(patch2, unroll->out); arm_load_membase(unroll->out, ARM_WORK, reg, 24); arm_alu_reg_reg(unroll->out, ARM_SUB, reg3, reg3, ARM_WORK); arm_load_membase(unroll->out, ARM_LINK, reg, 28); arm_test_reg_reg(unroll->out, ARM_CMP, reg3, ARM_LINK); patch2 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_LT_UN, 0); arm_alu_reg_reg(unroll->out, ARM_ADD, reg3, reg3, ARM_WORK); arm_load_membase(unroll->out, ARM_WORK, reg, 12); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, ARM_WORK); /* Re-execute the current instruction in the interpreter */ #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS arm_patch(patch1, unroll->out); #endif arm_patch(patch3, unroll->out); ReExecute(unroll, pc, label); /* Compute the address of the array element */ arm_patch(patch2, unroll->out); arm_load_membase(unroll->out, ARM_WORK, reg, 20); arm_mul_reg_reg(unroll->out, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, ARM_WORK, reg, 32); arm_mul_reg_reg(unroll->out, reg3, reg3, ARM_WORK); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, reg3); arm_load_membase(unroll->out, ARM_WORK, reg, 4); arm_mul_reg_reg(unroll->out, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, reg, reg, 8); arm_alu_reg_reg(unroll->out, ARM_ADD, reg, reg, reg2); }
// Thread that waits for forfig change and then restarts the program static void * Config_Monitor_Watchthread( void * v) { DETACH_THREAD ; // Blocking call until a config change detected Config_Monitor_Block() ; LEVEL_DEBUG("Configuration file change detected. Will restart %s",Globals.argv[0]); // Restart the program ReExecute(v) ; return v ; }
/* * Check a 2D array access operation for exception conditions. */ static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS unsigned char *patch1; #endif unsigned char *patch2; unsigned char *patch3; #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Check the array reference against NULL */ x86_alu_reg_reg(unroll->out, X86_OR, reg, reg); patch1 = unroll->out; x86_branch8(unroll->out, X86_CC_EQ, 0, 0); #endif /* Check the array bounds */ x86_alu_reg_membase(unroll->out, X86_SUB, reg2, reg, 12); x86_alu_reg_membase(unroll->out, X86_CMP, reg2, reg, 16); patch2 = unroll->out; x86_branch32(unroll->out, X86_CC_LT, 0, 0); x86_alu_reg_membase(unroll->out, X86_ADD, reg2, reg, 12); patch3 = unroll->out; x86_jump8(unroll->out, 0); x86_patch(patch2, unroll->out); x86_alu_reg_membase(unroll->out, X86_SUB, reg3, reg, 24); x86_alu_reg_membase(unroll->out, X86_CMP, reg3, reg, 28); patch2 = unroll->out; x86_branch32(unroll->out, X86_CC_LT, 0, 0); x86_alu_reg_membase(unroll->out, X86_ADD, reg2, reg, 12); x86_alu_reg_membase(unroll->out, X86_ADD, reg3, reg, 28); /* Re-execute the current instruction in the interpreter */ #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS x86_patch(patch1, unroll->out); #endif x86_patch(patch3, unroll->out); ReExecute(unroll, pc, label); /* Compute the address of the array element */ x86_patch(patch2, unroll->out); x86_imul_reg_membase(unroll->out, reg2, reg, 20); x86_imul_reg_membase(unroll->out, reg3, reg, 32); x86_alu_reg_reg(unroll->out, X86_ADD, reg2, reg3); x86_imul_reg_membase(unroll->out, reg2, reg, 4); x86_mov_reg_membase(unroll->out, reg, reg, 8, 4); x86_alu_reg_reg(unroll->out, X86_ADD, reg, reg2); }
/* * Perform an integer division or remainder. */ static void Divide(MDUnroll *unroll, int isSigned, int wantRemainder, unsigned char *pc, unsigned char *label) { #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) #define IL_NEED_DIVIDE_REEXECUTE 1 unsigned char *patch1; #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) #define IL_NEED_DIVIDE_REEXECUTE 1 unsigned char *patch2, *patch3; #endif /* Get the arguments into EAX and ECX so we know where they are */ if(unroll->pseudoStackSize != 2 || unroll->pseudoStack[0] != X86_EAX || unroll->pseudoStack[1] != X86_ECX) { FlushRegisterStack(unroll); unroll->stackHeight -= 8; x86_mov_reg_membase(unroll->out, X86_EAX, MD_REG_STACK, unroll->stackHeight, 4); x86_mov_reg_membase(unroll->out, X86_ECX, MD_REG_STACK, unroll->stackHeight + 4, 4); unroll->pseudoStack[0] = X86_EAX; unroll->pseudoStack[1] = X86_ECX; unroll->pseudoStackSize = 2; unroll->regsUsed |= ((1 << X86_EAX) | (1 << X86_ECX)); } /* Check for conditions that may cause an exception */ #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, 0); patch1 = unroll->out; x86_branch8(unroll->out, X86_CC_EQ, 0, 0); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, -1); patch2 = unroll->out; x86_branch32(unroll->out, X86_CC_NE, 0, 0); x86_alu_reg_imm(unroll->out, X86_CMP, X86_EAX, (int)0x80000000); patch3 = unroll->out; x86_branch32(unroll->out, X86_CC_NE, 0, 0); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS) x86_patch(patch1, unroll->out); #endif #if defined(IL_NEED_DIVIDE_REEXECUTE) /* Re-execute the division instruction to throw the exception */ ReExecute(unroll, pc, label); #endif #if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS) x86_patch(patch2, unroll->out); x86_patch(patch3, unroll->out); #endif /* Perform the division */ if(isSigned) { x86_cdq(unroll->out); } else { x86_clear_reg(unroll->out, X86_EDX); } x86_div_reg(unroll->out, X86_ECX, isSigned); /* Pop ECX from the pseudo stack */ FreeTopRegister(unroll, -1); /* If we want the remainder, then replace EAX with EDX on the stack */ if(wantRemainder) { unroll->pseudoStack[0] = X86_EDX; unroll->regsUsed = (1 << X86_EDX); } }
static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_inst_ptr patch1; #endif md_inst_ptr patch2; md_inst_ptr patch3; /* redefinitions to make it a lot clearer for me to debug */ int array = reg; int i = reg2; int j = reg3; int work = PPC_WORK; /* Algorithm of calc_address: a->data + (((i - a->bounds[0].lower) * a->bounds[0].multiplier) + (j - a->bounds[1].lower) * a->bounds[0].multiplier)) * a->elemSize) I've tried to pre-compute a->bounds into bounds (or MD_REG_PC) */ #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_reg_is_null(unroll->out, reg); patch1 = unroll->out; md_branch_eq(unroll->out); #endif md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, lower)); md_sub_reg_reg_word_32(unroll->out, i, work); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, size)); md_cmp_cc_reg_reg_word_32(unroll->out, MD_CC_GE_UN, i, work); patch2 = unroll->out; md_branch_ge_un(unroll->out); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, lower)); md_sub_reg_reg_word_32(unroll->out, j, work); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, size)); md_cmp_cc_reg_reg_word_32(unroll->out, MD_CC_GE_UN, j, work); patch3 = unroll->out; md_branch_lt_un(unroll->out); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, lower)); md_add_reg_reg_word_32(unroll->out, j, work); md_patch(patch2, unroll->out); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, lower)); md_add_reg_reg_word_32(unroll->out, i, work); #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_patch(patch1, unroll->out); #endif ReExecute(unroll, pc, label); /* calculate address */ md_patch(patch3, unroll->out); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, multiplier)); md_mul_reg_reg_word_32(unroll->out, i, work); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, multiplier)); md_mul_reg_reg_word_32(unroll->out, j, work); md_load_membase_word_32(unroll->out, work, array, offsetof(System_MArray, elemSize)); md_add_reg_reg_word_32(unroll->out, i, j); md_load_membase_word_native(unroll->out, reg, array, offsetof(System_MArray, data)); md_mul_reg_reg_word_32(unroll->out, i, work); ppc_cache_prefetch(unroll->out, reg, i); md_reg_to_word_native(unroll->out, i); md_add_reg_reg_word_native(unroll->out, reg, i); }
/* * Check a 2D array access operation for exception conditions. */ static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS unsigned char *patch1; #endif unsigned char *patch2; unsigned char *patch3; #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Check the array reference against NULL */ amd64_alu_reg_reg(unroll->out, X86_OR, reg, reg); patch1 = unroll->out; amd64_branch8(unroll->out, X86_CC_EQ, 0, 0); #endif /* a->data + (((i - a->bounds[0].lower) * a->bounds[0].multiplier) + (j - a->bounds[1].lower) * a->bounds[0].multiplier)) * a->elemSize) as follows i = i - a->bounds[0].lower j = j - a->bounds[1].lower i = i * a->bounds[0].multiplier j = j * a->bounds[1].multiplier i = i + j i = i * a->elemSize a = a->data a = a + i */ /* Check the array bounds (all of which are ILInt32) */ amd64_alu_reg_membase_size(unroll->out, X86_SUB, reg2, reg, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, lower), 4); /* i = i - a->bounds[0].lower */ amd64_alu_reg_membase_size(unroll->out, X86_CMP, reg2, reg, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, size), 4); patch2 = unroll->out; amd64_branch32(unroll->out, X86_CC_LT, 0, 0); amd64_alu_reg_membase_size(unroll->out, X86_ADD, reg2, reg, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, lower), 4); patch3 = unroll->out; amd64_jump8(unroll->out, 0); amd64_patch(patch2, unroll->out); amd64_alu_reg_membase_size(unroll->out, X86_SUB, reg3, reg, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, lower), 4); /* j = j - a->bounds[1].lower */ amd64_alu_reg_membase_size(unroll->out, X86_CMP, reg3, reg, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, size), 4); patch2 = unroll->out; amd64_branch32(unroll->out, X86_CC_LT, 0, 0); amd64_alu_reg_membase_size(unroll->out, X86_ADD, reg2, reg, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, lower), 4); amd64_alu_reg_membase_size(unroll->out, X86_ADD, reg3, reg, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, lower), 4); /* Re-execute the current instruction in the interpreter */ #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS amd64_patch(patch1, unroll->out); #endif amd64_patch(patch3, unroll->out); ReExecute(unroll, pc, label); /* Compute the address of the array element */ amd64_patch(patch2, unroll->out); amd64_imul_reg_membase_size(unroll->out, reg2, reg, offsetof(System_MArray, bounds) + offsetof(MArrayBounds, multiplier), 4); /* i = i * a->bounds[0].multiplier */ amd64_imul_reg_membase_size(unroll->out, reg3, reg, offsetof(System_MArray, bounds) + sizeof(MArrayBounds) + offsetof(MArrayBounds, multiplier), 4); /* j = j * a->bounds[1].multiplier */ amd64_alu_reg_reg(unroll->out, X86_ADD, reg2, reg3); /* i = i + j */ amd64_imul_reg_membase_size(unroll->out, reg2, reg, offsetof(System_MArray, elemSize), 4); /* i = i * a->elemSize */ amd64_mov_reg_membase(unroll->out, reg, reg, offsetof(System_MArray, data), 8); /* a = a->data */ /* up-convert to 32 bit */ amd64_movsxd_reg_reg(unroll->out, reg2, reg2); amd64_alu_reg_reg(unroll->out, X86_ADD, reg, reg2); /* a = a + i */ }