Index: vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (revision 506974) +++ vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (working copy) @@ -458,9 +458,8 @@ for( BasicBlock * bb = (BasicBlock*)irManager->getFlowGraph()->getEntryNode(); bb != NULL; bb=bb->getLayoutSucc()) { uint64 bcOffset; for (Inst* inst = (Inst*)bb->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) { - if (inst->hasKind(Inst::Kind_ControlTransferInst) && - ((ControlTransferInst*)inst)->isDirect() - ){ + if (inst->hasKind(Inst::Kind_ControlTransferInst)) { + if ( ((ControlTransferInst*)inst)->isDirect()) { uint8 * instCodeStartAddr=(uint8*)inst->getCodeStartAddr(); uint8 * instCodeEndAddr=(uint8*)instCodeStartAddr+inst->getCodeSize(); uint8 * targetCodeStartAddr=0; @@ -476,9 +475,10 @@ }else continue; int64 offset=targetCodeStartAddr-instCodeEndAddr; - #ifdef _EM64T_ if (llabs(offset) > 0xFFFFFFFF) { + // actually we should not get here in case of correct work of constraint resolver + assert(0); const RegName TMP_BASE = RegName_R14; EncoderBase::Operands args; args.clear(); @@ -493,45 +493,66 @@ inst->getOpnd(targetOpndIndex)->assignImmValue((int64)offset); // re-emit the instruction: inst->emit(instCodeStartAddr); - - if (inst->hasKind(Inst::Kind_CallInst)){ - registerDirectCall(inst); - } #ifdef _EM64T_ } #endif - } + } // direct CT re-emitting finished + + // register call for code patching + if (inst->hasKind(Inst::Kind_CallInst)){ + registerDirectCall(inst); + } + } // todo64 - if (isBcRequired) { - uint64 instID = inst->getId(); - bcOffset = bc2LIRMapHandler->getVectorEntry(instID); + if (isBcRequired) { + uint64 instID = inst->getId(); + bcOffset = bc2LIRMapHandler->getVectorEntry(instID); - if (bcOffset != ILLEGAL_VALUE) { - POINTER_SIZE_INT instStartAddr = (POINTER_SIZE_INT) inst->getCodeStartAddr(); - bcMap->setEntry((uint64) instStartAddr, bcOffset); - } - } - } - } + if (bcOffset != ILLEGAL_VALUE) { + POINTER_SIZE_INT instStartAddr = (POINTER_SIZE_INT) inst->getCodeStartAddr(); + bcMap->setEntry((uint64) instStartAddr, bcOffset); + } + } + } // inst iteration + } // node iteration } //________________________________________________________________________________________ void CodeEmitter::registerDirectCall(Inst * inst) { - assert(inst->hasKind(Inst::Kind_CallInst) && ((CallInst*)inst)->isDirect()); + assert(inst->hasKind(Inst::Kind_CallInst)); CallInst * callInst=(CallInst*)inst; Opnd * targetOpnd=callInst->getOpnd(callInst->getTargetOpndIndex()); - assert(targetOpnd->isPlacedIn(OpndKind_Imm)); - Opnd::RuntimeInfo * ri=targetOpnd->getRuntimeInfo(); + Opnd::RuntimeInfo * ri = (targetOpnd->isPlacedIn(OpndKind_Imm)) ? targetOpnd->getRuntimeInfo() : NULL; - if( !ri || ri->getKind() != Opnd::RuntimeInfo::Kind_MethodDirectAddr) { return; }; + MethodDesc * md = NULL; + void* addrForFuturePatching = 0; - MethodDesc * md = (MethodDesc*)ri->getValue(0); - irManager->getCompilationInterface().setNotifyWhenMethodIsRecompiled(md,inst->getCodeStartAddr()); - if (Log::isEnabled()) { - Log::out() << "Registered call to " << md->getParentType()->getName() << "." << md->getName() << " at "; - Log::out() << inst->getCodeStartAddr() << " for recompiled method event" << ::std::endl; + if( ri && ri->getKind() == Opnd::RuntimeInfo::Kind_MethodDirectAddr) { // simple direct call + md = (MethodDesc*)ri->getValue(0); + addrForFuturePatching = (void*)((POINTER_SIZE_INT)inst->getCodeStartAddr()+1); // +1 - skipping CALL opcode + if (Log::isEnabled()) { + Log::out() << "Registered call to " << md->getParentType()->getName() << "." << md->getName() << " at "; + Log::out() << inst->getCodeStartAddr() << " for recompiled method event" << ::std::endl; + } + } else { + Inst* targetDef = targetOpnd->getDefiningInst(); + Opnd* targetVal = (targetDef && targetDef->getMnemonic()==Mnemonic_MOV) ? targetDef->getOpnd(1) : NULL; + Opnd::RuntimeInfo* targetValRI = (targetVal && targetVal->isPlacedIn(OpndKind_Imm)) ? targetVal->getRuntimeInfo() : NULL; + if (targetValRI && targetValRI->getKind()==Opnd::RuntimeInfo::Kind_MethodDirectAddr) { // pseudo direct call + md = (MethodDesc*)targetValRI->getValue(0); + addrForFuturePatching = (void*)((POINTER_SIZE_INT)targetDef->getCodeStartAddr()+2); // +2 - skipping REX flag and MOV opcode + if (Log::isEnabled()) { + Log::out() << "Registered mov (of target for call to " << md->getParentType()->getName() << "." << md->getName() << ") at (mov addr)"; + Log::out() << targetDef->getCodeStartAddr() << " for recompiled method event" << ::std::endl; + } + } else { + return; + } } + assert(md); + assert(addrForFuturePatching); + irManager->getCompilationInterface().setNotifyWhenMethodIsRecompiled(md,addrForFuturePatching); } //________________________________________________________________________________________ @@ -541,15 +562,30 @@ { Byte ** indirectAddr = (Byte **)recompiledMethodDesc->getIndirectAddress(); Byte * targetAddr = *indirectAddr; - Byte * callAddr = (Byte*)data; - uint32 offset = targetAddr - callAddr-5; + Byte * addrForPatching = (Byte*)data; + POINTER_SIZE_INT valueForPatching = 0; + Byte * opcodeAddr = addrForPatching - 1; // CALL and MOV opcodes fits into 1 byte + + Byte opcode = *opcodeAddr; + + if ( 0xB8 == (opcode&0xF8) ) { // MOV opcode (&0xF8 - to skip rd bits) + // value is an absolute address + valueForPatching = (POINTER_SIZE_INT)targetAddr; + } else if ( 0xE8 == (opcode&0xF8) ) { // CALL opcode (&0xF8 - to skip rd bits) + // value is an offset from the call instruction + valueForPatching = targetAddr - addrForPatching-5; + } else { // must not get here + assert(0); + valueForPatching = targetAddr - addrForPatching-5; + } + //FIXME //if (Log::cat_rt()->isDebugEnabled()) { - // Log::cat_rt()->out() << "patching call to "<getName()<<" at "<<(void*)callAddr<<"; new target address is "<<(void*)targetAddr<< ::std::endl; + // Log::cat_rt()->out() << "patching call to "<getName()<<" at "<<(void*)addrforPatching<<"; new target address is "<<(void*)targetAddr<< ::std::endl; //} - *(uint32*)(callAddr+1)=offset; + *(POINTER_SIZE_INT*)(addrForPatching) = valueForPatching; return true; }