// inputs should be preserved outside if required since we do a call // num_std_need_to_save registers will be preserved char * m2n_gen_push_m2n(char * buf, Method_Handle method, frame_type current_frame_type, bool handles, unsigned num_callee_saves, unsigned num_std_need_to_save, I_32 bytes_to_m2n_top) { // skip callee-saves registers bytes_to_m2n_top -= num_callee_saves * LcgEM64TContext::GR_SIZE; // TODO: check if it makes sense to save all callee-saves registers here //store rest of callee-saves registers for (unsigned i = num_callee_saves; i < LcgEM64TContext::MAX_GR_LOCALS; i++) { bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), LcgEM64TContext::get_reg_from_map(LcgEM64TContext::GR_LOCALS_OFFSET + i), size_64); } // init pop_regs to null bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), Imm_Opnd(size_32, 0), size_64); // store current_frame_type bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; assert(fit32(current_frame_type)); buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), Imm_Opnd(size_32, current_frame_type), size_64); // store a method associated with the current m2n frame bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; if (fit32((int64)method)) { buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), Imm_Opnd(size_32, (int64)method), size_64); } else { buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (int64)method), size_64); buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), rax_opnd); } // store local object handles bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), Imm_Opnd(size_64, (int64)0), size_64); // move pointer to the current VM_Thread structure to rax buf = m2n_gen_ts_to_register(buf, &rax_opnd, num_callee_saves, LcgEM64TContext::MAX_GR_LOCALS, num_std_need_to_save, 0); // shift to the last_m2n_frame field I_32 last_m2n_frame_offset = (I_32)(int64)&((VM_thread*)0)->last_m2n_frame; buf = alu(buf, add_opc, rax_opnd, Imm_Opnd(size_32, last_m2n_frame_offset), size_64); // store pointer to pointer to last m2n frame bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), rax_opnd, size_64); // save pointer to the previous m2n frame bytes_to_m2n_top -= LcgEM64TContext::GR_SIZE; buf = mov(buf, r9_opnd, M_Base_Opnd(rax_reg, 0)); buf = mov(buf, M_Base_Opnd(rsp_reg, bytes_to_m2n_top), r9_opnd, size_64); // update last m2n frame of the current thread buf = lea(buf, r9_opnd, M_Base_Opnd(rsp_reg, bytes_to_m2n_top)); buf = mov(buf, M_Base_Opnd(rax_reg, 0), r9_opnd, size_64); return buf; }
bool RuntimeInterface::isSOEArea(MethodDesc* methodDesc, const ::JitFrameContext* context, bool isFirst) { #ifdef _EM64T_ POINTER_SIZE_INT eip = *context->p_rip; #else POINTER_SIZE_INT eip = *context->p_eip; #endif StackInfo stackInfo; stackInfo.read(methodDesc, eip, isFirst); assert(eip >= (POINTER_SIZE_INT)methodDesc->getCodeBlockAddress(0)); POINTER_SIZE_INT eipOffset = eip - (POINTER_SIZE_INT)methodDesc->getCodeBlockAddress(0); assert(fit32(eipOffset)); return eipOffset<=stackInfo.getSOECheckAreaOffset(); }
void StackInfo::read(MethodDesc* pMethodDesc, POINTER_SIZE_INT eip, bool isFirst) { U_8* data = pMethodDesc->getInfoBlock(); byteSize = ((StackInfo *)data)->byteSize; hashTableSize = ((StackInfo *)data)->hashTableSize; frameSize = ((StackInfo *)data)->frameSize; icalleeOffset = ((StackInfo *)data)->icalleeOffset; icalleeMask = ((StackInfo *)data)->icalleeMask; localOffset = ((StackInfo *)data)->localOffset; offsetOfThis = ((StackInfo *)data)->offsetOfThis; itraceMethodExitString = ((StackInfo *)data)->itraceMethodExitString; soeCheckAreaOffset = ((StackInfo *)data)->soeCheckAreaOffset; if (!isFirst){ DepthEntry * entry = getHashEntry(data, eip, hashTableSize); assert(entry); if (!entry){ if (Log::cat_rt()->isEnabled()) Log::cat_rt()->out()<<"eip=0x"<<(void*)eip<<" not found during stack unwinding!"<<::std::endl; ::std::cerr<<"eip=0x"<<(void*)eip<<" not found during stack unwinding!"<<::std::endl; } calleeSaveRegsMask = entry->info.calleeSaveRegs; stackDepth = entry->info.stackDepth; }else{ assert(eip >= (POINTER_SIZE_INT)pMethodDesc->getCodeBlockAddress(0)); POINTER_SIZE_INT eipOffset = eip - (POINTER_SIZE_INT)pMethodDesc->getCodeBlockAddress(0); assert(fit32(eipOffset)); if (eipOffset <= soeCheckAreaOffset) { stackDepth = 0; //0 depth -> stack overflow error } else { DepthEntry * entry = NULL; U_32 i = CALL_MIN_SIZE; for (; i<= CALL_MAX_SIZE; i++) { entry = getHashEntry(data, eip + i, hashTableSize); if(entry) break; } if (entry && (entry->info.callSize == i)) { stackDepth = entry->info.stackDepth; //call site's depth } else { stackDepth = frameSize; //hardware NPE's depth } } if (Log::cat_rt()->isEnabled()) Log::cat_rt()->out()<<"Hardware exception from eip=0x"<<(void*)eip<<::std::endl; } }