Index: vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp (revision 589051) +++ vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp (working copy) @@ -484,3 +484,4 @@ } }}; //namespace Ia32 + Index: vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (revision 589051) +++ vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (working copy) @@ -528,9 +528,9 @@ // to regalloc and constraint resolver. // However, this seems does not change anything currently, // so leaving as-is. - //test low, low - //setns hi ; if lo is positive, then load 1 into hi - //sub hi, 1 ; if lo is positive, then hi is now '0'. otherwise, it's -1 + //test low, low + //setns hi ; if lo is positive, then load 1 into hi + //sub hi, 1 ; if lo is positive, then hi is now '0'. otherwise, it's -1 irManager->newInstEx(Mnemonic_CDQ, 1, dst_2, dst_1)->insertBefore(inst); } else { //fill upper word with 0 @@ -1520,4 +1520,3 @@ }} - Index: vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp (revision 589051) +++ vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp (working copy) @@ -52,7 +52,8 @@ class APIMagicHandler { public: - APIMagicHandler(IRManager* _irm, CallInst* _inst, MethodDesc* _md) : irm(_irm), callInst(_inst), md(_md) { + APIMagicHandler(IRManager* _irm, CallInst* _inst, MethodDesc* _md) + : irm(_irm), callInst(_inst), md(_md), typeManager(irm->getTypeManager()) { cfg = irm->getFlowGraph(); } virtual ~APIMagicHandler(){}; @@ -60,13 +61,14 @@ virtual void run()=0; protected: - void convertIntToInt(Opnd* dst, Opnd* src, Node* node); - Opnd* addElemIndexWithLEA(Opnd* array, Opnd* index, Node* node); + void convertIntToInt(Opnd* dst, Opnd* src, Node* node); + Opnd* addElemIndexWithLEA(Opnd* array, Opnd* index, RegName dstRegName, Node* node); IRManager* irm; CallInst* callInst; MethodDesc* md; ControlFlowGraph* cfg; + TypeManager& typeManager; }; #define DECLARE_HELPER_INLINER(name)\ @@ -82,6 +84,9 @@ DECLARE_HELPER_INLINER(Integer_numberOfTrailingZeros_Handler_x_I_x_I); DECLARE_HELPER_INLINER(Long_numberOfLeadingZeros_Handler_x_J_x_I); DECLARE_HELPER_INLINER(Long_numberOfTrailingZeros_Handler_x_J_x_I); +DECLARE_HELPER_INLINER(System_arraycopyDirect_Handler); +DECLARE_HELPER_INLINER(System_arraycopyReverse_Handler); +DECLARE_HELPER_INLINER(System_arraycopyFast_Handler); DECLARE_HELPER_INLINER(String_compareTo_Handler_x_String_x_I); DECLARE_HELPER_INLINER(String_regionMatches_Handler_x_I_x_String_x_I_x_I_x_Z); @@ -129,7 +134,19 @@ } #endif } else if( ri->getKind() == Opnd::RuntimeInfo::Kind_InternalHelperAddress ) { - if( strcmp((char*)ri->getValue(0),"String_compareTo")==0 ) { + if( strcmp((char*)ri->getValue(0),"memory_copy_direct")==0 ) { + if(getBoolArg("System_arraycopy_as_magic", true)) { + handlers.push_back(new (tmpMM) System_arraycopyDirect_Handler(irm, callInst, NULL)); + } else { assert(0); } + } else if( strcmp((char*)ri->getValue(0),"memory_copy_reverse")==0 ) { + if(getBoolArg("System_arraycopy_as_magic", true)) { + handlers.push_back(new (tmpMM) System_arraycopyReverse_Handler(irm, callInst, NULL)); + } else { assert(0); } + } else if( strcmp((char*)ri->getValue(0),"memory_copy_fast")==0 ) { + if(getBoolArg("System_arraycopy_as_magic", true)) { + handlers.push_back(new (tmpMM) System_arraycopyFast_Handler(irm, callInst, NULL)); + } else { assert(0); } + } else if( strcmp((char*)ri->getValue(0),"String_compareTo")==0 ) { if(getBoolArg("String_compareTo_as_magic", true)) handlers.push_back(new (tmpMM) String_compareTo_Handler_x_String_x_I(irm, callInst, NULL)); } else if( strcmp((char*)ri->getValue(0),"String_regionMatches")==0 ) { @@ -314,6 +331,204 @@ #endif } +void System_arraycopyDirect_Handler::run() +{ + Node* currNode = callInst->getNode(); + assert( currNode->getOutEdge(Edge::Kind_Dispatch) == NULL); +#ifdef _EM64T_ + RegName counterRegName = RegName_RCX; + RegName srcAddrRegName = RegName_RSI; + RegName dstAddrRegName = RegName_RDI; +#else + RegName counterRegName = RegName_ECX; + RegName srcAddrRegName = RegName_ESI; + RegName dstAddrRegName = RegName_EDI; +#endif + + Opnd* src = getCallSrc(callInst, 0); + Opnd* srcPos = getCallSrc(callInst, 1); + Opnd* dst = getCallSrc(callInst, 2); + Opnd* dstPos = getCallSrc(callInst, 3); + Opnd* counterVal = getCallSrc(callInst, 4); + + // prepare counter + Opnd* counter = irm->newRegOpnd(typeManager.getIntPtrType(),counterRegName); + convertIntToInt(counter, counterVal, currNode); + + // prepare src/dst positions + Opnd* srcAddr = addElemIndexWithLEA(src,srcPos,srcAddrRegName,currNode); + Opnd* dstAddr = addElemIndexWithLEA(dst,dstPos,dstAddrRegName,currNode); + + Opnd* one = irm->newImmOpnd(typeManager.getInt8Type(), 1); + + Mnemonic mn = Mnemonic_NULL; + Type* elemType = src->getType()->asArrayType()->getElementType(); + OpndSize typeSize = IRManager::getTypeSize(elemType->tag); + switch(typeSize) { + case OpndSize_8: mn = Mnemonic_MOVS8; break; + case OpndSize_16: mn = Mnemonic_MOVS16; break; + case OpndSize_32: mn = Mnemonic_MOVS32; break; + case OpndSize_64: + { + /** + * FIXME + * Currently JIT erroneously supposes that compressed mode is always on. + * So if type is object, it is actually compressed (32-bit sized). + * But IRManager::getTypeSize() "correctly" returns OpndSize_64. + */ + if (!elemType->isObject()) { + currNode->appendInst(irm->newInstEx(Mnemonic_SHL, 1, counter, counter, one)); + } + mn = Mnemonic_MOVS32; + } + break; + default: assert(0); mn = Mnemonic_MOVS32; break; + } + + Inst* copyInst = irm->newInst(mn,dstAddr,srcAddr,counter); + copyInst->setPrefix(InstPrefix_REP); + currNode->appendInst(copyInst); + + callInst->unlink(); +} + +void System_arraycopyReverse_Handler::run() +{ + Node* currNode = callInst->getNode(); + currNode->appendInst(irm->newInst(Mnemonic_PUSHFD)); + currNode->appendInst(irm->newInst(Mnemonic_STD)); + System_arraycopyDirect_Handler directHandler(irm, callInst, NULL); + directHandler.run(); + + currNode->appendInst(irm->newInst(Mnemonic_POPFD)); +} + +void System_arraycopyFast_Handler::run() +{ + Node* currNode = callInst->getNode(); + + Edge* outEdge = currNode->getOutEdge(Edge::Kind_Unconditional); + assert(outEdge!= NULL); + Node* exitNode = outEdge->getTargetNode(); + + Opnd* src = getCallSrc(callInst, 0); + Opnd* srcPos = getCallSrc(callInst, 1); + Opnd* dst = getCallSrc(callInst, 2); + Opnd* dstPos = getCallSrc(callInst, 3); + Opnd* counterVal = getCallSrc(callInst, 4); + + Constraint reg32Constr(OpndKind_GPReg, OpndSize_32); + Constraint reg16Constr(OpndKind_GPReg, OpndSize_16); + Constraint reg8Constr(OpndKind_GPReg, OpndSize_8); + +#ifdef _EM64T_ + RegName srcAddrRegName = RegName_RSI; + RegName dstAddrRegName = RegName_RDI; + Constraint regPtrConstr(OpndKind_GPReg, OpndSize_64); +#else + RegName srcAddrRegName = RegName_ESI; + RegName dstAddrRegName = RegName_EDI; + Constraint regPtrConstr(OpndKind_GPReg, OpndSize_32); +#endif + + Type* intPtrType = typeManager.getIntPtrType(); + Type* int32Type = typeManager.getInt32Type(); + Type* int16Type = typeManager.getInt16Type(); + Type* int8Type = typeManager.getInt8Type(); + + // prepare counter + Opnd* counter = irm->newOpnd(intPtrType, regPtrConstr); + convertIntToInt(counter, counterVal, currNode); + + // prepare src/dst positions + Opnd* srcAddr = addElemIndexWithLEA(src, srcPos, srcAddrRegName, currNode); + Opnd* dstAddr = addElemIndexWithLEA(dst, dstPos, dstAddrRegName, currNode); + + Opnd* one = irm->newImmOpnd(int32Type, 1); + Opnd* two = irm->newImmOpnd(intPtrType, 2); + Opnd* three = irm->newImmOpnd(int32Type, 3); + Opnd* four = irm->newImmOpnd(intPtrType, 4); + + Type* elemType = src->getType()->asArrayType()->getElementType(); + OpndSize typeSize = IRManager::getTypeSize(elemType->tag); + switch(typeSize) { + case OpndSize_8: + break; + case OpndSize_16: + currNode->appendInst(irm->newInstEx(Mnemonic_SHL, 1, counter, counter, one)); // shl ecx, 1 + break; + case OpndSize_32: + currNode->appendInst(irm->newInstEx(Mnemonic_SHL, 1, counter, counter, two)); // shl ecx, 2 + break; + case OpndSize_64: + { + /** + * FIXME + * Currently JIT erroneously supposes that compressed mode is always on. + * So if type is object, it is actually compressed (32-bit sized). + * But IRManager::getTypeSize() "correctly" returns OpndSize_64. + */ + if (!elemType->isObject()) { + currNode->appendInst(irm->newInstEx(Mnemonic_SHL, 1, counter, counter, three)); // shl ecx, 3 + } + else + currNode->appendInst(irm->newInstEx(Mnemonic_SHL, 1, counter, counter, two)); // shl ecx, 2 + } + break; + default: assert(0); + break; + } + Opnd* offset = irm->newOpnd(intPtrType, regPtrConstr); + Opnd* ebx = irm->newOpnd(int32Type, reg32Constr); + Opnd* bx = irm->newOpnd(int16Type, reg16Constr); + Opnd* bl = irm->newOpnd(int8Type, reg8Constr); + + Node* mainLoop = cfg->createBlockNode(); + Node* copy2BytesEndTest = cfg->createBlockNode(); + Node* copy2BytesEnd = cfg->createBlockNode(); + Node* copy1ByteEndTest = cfg->createBlockNode(); + Node* copy1ByteEnd = cfg->createBlockNode(); + + cfg->removeEdge(outEdge); // disconnect curr and exit nodes + cfg->addEdge(currNode, copy2BytesEndTest, 0.4); + cfg->addEdge(currNode, mainLoop, 0.6); + cfg->addEdge(mainLoop, mainLoop, 0.85); + cfg->addEdge(mainLoop, copy2BytesEndTest, 0.15); + cfg->addEdge(copy2BytesEndTest, copy2BytesEnd, 0.6); + cfg->addEdge(copy2BytesEndTest, copy1ByteEndTest, 0.4); + cfg->addEdge(copy2BytesEnd, copy1ByteEndTest); + cfg->addEdge(copy1ByteEndTest, copy1ByteEnd, 0.6); + cfg->addEdge(copy1ByteEndTest, exitNode, 0.4); + cfg->addEdge(copy1ByteEnd, exitNode); + + currNode->appendInst(irm->newInstEx(Mnemonic_MOV, 1, offset, four)); // mov offset, 4 + currNode->appendInst(irm->newInstEx(Mnemonic_SUB, 1, srcAddr, srcAddr, four)); // sub esi, 4 + currNode->appendInst(irm->newInstEx(Mnemonic_SUB, 1, dstAddr, dstAddr, four)); // sub edi, 4 + currNode->appendInst(irm->newInstEx(Mnemonic_CMP, 0, counter, four)); // cmp ecx, 4 + currNode->appendInst(irm->newBranchInst(Mnemonic_JL, copy2BytesEndTest, mainLoop)); // jl copy2BytesEndTest + + mainLoop->appendInst(irm->newInstEx(Mnemonic_MOV, 1, ebx, irm->newMemOpnd(int32Type, srcAddr, offset, 0, 0))); // mov ebx, [esi + offset] + mainLoop->appendInst(irm->newInstEx(Mnemonic_MOV, 1, irm->newMemOpnd(int32Type, dstAddr, offset, 0, 0), ebx)); // mov [edi + offset], ebx + mainLoop->appendInst(irm->newInstEx(Mnemonic_ADD, 1, offset, offset, four)); // add offset, 4 + mainLoop->appendInst(irm->newInstEx(Mnemonic_CMP, 0, offset, counter)); // cmp offset, ecx + mainLoop->appendInst(irm->newBranchInst(Mnemonic_JLE, mainLoop, copy2BytesEndTest)); // jle mainLoop + + copy2BytesEndTest->appendInst(irm->newInstEx(Mnemonic_TEST, 0, counter, two)); // test ecx, 2 + copy2BytesEndTest->appendInst(irm->newBranchInst(Mnemonic_JZ, copy1ByteEndTest, copy2BytesEnd)); // jz copy1ByteEndTest + + copy2BytesEnd->appendInst(irm->newInstEx(Mnemonic_MOV, 1, bx, irm->newMemOpnd(int16Type, srcAddr, offset, 0, 0))); // mov bx, [esi + offset] + copy2BytesEnd->appendInst(irm->newInstEx(Mnemonic_MOV, 1, irm->newMemOpnd(int16Type, dstAddr, offset, 0, 0), bx)); // mov [edi + offset], bx + copy2BytesEnd->appendInst(irm->newInstEx(Mnemonic_ADD, 1, offset, offset, two)); // add offset, 2 + + copy1ByteEndTest->appendInst(irm->newInstEx(Mnemonic_TEST, 0, counter, one)); // test ecx, 1 + copy1ByteEndTest->appendInst(irm->newBranchInst(Mnemonic_JZ, exitNode, copy1ByteEnd)); // jz exitNode + + copy1ByteEnd->appendInst(irm->newInstEx(Mnemonic_MOV, 1, bl, irm->newMemOpnd(int8Type, srcAddr, offset, 0, 0))); // mov bl, [esi + offset] + copy1ByteEnd->appendInst(irm->newInstEx(Mnemonic_MOV, 1, irm->newMemOpnd(int8Type, dstAddr, offset, 0, 0), bl)); // mov [edi + offset], bl + + callInst->unlink(); +} + void String_compareTo_Handler_x_String_x_I::run() { //mov ds:esi, this //mov es:edi, src @@ -344,13 +559,12 @@ RegName counterRegName = RegName_RCX; RegName thisAddrRegName = RegName_RSI; RegName trgtAddrRegName = RegName_RDI; - Type* counterType = irm->getTypeManager().getInt64Type(); #else RegName counterRegName = RegName_ECX; RegName thisAddrRegName = RegName_ESI; RegName trgtAddrRegName = RegName_EDI; - Type* counterType = irm->getTypeManager().getInt32Type(); #endif + Type* counterType = typeManager.getIntPtrType(); Node* counterIsZeroNode = irm->getFlowGraph()->createBlockNode(); // if counter is zero jump to counterIsZeroNode immediately @@ -368,16 +582,10 @@ Opnd* counter = irm->newRegOpnd(counterType,counterRegName); convertIntToInt(counter, valForCounter, node); - // prepare this position - Opnd* thisAddr = addElemIndexWithLEA(thisArr,thisIdx,node); - Opnd* thisAddrReg = irm->newRegOpnd(thisAddr->getType(),thisAddrRegName); - node->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, thisAddrReg, thisAddr)); + // prepare this/trgt positions + Opnd* thisAddrReg = addElemIndexWithLEA(thisArr,thisIdx,thisAddrRegName,node); + Opnd* trgtAddrReg = addElemIndexWithLEA(trgtArr,trgtIdx,trgtAddrRegName,node); - // prepare trgt position - Opnd* trgtAddr = addElemIndexWithLEA(trgtArr,trgtIdx,node); - Opnd* trgtAddrReg = irm->newRegOpnd(trgtAddr->getType(),trgtAddrRegName); - node->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, trgtAddrReg, trgtAddr)); - Inst* compareInst = irm->newInst(Mnemonic_CMPSW,thisAddrReg,trgtAddrReg,counter); compareInst->setPrefix(InstPrefix_REPZ); node->appendInst(compareInst); @@ -400,7 +608,7 @@ Opnd* two = irm->newImmOpnd(counterType,2); differentStringsNode->appendInst(irm->newInstEx(Mnemonic_SUB, 1, thisAddrReg, thisAddrReg, two)); differentStringsNode->appendInst(irm->newInstEx(Mnemonic_SUB, 1, trgtAddrReg, trgtAddrReg, two)); - Type* charType = irm->getTypeManager().getCharType(); + Type* charType = typeManager.getCharType(); Opnd* thisChar = irm->newMemOpnd(charType, thisAddrReg); Opnd* trgtChar = irm->newMemOpnd(charType, trgtAddrReg); Opnd* dst = irm->newOpnd(charType); @@ -444,28 +652,21 @@ RegName counterRegName = RegName_RCX; RegName thisAddrRegName = RegName_RSI; RegName trgtAddrRegName = RegName_RDI; - Type* counterType = irm->getTypeManager().getInt64Type(); #else RegName counterRegName = RegName_ECX; RegName thisAddrRegName = RegName_ESI; RegName trgtAddrRegName = RegName_EDI; - Type* counterType = irm->getTypeManager().getInt32Type(); #endif + Type* counterType = typeManager.getIntPtrType(); // prepare counter Opnd* counter = irm->newRegOpnd(counterType,counterRegName); convertIntToInt(counter, valForCounter, node); - // prepare this position - Opnd* thisAddr = addElemIndexWithLEA(thisArr,thisIdx,node); - Opnd* thisAddrReg = irm->newRegOpnd(thisAddr->getType(),thisAddrRegName); - node->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, thisAddrReg, thisAddr)); + // prepare this/trgt positions + Opnd* thisAddrReg = addElemIndexWithLEA(thisArr,thisIdx,thisAddrRegName,node); + Opnd* trgtAddrReg = addElemIndexWithLEA(trgtArr,trgtIdx,trgtAddrRegName,node); - // prepare trgt position - Opnd* trgtAddr = addElemIndexWithLEA(trgtArr,trgtIdx,node); - Opnd* trgtAddrReg = irm->newRegOpnd(trgtAddr->getType(),trgtAddrRegName); - node->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, trgtAddrReg, trgtAddr)); - Inst* compareInst = irm->newInst(Mnemonic_CMPSW,thisAddrReg,trgtAddrReg,counter); compareInst->setPrefix(InstPrefix_REPZ); node->appendInst(compareInst); @@ -502,14 +703,16 @@ Type* srcType = src->getType(); // this works only for equal types - // or Int32 into Int64 conversion + // or Int32 into IntPtr conversion assert(srcType == dstType || (srcType == irm->getTypeManager().getInt32Type() && - dstType == irm->getTypeManager().getInt64Type())); + dstType == irm->getTypeManager().getIntPtrType())); if(srcType != dstType) { +#ifdef _EM64T_ node->appendInst(irm->newInstEx(Mnemonic_MOVZX, 1, dst, src)); - } else { +#else node->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, dst, src)); +#endif } } @@ -517,20 +720,20 @@ // address of the first element and index // using 'LEA' instruction -Opnd* APIMagicHandler::addElemIndexWithLEA(Opnd* array, Opnd* index, Node* node) +Opnd* APIMagicHandler::addElemIndexWithLEA(Opnd* array, Opnd* index, RegName dstRegName, Node* node) { - ArrayType * arrayType=((Opnd*)array)->getType()->asArrayType(); - Type * elemType=arrayType->getElementType(); - Type * dstType=irm->getManagedPtrType(elemType); + ArrayType * arrayType = array->getType()->asArrayType(); + Type * elemType = arrayType->getElementType(); + Type * dstType = irm->getManagedPtrType(elemType); + Opnd * dst = irm->newRegOpnd(dstType,dstRegName); - TypeManager& typeManager = irm->getTypeManager(); +// TypeManager& typeManager = typeManager; #ifdef _EM64T_ - Type * indexType = typeManager.getInt64Type(); Type * offType = typeManager.getInt64Type(); #else - Type * indexType = typeManager.getInt32Type(); Type * offType = typeManager.getInt32Type(); #endif + Type * indexType = typeManager.getIntPtrType(); uint32 elemSize = 0; if (elemType->isReference() @@ -552,8 +755,8 @@ } Opnd * arrOffset = irm->newImmOpnd(offType, arrayType->getArrayElemOffset()); Opnd * addr = irm->newMemOpnd(dstType,(Opnd*)array, indexOpnd, elemSizeOpnd, arrOffset); - Opnd * dst = irm->newOpnd(dstType); node->appendInst(irm->newInstEx(Mnemonic_LEA, 1, dst, addr)); + return dst; } Index: vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (revision 589051) +++ vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (working copy) @@ -156,6 +156,32 @@ return; } +void __stdcall memory_copy_direct(uint32 op1, uint32 op2, uint32 op3, uint32 op4, uint32 op5) { + + Jitrino::crash("Illegal internal helper was called.\n Please enable FastMemoryCopy optimization in the code generator path"); + assert(0); + + return; +} + +void __stdcall memory_copy_reverse(uint32 op1, uint32 op2, uint32 op3, uint32 op4, uint32 op5) { + + Jitrino::crash("Illegal internal helper was called.\n Please enable FastMemoryCopy optimization in the code generator path"); + assert(0); + + return; +} + +void __stdcall memory_copy_fast(uint32 op1, uint32 op2, uint32 op3, uint32 op4, uint32 op5) { + + Jitrino::crash("Illegal internal helper was called.\n Please enable FastMemoryCopy optimization in the code generator path"); + assert(0); + + return; +} + + + //_______________________________________________________________________________________________________________ uint32 InstCodeSelector::_tauUnsafe; @@ -178,6 +204,9 @@ irManager.registerInternalHelperInfo("add_value_profile_value", IRManager::InternalHelperInfo((void*)&add_value_profile_value,&CallingConvention_STDCALL)); irManager.registerInternalHelperInfo("fill_array_with_const", IRManager::InternalHelperInfo((void*)&fill_array_with_const,&CallingConvention_STDCALL)); + irManager.registerInternalHelperInfo("memory_copy_direct", IRManager::InternalHelperInfo((void*)&memory_copy_direct,&CallingConvention_STDCALL)); + irManager.registerInternalHelperInfo("memory_copy_reverse", IRManager::InternalHelperInfo((void*)&memory_copy_reverse,&CallingConvention_STDCALL)); + irManager.registerInternalHelperInfo("memory_copy_fast", IRManager::InternalHelperInfo((void*)&memory_copy_fast,&CallingConvention_STDCALL)); irManager.registerInternalHelperInfo("String_compareTo", IRManager::InternalHelperInfo(NULL,&CallingConvention_STDCALL)); irManager.registerInternalHelperInfo("String_regionMatches", IRManager::InternalHelperInfo(NULL,&CallingConvention_STDCALL)); } @@ -473,11 +502,11 @@ // Convert to integer CG_OpndHandle* InstCodeSelector::convToInt(ConvertToIntOp::Types opType, - bool isSigned, - bool isZeroExtend, - ConvertToIntOp::OverflowMod ovfMod, - Type* dstType, - CG_OpndHandle* src) + bool isSigned, + bool isZeroExtend, + ConvertToIntOp::OverflowMod ovfMod, + Type* dstType, + CG_OpndHandle* src) { Type * sizeType=NULL; switch (opType){ @@ -488,16 +517,16 @@ sizeType=isSigned?typeManager.getInt16Type():typeManager.getUInt16Type(); break; -#ifdef _IA32_ +#ifdef _IA32_ case ConvertToIntOp::I: -#endif +#endif case ConvertToIntOp::I4: sizeType=isSigned?typeManager.getInt32Type():typeManager.getUInt32Type(); break; #ifdef _EM64T_ case ConvertToIntOp::I: -#endif +#endif case ConvertToIntOp::I8: sizeType=isSigned?typeManager.getInt64Type():typeManager.getUInt64Type(); break; @@ -1800,7 +1829,7 @@ uint32 elemSize = 0; if (elemType->isReference() - && Type::isCompressedReference(elemType->tag, compilationInterface) + && Type::isCompressedReference(elemType->tag, compilationInterface) && !elemType->isCompressedReference()) { elemSize = 4; } else { @@ -2438,90 +2467,6 @@ } //_______________________________________________________________________________________________________________ -// reverse copying with 'rep move' instruction -// start indexes (args[1] and args[3] must be prepared respectively) - -CG_OpndHandle* InstCodeSelector::arraycopyReverse(uint32 numArgs, - CG_OpndHandle** args) -{ - - - appendInsts(irManager.newInst(Mnemonic_PUSHFD)); - appendInsts(irManager.newInst(Mnemonic_STD)); - - arraycopy(numArgs,args); - - appendInsts(irManager.newInst(Mnemonic_POPFD)); - - return NULL; -} - -//_______________________________________________________________________________________________________________ -// Transforming System::arraycopy call into 'rep move' - -CG_OpndHandle* InstCodeSelector::arraycopy(uint32 numArgs, - CG_OpndHandle** args) -{ - assert(numArgs == 5); - -#ifdef _EM64T_ - RegName counterRegName = RegName_RCX; - RegName srcAddrRegName = RegName_RSI; - RegName dstAddrRegName = RegName_RDI; -#else - RegName counterRegName = RegName_ECX; - RegName srcAddrRegName = RegName_ESI; - RegName dstAddrRegName = RegName_EDI; -#endif - - // prepare counter - Type* counterType = typeManager.getIntPtrType(); - Opnd* counter = irManager.newRegOpnd(counterType,counterRegName); - copyOpnd(counter,(Opnd*)args[4]); - - // prepare src position - Opnd* srcAddr = (Opnd*)addElemIndexWithLEA(NULL,args[0],args[1]); - Opnd* srcAddrReg = irManager.newRegOpnd(srcAddr->getType(),srcAddrRegName); - copyOpnd(srcAddrReg,srcAddr); - - // prepare dst position - Opnd* dstAddr = (Opnd*)addElemIndexWithLEA(NULL,args[2],args[3]); - Opnd* dstAddrReg = irManager.newRegOpnd(dstAddr->getType(),dstAddrRegName); - copyOpnd(dstAddrReg,dstAddr); - - // double counter if elem type is 64 bits long - PtrType* srcAddrType = srcAddr->getType()->asPtrType(); - assert(srcAddrType); - Type::Tag tag = srcAddrType->getPointedToType()->tag; - Mnemonic mn = Mnemonic_NULL; - OpndSize typeSize = IRManager::getTypeSize(tag); - switch(typeSize) { - case OpndSize_8: mn = Mnemonic_MOVS8; break; - case OpndSize_16: mn = Mnemonic_MOVS16; break; - case OpndSize_32: mn = Mnemonic_MOVS32; break; - case OpndSize_64: - { - /** - * FIXME - * Currently JIT erroneously supposes that compressed mode is always on. - * So if type is object, it is actually compressed (32-bit sized). - * But IRManager::getTypeSize() "correctly" returns OpndSize_64. - */ - if (!srcAddrType->getPointedToType()->isObject()) { - appendInsts(irManager.newInst(Mnemonic_SHL, counter, irManager.newImmOpnd(counterType, (int32)1))); - } - mn = Mnemonic_MOVS32; - } - break; - default: assert(0); mn = Mnemonic_MOVS32; break; - } - Inst* copyInst = irManager.newInst(mn,dstAddrReg,srcAddrReg,counter); - copyInst->setPrefix(InstPrefix_REP); - appendInsts(copyInst); - return NULL; -} - -//_______________________________________________________________________________________________________________ // Direct call to the method. Depending on the code generator flags we // either expand direct call into loading method address into a register and // indirect call or true direct call that will be patched if method is recompiled. @@ -2572,32 +2517,6 @@ } //_______________________________________________________________________________________________________________ -// Intrinsic call - -CG_OpndHandle* InstCodeSelector::callintr(uint32 numArgs, - CG_OpndHandle** args, - Type* retType, - IntrinsicCallOp::Id callId) -{ - ICS_ASSERT(0); - return 0; -} - -//_______________________________________________________________________________________________________________ -// Intrinsic call - -CG_OpndHandle* InstCodeSelector::tau_callintr(uint32 numArgs, - CG_OpndHandle** args, - Type* retType, - IntrinsicCallOp::Id callId, - CG_OpndHandle* tauNullsChecked, - CG_OpndHandle* tauTypesChecked) -{ - ICS_ASSERT(0); - return 0; -} - -//_______________________________________________________________________________________________________________ // JIT helper call CG_OpndHandle* InstCodeSelector::callhelper(uint32 numArgs, @@ -2686,6 +2605,27 @@ appendInsts(irManager.newInternalRuntimeHelperCallInst("fill_array_with_const", numArgs, newArgs, dstOpnd)); break; } + case ArrayCopyDirect: + { + assert(numArgs == 5); + Opnd * newArgs[5] = {(Opnd *)args[0], (Opnd *)args[1], (Opnd *)args[2], (Opnd *)args[3], (Opnd *)args[4]}; + appendInsts(irManager.newInternalRuntimeHelperCallInst("memory_copy_direct", numArgs, newArgs, dstOpnd)); + break; + } + case ArrayCopyReverse: + { + assert(numArgs == 5); + Opnd * newArgs[5] = {(Opnd *)args[0], (Opnd *)args[1], (Opnd *)args[2], (Opnd *)args[3], (Opnd *)args[4]}; + appendInsts(irManager.newInternalRuntimeHelperCallInst("memory_copy_reverse", numArgs, newArgs, dstOpnd)); + break; + } + case ArrayCopyFast: + { + assert(numArgs == 5); + Opnd * newArgs[5] = {(Opnd *)args[0], (Opnd *)args[1], (Opnd *)args[2], (Opnd *)args[3], (Opnd *)args[4]}; + appendInsts(irManager.newInternalRuntimeHelperCallInst("memory_copy_fast", numArgs, newArgs, dstOpnd)); + break; + } case StringCompareTo: { assert(numArgs == 7); Index: vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (revision 589051) +++ vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (working copy) @@ -211,14 +211,10 @@ CG_OpndHandle* methodPtr, CG_OpndHandle* nonNullFirstArgTau, CG_OpndHandle* tauTypesChecked); CG_OpndHandle* call(uint32 numArgs, CG_OpndHandle** args, Type* retType, MethodDesc *desc); - CG_OpndHandle* arraycopyReverse(uint32 numArgs, CG_OpndHandle** args); - CG_OpndHandle* arraycopy(uint32 numArgs, CG_OpndHandle** args); CG_OpndHandle* tau_call(uint32 numArgs, CG_OpndHandle** args, Type* retType, MethodDesc *desc, CG_OpndHandle *nonNullFirstArgTau, CG_OpndHandle *tauTypesChecked); CG_OpndHandle* tau_callvirt(uint32 numArgs,CG_OpndHandle** args, Type* retType, MethodDesc *desc, CG_OpndHandle* tauNullChecked, CG_OpndHandle* tauTypesChecked); - CG_OpndHandle* callintr(uint32 numArgs, CG_OpndHandle** args, Type* retType,IntrinsicCallOp::Id callId); - CG_OpndHandle* tau_callintr(uint32 numArgs, CG_OpndHandle** args, Type* retType,IntrinsicCallOp::Id callId, CG_OpndHandle *tauNullsChecked, CG_OpndHandle *tauTypesChecked); CG_OpndHandle* callhelper(uint32 numArgs, CG_OpndHandle** args, Type* retType,JitHelperCallOp::Id callId); CG_OpndHandle* callvmhelper(uint32 numArgs, CG_OpndHandle** args, Type* retType, VM_RT_SUPPORT callId); Index: vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h =================================================================== --- vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (revision 589051) +++ vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (working copy) @@ -175,7 +175,6 @@ CG_OpndHandle *call(uint32, CG_OpndHandle**, Type*, MethodDesc*); CG_OpndHandle *tau_call(uint32, CG_OpndHandle**, Type*, MethodDesc*, CG_OpndHandle*, CG_OpndHandle*); CG_OpndHandle *tau_calli(uint32,CG_OpndHandle**, Type*, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*); - CG_OpndHandle *tau_callintr(uint32, CG_OpndHandle**, Type*, IntrinsicCallOp::Id, CG_OpndHandle*, CG_OpndHandle*); void ret(); void ret(CG_OpndHandle*); @@ -307,8 +306,6 @@ CG_OpndHandle* convToUPtr(PtrType*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("convToUPtr") } CG_OpndHandle *tau_ldIntfTableAddr(Type*, CG_OpndHandle*, NamedType*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("tau_ldIntfTableAddr"); } CG_OpndHandle* tau_ldIntfTableAddr(Type*, CG_OpndHandle*, NamedType*); - CG_OpndHandle* arraycopyReverse(unsigned int, CG_OpndHandle**); - CG_OpndHandle* arraycopy(unsigned int, CG_OpndHandle**); CG_OpndHandle* addElemIndexWithLEA(Type*, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("addElemIndexWithLEA") } CG_OpndHandle* ldRef(Type*, MethodDesc*, unsigned int, bool); void pseudoInst() {} Index: vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp =================================================================== --- vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (revision 589051) +++ vm/jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (working copy) @@ -1304,32 +1304,7 @@ } //----------------------------------------------------------------------------// -// Intrinsic call -CG_OpndHandle *IpfInstCodeSelector::tau_callintr(uint32 numArgs, - CG_OpndHandle **args, - Type *retType, - IntrinsicCallOp::Id callId, - CG_OpndHandle *tauNullsChecked, - CG_OpndHandle *tauTypesChecked) { - - IPF_LOG << " tau_callintr" << endl; - - VM_RT_SUPPORT hId = VM_RT_CHAR_ARRAYCOPY_NO_EXC; - uint64 address = (uint64) compilationInterface.getRuntimeHelperAddress(hId); - Opnd *helperAddress = opndManager->newImm(address); - RegOpnd *retOpnd = NULL; - - if(retType != NULL) - retOpnd = opndManager->newRegOpnd(toOpndKind(retType->tag), toDataKind(retType->tag)); - - directCall(numArgs, (Opnd **) args, retOpnd, helperAddress, p0); - - return retOpnd; -} - -//----------------------------------------------------------------------------// - void IpfInstCodeSelector::ret() { IPF_LOG << " ret" << endl; @@ -1820,20 +1795,6 @@ } //----------------------------------------------------------------------------// - -CG_OpndHandle* IpfInstCodeSelector::arraycopy(unsigned int numArgs, - CG_OpndHandle** args) { - NOT_IMPLEMENTED_C("arraycopy") -} - -//----------------------------------------------------------------------------// - -CG_OpndHandle* IpfInstCodeSelector::arraycopyReverse(unsigned int numArgs, - CG_OpndHandle** args) { - NOT_IMPLEMENTED_C("arraycopyReverse") -} - -//----------------------------------------------------------------------------// // Load address of the field at "base + offset" CG_OpndHandle *IpfInstCodeSelector::ldFieldAddr(Type *fieldRefType, Index: vm/jitrino/src/codegenerator/CodeGenIntfc.h =================================================================== --- vm/jitrino/src/codegenerator/CodeGenIntfc.h (revision 589051) +++ vm/jitrino/src/codegenerator/CodeGenIntfc.h (working copy) @@ -152,15 +152,6 @@ }; }; -class IntrinsicCallOp { -public: - enum Id { - CharArrayCopy, - ArrayCopyDirect, - ArrayCopyReverse - }; -}; - class JitHelperCallOp { public: enum Id { @@ -170,6 +161,9 @@ ReadThisState, LockedCompareAndExchange, AddValueProfileValue, + ArrayCopyDirect, + ArrayCopyReverse, + ArrayCopyFast, StringCompareTo, StringRegionMatches }; @@ -260,8 +254,6 @@ NamedType* vtableType) = 0; virtual CG_OpndHandle* call(uint32 numArgs, CG_OpndHandle** args, Type* retType, MethodDesc *desc) = 0; - virtual CG_OpndHandle* arraycopyReverse(uint32 numArgs, CG_OpndHandle** args) = 0; - virtual CG_OpndHandle* arraycopy(uint32 numArgs, CG_OpndHandle** args) = 0; virtual CG_OpndHandle* tau_call(uint32 numArgs, CG_OpndHandle** args, Type* retType, MethodDesc *desc, CG_OpndHandle *tauNullChecked, @@ -274,10 +266,6 @@ CG_OpndHandle* methodPtr, CG_OpndHandle* tauNullChecked, CG_OpndHandle* tauTypesChecked) = 0; - virtual CG_OpndHandle* tau_callintr(uint32 numArgs, CG_OpndHandle** args, Type* retType, - IntrinsicCallOp::Id callId, - CG_OpndHandle* tauNullChecked, - CG_OpndHandle* tauTypesChecked) = 0; virtual CG_OpndHandle* callhelper(uint32 numArgs, CG_OpndHandle** args, Type* retType, JitHelperCallOp::Id callId) = 0; virtual CG_OpndHandle* callvmhelper(uint32 numArgs, CG_OpndHandle** args, Type* retType, Index: vm/jitrino/src/optimizer/HLOAPIMagics.cpp =================================================================== --- vm/jitrino/src/optimizer/HLOAPIMagics.cpp (revision 589051) +++ vm/jitrino/src/optimizer/HLOAPIMagics.cpp (working copy) @@ -25,7 +25,255 @@ namespace Jitrino { +bool arraycopyOptimizable(Inst* arraycopyCall) { + + assert(arraycopyCall->getNumSrcOperands()==7); // first two are taus + + // + // an ArrayStoreException is thrown and the destination is not modified: + // + // - The src argument refers to an object that is not an array. + // - The dest argument refers to an object that is not an array. + // - The src argument and dest argument refer to arrays whose component types are different primitive types. + // - The src argument refers to an array with a primitive component type and the dest argument + // refers to an array with a reference component type. + // - The src argument refers to an array with a reference component type and the dest argument + // refers to an array with a primitive component type. + // + Opnd * src = arraycopyCall->getSrc(2); + Type * srcType = src->getType(); + Opnd * dst = arraycopyCall->getSrc(4); + Type * dstType = dst->getType(); + assert(srcType->isObject() && + arraycopyCall->getSrc(3)->getType()->isInt4() && // 1 - srcPos + dstType->isObject() && + arraycopyCall->getSrc(5)->getType()->isInt4() && // 3 - dstPos + arraycopyCall->getSrc(6)->getType()->isInt4()); // 4 - length + + bool throwsASE = false; + bool srcIsArray = srcType->isArray() && !srcType->isUnresolvedType(); + bool dstIsArray = dstType->isArray() && !dstType->isUnresolvedType(); + ArrayType* srcAsArrayType = srcType->asArrayType(); + ArrayType* dstAsArrayType = dstType->asArrayType(); + bool srcIsArrOfPrimitive = srcIsArray && VMInterface::isArrayOfPrimitiveElements(srcAsArrayType->getVMTypeHandle()); + bool dstIsArrOfPrimitive = dstIsArray && VMInterface::isArrayOfPrimitiveElements(dstAsArrayType->getVMTypeHandle()); + if ( !(srcIsArray && dstIsArray) ) { + throwsASE = true; + } else if ( srcIsArrOfPrimitive ) { + if( !dstIsArrOfPrimitive || srcType != dstType ) + throwsASE = true; + } else if( dstIsArrOfPrimitive ) { + throwsASE = true; + } else { // the both are of objects + // Here is some inaccuracy. If src is a subclass of dst there is no ASE for sure. + // If it is not, we should check the assignability of each element being copied. + // To avoid this we just reject the inlining of System::arraycopy call in this case. + NamedType* srcElemType = srcAsArrayType->getElementType(); + NamedType* dstElemType = dstAsArrayType->getElementType(); + throwsASE = srcElemType->getVMTypeHandle() != dstElemType->getVMTypeHandle(); + } + if ( throwsASE ) + return false; + else + return true; +} + void +System_arraycopy_HLO_Handler::run() +{ + InstFactory& instFactory = builder->getInstFactory(); + ControlFlowGraph& cfg = builder->getControlFlowGraph(); + + Node* firstNode = callInst->getNode(); + Edge* outEdge = firstNode->getOutEdge(Edge::Kind_Unconditional); + Node* exitNode = outEdge->getTargetNode(); + Node* dispatch = firstNode->getExceptionEdgeTarget(); + assert(dispatch); + callInst->unlink(); + cfg.removeEdge(outEdge); + + builder->setCurrentBCOffset(callInst->getBCOffset()); + builder->setCurrentNode(firstNode); + + // the fist two are tau operands + Opnd * src = callInst->getSrc(2); + Opnd * srcPos = callInst->getSrc(3); + Type * srcPosType = srcPos->getType(); + Opnd * dst = callInst->getSrc(4); + Opnd * dstPos = callInst->getSrc(5); + Type * dstPosType = dstPos->getType(); + Opnd * len = callInst->getSrc(6); + + // + // Generate exception condition checks: + // chknull src + // chknull dst + // cmpbr srcPos < 0, boundsException + // cmpbr dstPos < 0, boundsException + // cmpbr len < 0, boundsException + // srcEnd = add srcPos, len + // srcLen = src.length + // cmpbr srcEnd > srcLen, boundsException + // dstEnd = add dstPos, len + // dstLen = dst.length + // cmpbr dstEnd > dstLen, boundsException + // Skip trivial: + // cmpbr (src == dst) && (dstPos == srcPos), Exit + // + // Choose method: + // cmpbr (src != dst), Fast + // Choose a direction: + // cmpbr (dstPos > srcPos), Reverse + // + // Direct: + // JitHelperCall id=ArrayCopyDirect + // goto Exit + // Reverse: + // srcPos = srcPos + len - 1 + // dstPos = dstPos + len - 1 + // JitHelperCall id=ArrayCopyReverse + // goto Exit + // + // Fast: + // JitHelperCall id=ArrayCopyFast + // goto Exit + // boundsException: + // chkbounds -1, src + // Exit: + // + + // Referenced nodes creation + LabelInst * reverseCopying = (LabelInst*)instFactory.makeLabel(); + LabelInst * fastCopying = (LabelInst*)instFactory.makeLabel(); + LabelInst * boundsException = (LabelInst*)instFactory.makeLabel(); + LabelInst * Exit = (LabelInst*)exitNode->getLabelInst(); + + Node* BExcNode = cfg.createBlockNode(boundsException); + Node* RevCopyNode = cfg.createBlockNode(reverseCopying); + Node* FastCopyNode = cfg.createBlockNode(fastCopying); + + //Other nodes creation and filling + Opnd* tauSrcNullChecked = builder->genTauCheckNull(src); + + // node + builder->genFallthroughNode(dispatch); + Opnd* tauDstNullChecked = builder->genTauCheckNull(dst); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(BExcNode, 0); + + Opnd* tauNullCheckedRefArgs = builder->genTauAnd(tauSrcNullChecked, tauDstNullChecked); + + Type * intType = builder->getTypeManager().getInt32Type(); + Type::Tag intTag = intType->tag; + + Opnd * zero = builder->genLdConstant(0); + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,zero,srcPos,boundsException)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(BExcNode, 0); + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,zero,dstPos,boundsException)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(BExcNode, 0); + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,zero,len,boundsException)); + + Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(BExcNode, 0); + + Opnd * srcLen = builder->genArrayLen(intType, intTag, src, tauSrcNullChecked); + Opnd * srcEnd = builder->genAdd(intType,mod,srcPos,len); + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,srcEnd,srcLen,boundsException)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(BExcNode, 0); + + Opnd * dstEnd = builder->genAdd(intType,mod,dstPos,len); + Opnd * dstLen = builder->genArrayLen(intType, intTag, dst, tauDstNullChecked); + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,dstEnd,dstLen,boundsException)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(exitNode, 0); + + // The case of same arrays and same positions + Opnd * diff = builder->genCmp3(intType,intTag,Cmp_GT,dstPos,srcPos); + Opnd * sameArrays = builder->genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst); + Opnd * zeroDiff = builder->genCmp(intType,intTag,Cmp_EQ,diff,zero); + Opnd * nothingToCopy = builder->genAnd(intType,sameArrays,zeroDiff); + builder->appendInst(instFactory.makeBranch(Cmp_NonZero,intTag,nothingToCopy,Exit)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(FastCopyNode); + + Opnd* tauTypesChecked = builder->genTauSafe(); + + // Checking for opportunity to use optimized method + builder->appendInst(instFactory.makeBranch(Cmp_NonZero,Type::Object,sameArrays,fastCopying)); + + // node + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(RevCopyNode,0); + + // Choosing direction + builder->appendInst(instFactory.makeBranch(Cmp_GT,intTag,dstPos,srcPos,reverseCopying)); + + // Direct Copying + builder->genFallthroughNode(); + builder->genEdgeFromCurrent(exitNode,0); + + Opnd* directArgs [5]; + directArgs[0] = src; + directArgs[1] = srcPos; + directArgs[2] = dst; + directArgs[3] = dstPos; + directArgs[4] = len; + builder->appendInst(instFactory.makeJitHelperCall(OpndManager::getNullOpnd(), ArrayCopyDirect, + tauNullCheckedRefArgs, tauTypesChecked, + 5, directArgs)); + + // Reverse Copying + builder->setCurrentNode(RevCopyNode); + builder->genEdgeFromCurrent(exitNode); + + Opnd* one = builder->genLdConstant(1); + Opnd* lastSrcIdx = builder->genSub(srcPosType,mod,srcEnd,one); + Opnd* lastDstIdx = builder->genSub(dstPosType,mod,dstEnd,one); + + Opnd* reverseArgs [5]; + reverseArgs[0] = src; + reverseArgs[1] = lastSrcIdx; // srcPos+len-1 + reverseArgs[2] = dst; + reverseArgs[3] = lastDstIdx; // dstPos+len-1 + reverseArgs[4] = len; + builder->appendInst(instFactory.makeJitHelperCall(OpndManager::getNullOpnd(), ArrayCopyReverse, + tauNullCheckedRefArgs, tauTypesChecked, + 5, reverseArgs)); + + // Fast Copying + builder->setCurrentNode(FastCopyNode); + builder->genEdgeFromCurrent(exitNode); + builder->appendInst(instFactory.makeJitHelperCall(OpndManager::getNullOpnd(), ArrayCopyFast, + tauNullCheckedRefArgs, tauTypesChecked, + 5, directArgs)); + + // Bounds Exception + builder->setCurrentNode(BExcNode); + builder->genEdgeFromCurrent(exitNode); + builder->genEdgeFromCurrent(dispatch, 0); + Opnd* minusone = builder->genLdConstant(-1); + builder->genTauCheckBounds(src,minusone,tauSrcNullChecked); +} + +void String_compareTo_HLO_Handler::run() { IRManager* irm = builder->getIRManager(); @@ -110,7 +358,7 @@ Opnd* opnds[] = {thisValue,thisStart,thisLength,trgtValue,trgtStart,trgtLength,counter}; // This helper call will be processed in Ia32ApiMagics pass - builder->appendInst(instFactory.makeJitHelperCall(dst, StringCompareTo, 7, opnds)); + builder->appendInst(instFactory.makeJitHelperCall(dst, StringCompareTo, NULL, NULL, 7, opnds)); cfg.orderNodes(true); } @@ -214,7 +462,7 @@ VarOpnd* resultVar = builder->createVarOpnd(dst->getType(),false); SsaVarOpnd* resVar = builder->createSsaVarOpnd(resultVar); Opnd* res = builder->createOpnd(dst->getType()); - builder->appendInst(instFactory.makeJitHelperCall(res, StringRegionMatches, 5, opnds)); + builder->appendInst(instFactory.makeJitHelperCall(res, StringRegionMatches, NULL, NULL, 5, opnds)); builder->genStVar(resVar,res); builder->genEdgeFromCurrent(lastNode); @@ -264,6 +512,7 @@ void HLOAPIMagicIRBuilder::appendInst(Inst* inst) { inst->setBCOffset(currentBCOffset); + assert(currentNode); currentNode->appendInst(inst); } @@ -300,8 +549,6 @@ return fieldVal; } - - Opnd* HLOAPIMagicIRBuilder::createOpnd(Type* type) { if (type->tag == Type::Void) @@ -371,7 +618,6 @@ return dst; } - Opnd* HLOAPIMagicIRBuilder::genLdConstant(int32 val) { Opnd* dst = createOpnd(typeManager.getInt32Type()); @@ -430,7 +676,7 @@ Opnd* HLOAPIMagicIRBuilder::genTauCheckBounds(Opnd* array, Opnd* index, Opnd *tauNullChecked) { - Opnd *tauArrayTypeChecked = genTauHasType(array, array->getType()); + Opnd* tauArrayTypeChecked = genTauHasType(array, array->getType()); Opnd* arrayLen = genTauArrayLen(typeManager.getInt32Type(), Type::Int32, array, tauNullChecked, tauArrayTypeChecked); @@ -452,19 +698,4 @@ return dst; } -Opnd* -HLOAPIMagicIRBuilder::genIntrinsicCall(IntrinsicCallId intrinsicId, - Type* returnType, - Opnd* tauNullCheckedRefArgs, - Opnd* tauTypesChecked, - uint32 numArgs, - Opnd* args[]) { - Opnd * dst = createOpnd(returnType); - appendInst(instFactory.makeIntrinsicCall(dst, intrinsicId, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs, args)); - return dst; -} - } //namespace Jitrino Index: vm/jitrino/src/optimizer/CodeSelectors.h =================================================================== --- vm/jitrino/src/optimizer/CodeSelectors.h (revision 589051) +++ vm/jitrino/src/optimizer/CodeSelectors.h (working copy) @@ -104,9 +104,6 @@ // Maps instruction to ConvertToIntOp::OverflowMod ConvertToIntOp::OverflowMod mapToIntConvertOvfMod(Inst *inst); - // Maps intrinsic id - IntrinsicCallOp::Id convertIntrinsicId(IntrinsicCallId callId); - JitHelperCallOp::Id convertJitHelperId(JitHelperCallId callId); CG_OpndHandle ** genCallArgs(Inst * call, uint32 arg0Pos); Index: vm/jitrino/src/optimizer/Opcode.cpp =================================================================== --- vm/jitrino/src/optimizer/Opcode.cpp (revision 589051) +++ vm/jitrino/src/optimizer/Opcode.cpp (working copy) @@ -106,7 +106,6 @@ { Op_TauVirtualCall, true, MB::Call, MK::Exception, "callvirt", "callvrt [%2.%d](%a) ((%0,%1)) -) %l %b", }, { Op_IndirectCall, true, MB::Call, MK::Exception, "calli", "calli [%0](%a) ((%1,%2)) -) %l", }, { Op_IndirectMemoryCall, true, MB::Call, MK::Exception, "callimem", "callimem [%0](%a) ((%1,%2)) -) %l", }, - { Op_IntrinsicCall, true, MB::Call, MK::Exception, "callintr", "callintr %d(%p) ((%0,%1)) -) %l", }, { Op_JitHelperCall, true, MB::Call, MK::Exception, "callhelper", "callhelper %d(%s) -) %l", }, { Op_VMHelperCall, true, MB::Call, MK::Exception, "callvmhelper", "callvmhelper %d(%s) -) %l %b", }, { Op_Return, true, MB::ControlFlow, MK::None, "return", "return %s", }, Index: vm/jitrino/src/optimizer/codelowerer.h =================================================================== --- vm/jitrino/src/optimizer/codelowerer.h (revision 589051) +++ vm/jitrino/src/optimizer/codelowerer.h (working copy) @@ -136,8 +136,6 @@ Inst* caseIndirectMemoryCall(CallInst* inst) {return caseDefault(inst);} - Inst* caseIntrinsicCall(IntrinsicCallInst* inst) {return caseDefault(inst);} - Inst* caseJitHelperCall(JitHelperCallInst* inst) {return caseDefault(inst);} Inst* caseVMHelperCall(VMHelperCallInst* inst) {return caseDefault(inst);} Index: vm/jitrino/src/optimizer/HLOAPIMagics.h =================================================================== --- vm/jitrino/src/optimizer/HLOAPIMagics.h (revision 589051) +++ vm/jitrino/src/optimizer/HLOAPIMagics.h (working copy) @@ -55,7 +55,7 @@ uint16 getCurrentBCOffset() {return currentBCOffset;} void setCurrentBCOffset(uint16 offset) {currentBCOffset = offset;} - void genEdgeFromCurrent(Node* target) {cfg.addEdge(currentNode, target);} + void genEdgeFromCurrent(Node* target, double edgeProb = 1.0) {cfg.addEdge(currentNode, target, edgeProb);} void genEdgeToCurrent(Node* source) {cfg.addEdge(source,currentNode);} Node* genNodeAfter(Node* node, LabelInst* label, Node* dispatch=NULL); @@ -87,8 +87,6 @@ Opnd* genTauCheckBounds(Opnd* array, Opnd* index, Opnd *tauNullChecked); Opnd* genTauCheckBounds(Opnd* ub, Opnd *index); Opnd* genTauHasType(Opnd *src, Type *castType); - Opnd* genIntrinsicCall(IntrinsicCallId intrinsicId, Type* returnType, Opnd* tauNullCheckedRefArgs, - Opnd* tauTypesChecked, uint32 numArgs, Opnd* args[]); private: IRManager* irm; @@ -126,11 +124,14 @@ virtual void run();\ };\ +DECLARE_HLO_MAGIC_INLINER(System_arraycopy_HLO_Handler); DECLARE_HLO_MAGIC_INLINER(String_compareTo_HLO_Handler); DECLARE_HLO_MAGIC_INLINER(String_regionMatches_HLO_Handler); DEFINE_SESSION_ACTION(HLOAPIMagicSession, hlo_api_magic, "APIMagics HLO Pass") +bool arraycopyOptimizable(Inst* arraycopyCall); + void HLOAPIMagicSession::_run(IRManager& irm) { @@ -152,6 +153,12 @@ const char* className = md->getParentType()->getName(); const char* methodName = md->getName(); const char* signature = md->getSignatureString(); + if (!strcmp(className, "java/lang/System")) { + if (!strcmp(methodName, "arraycopy") && !strcmp(signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V")) { + if(getBoolArg("System_arraycopy_as_magic", true) && arraycopyOptimizable(callInst)) + handlers.push_back(new (mm) System_arraycopy_HLO_Handler(callInst)); + } + } if (!strcmp(className, "java/lang/String")) { if (!strcmp(methodName, "compareTo") && !strcmp(signature, "(Ljava/lang/String;)I")) { if(getBoolArg("String_compareTo_as_magic", true)) Index: vm/jitrino/src/optimizer/escanalyzer.cpp =================================================================== --- vm/jitrino/src/optimizer/escanalyzer.cpp (revision 589051) +++ vm/jitrino/src/optimizer/escanalyzer.cpp (working copy) @@ -404,23 +404,6 @@ } } break; - case Op_JitHelperCall: // calljithelper - if (method_ea_level == 0) { - switch(inst->asJitHelperCallInst()->getJitHelperId()) { - case InitializeArray: - case FillArrayWithConst: - case SaveThisState: - case ReadThisState: - case LockedCompareAndExchange: - case AddValueProfileValue: - case StringCompareTo: - case StringRegionMatches: - break; - default: - assert(0); - } - } - break; case Op_TauStInd: // stind { @@ -504,23 +487,26 @@ } break; - case Op_IntrinsicCall: // callintr - if (!inst->getDst()->isNull()) { - assert(0); + case Op_JitHelperCall: // calljithelper + switch(inst->asJitHelperCallInst()->getJitHelperId()) { + case InitializeArray: + case FillArrayWithConst: + case SaveThisState: + case ReadThisState: + case LockedCompareAndExchange: + case AddValueProfileValue: + case ArrayCopyDirect: + case ArrayCopyReverse: + case ArrayCopyFast: + case StringCompareTo: + case StringRegionMatches: + // none of these helpers deals with objects so skip them + break; + default: + // if you added a new helper that is working with an object + // please take care of it + assert(0); } - n=inst->getNumSrcOperands(); - addinst=false; - for (uint32 i = 0; i < n; i++) { - Type* tt = inst->getSrc(i)->getType(); - if (!tt->isReference()) { - continue; - } - addinst=true; - break; - } - if (addinst) { - exam2Insts->push_back(inst); - } break; case Op_Catch: // catch @@ -886,26 +872,6 @@ } break; - case Op_IntrinsicCall: // callintr - n=inst->getNumSrcOperands(); - switch(inst->asIntrinsicCallInst()->getIntrinsicId()) { - case ArrayCopyDirect: - case ArrayCopyReverse: - cgnode = findCnGNode_op(inst->getSrc(4)->getId()); - assert(cgnode!=NULL); - cgn_src = findCnGNode_op(inst->getSrc(2)->getId()); - assert(cgn_src!=NULL); - addEdge(cgnode,cgn_src,ET_DEFER,inst); - if (verboseLog) { - Log::out() << "need to add edge from "<< cgnode->cngNodeId << " - " << cgnode->opndId << " to " - << cgn_src->cngNodeId << " - " << cgn_src->opndId << std::endl; - } - break; - default: - assert(0); - } - break; - case Op_StVar: // stvar type = inst->getDst()->getType(); if (type->isObject()) { @@ -1241,19 +1207,6 @@ } return; } - if (inst->getOpcode() == Op_IntrinsicCall) { //callintr - uint32 iid = inst->asIntrinsicCallInst()->getIntrinsicId(); - switch(iid) { - case ArrayCopyDirect: - case ArrayCopyReverse: - if (verboseLog) { - Log::out() << "++++ addEdge: callintr" << std::endl; - } - return; - default: - assert(0); - } - } if (inst->getOpcode() == Op_LdFieldAddr) { FieldDesc* fd=inst->asFieldAccessInst()->getFieldDesc(); if (fd->getParentType()->isSystemString()&&strcmp(fd->getName(),"value")==0) { @@ -2691,8 +2644,6 @@ fd->printFullName(os); os << std::endl; } - if (inst->asIntrinsicCallInst()) - os << " IntrinsicCallInst" << std::endl; if (inst->asMethodCallInst()) os << " MethodCallInst" << std::endl; if (inst->asMultiSrcInst()) @@ -3537,7 +3488,7 @@ Opnd** args = NULL; InstFactory& instfactory = irManager.getInstFactory(); Inst* jhcinst = instfactory.makeJitHelperCall( - stThis, ReadThisState, 0, args); + stThis, ReadThisState, NULL, NULL, 0, args); jhcinst->insertAfter(inst_after); newBlock = fg.splitNodeAtInstruction(jhcinst,true, false,instfactory.makeLabel()); fg.addEdge(oldBlock,fg.getUnwindNode()); @@ -3648,7 +3599,7 @@ Opnd* args[1] = {stVal}; InstFactory& instfactory = irManager.getInstFactory(); Inst* jhcinst = instfactory.makeJitHelperCall( - OpndManager::getNullOpnd(), SaveThisState, 1, args); + OpndManager::getNullOpnd(), SaveThisState, NULL, NULL, 1, args); // insert jit helper if (inst_before->getNode()->getFirstInst() == inst_before) { jhcinst->insertAfter(inst_before); @@ -3744,7 +3695,7 @@ os_sc << " null "; os_sc << std::endl; } else { - printCnGNode(stnode,os_sc); os_sc << std::endl; + printCnGNode(stnode,os_sc); os_sc << std::endl; } } } @@ -3844,7 +3795,7 @@ if ((*it)->nodeType == NT_OBJECT && getOutEscaped(*it) == 0 && !((*it)->nInst->getOpcode()==Op_LdRef)) { if ((*it)->nInst->getNode() == NULL && getEscState(*it)==NO_ESCAPE) { - continue; // already scalarized + continue; // already scalarized } ob_ref_type = (*it)->nodeRefType; // object ref type if (ob_ref_type != NR_REF) { @@ -3880,7 +3831,7 @@ os_sc << " null "; os_sc << std::endl; } else { - printCnGNode(stnode,os_sc); os_sc << std::endl; + printCnGNode(stnode,os_sc); os_sc << std::endl; } } @@ -5536,17 +5487,17 @@ EscAnalyzer::CnGNode* EscAnalyzer::getLObj(CnGNode* vval) { - CnGNode* n = vval; - while (n->nodeType != NT_LDOBJ) { - if (n->nodeType!=NT_VARVAL) - return NULL; - if (n->outEdges == NULL) - return NULL; - if ((n->outEdges)->size()!=1) - return NULL; - n=(n->outEdges)->front()->cngNodeTo; - } - return n; + CnGNode* n = vval; + while (n->nodeType != NT_LDOBJ) { + if (n->nodeType!=NT_VARVAL) + return NULL; + if (n->outEdges == NULL) + return NULL; + if ((n->outEdges)->size()!=1) + return NULL; + n=(n->outEdges)->front()->cngNodeTo; + } + return n; } //getLObj(CnGNode* vval) @@ -5869,5 +5820,5 @@ return callInst->getVMHelperId() == id; } -} //namespace Jitrino +} //namespace Jitrino Index: vm/jitrino/src/optimizer/lazyexceptionopt.cpp =================================================================== --- vm/jitrino/src/optimizer/lazyexceptionopt.cpp (revision 589051) +++ vm/jitrino/src/optimizer/lazyexceptionopt.cpp (working copy) @@ -892,7 +892,6 @@ } #endif return methodCallHasSideEffect(inst); - case Op_IntrinsicCall: case Op_JitHelperCall: case Op_VMHelperCall: return true; @@ -1103,6 +1102,5 @@ } } -} //namespace Jitrino +} //namespace Jitrino - Index: vm/jitrino/src/optimizer/Inst.h =================================================================== --- vm/jitrino/src/optimizer/Inst.h (revision 589051) +++ vm/jitrino/src/optimizer/Inst.h (working copy) @@ -69,7 +69,6 @@ class TokenInst; class LinkingExcInst; class CallInst; -class IntrinsicCallInst; class JitHelperCallInst; class VMHelperCallInst; class PhiInst; @@ -89,7 +88,6 @@ virtual void accept(CatchLabelInst*) = 0; virtual void accept(ConstInst*) = 0; virtual void accept(DispatchLabelInst*) = 0; - virtual void accept(IntrinsicCallInst*) = 0; virtual void accept(JitHelperCallInst*) = 0; virtual void accept(VMHelperCallInst*) = 0; virtual void accept(FieldAccessInst*) = 0; @@ -199,9 +197,6 @@ FieldAccessInst* asFieldAccessInst() const { if (isFieldAccess()) return (FieldAccessInst*)this; else return NULL; } - IntrinsicCallInst* asIntrinsicCallInst() const { - if (isIntrinsicCallInst()) return (IntrinsicCallInst*) this; else return NULL; - } JitHelperCallInst* asJitHelperCallInst() const { if (isJitHelperCallInst()) return (JitHelperCallInst*) this; else return NULL; } @@ -256,7 +251,6 @@ virtual bool isConst() const { return false; }; virtual bool isDispatchLabel() const { return false; }; virtual bool isFieldAccess() const { return false; }; - virtual bool isIntrinsicCallInst() const { return false; }; virtual bool isJitHelperCallInst() const { return false; }; virtual bool isVMHelperCallInst() const { return false; }; virtual bool isMethodCall() const { return false; }; @@ -939,40 +933,6 @@ Opnd** args; }; -// intrinsic calls -class IntrinsicCallInst : public Inst { -public: - void visit(InstFormatVisitor& visitor) {visitor.accept(this);} - bool isIntrinsicCallInst() const { return true; } - IntrinsicCallId getIntrinsicId() const {return intrinsicId;} -private: - virtual void handlePrintEscape(::std::ostream&, char code) const; - friend class InstFactory; - IntrinsicCallInst(Opcode op, Modifier mod, - Type::Tag type, - Opnd* dst, - uint32 nArgs, - Opnd** args_, - IntrinsicCallId intr) : Inst(op, mod, type, dst, nArgs), - intrinsicId(intr) { - args = NULL; - switch (nArgs) { - default: args = args_ + MAX_INST_SRCS; - case 2: srcs[1] = args_[1]; - case 1: srcs[0] = args_[0]; - case 0: break; - } - } - Opnd* getSrcExtended(uint32 srcIndex) const { - return args[srcIndex - MAX_INST_SRCS]; - } - void setSrcExtended(uint32 srcIndex, Opnd* src) { - args[srcIndex - MAX_INST_SRCS] = src; - } - Opnd** args; - IntrinsicCallId intrinsicId; -}; - // JIT helper calls class JitHelperCallInst : public Inst { public: @@ -1133,10 +1093,9 @@ Opnd *tauNullCheckedFirstArg, Opnd *tauTypesChecked, uint32 numArgs, Opnd** args); - Inst* makeIntrinsicCall(Opnd* dst, IntrinsicCallId id, + Inst* makeJitHelperCall(Opnd* dst, JitHelperCallId id, Opnd* tauNullChecked, Opnd* tauTypesChecked, uint32 numArgs, Opnd** args); - Inst* makeJitHelperCall(Opnd* dst, JitHelperCallId id, uint32 numArgs, Opnd** args); Inst* makeVMHelperCall(Opnd* dst, VM_RT_SUPPORT id, uint32 numArgs, Opnd** args); @@ -1347,7 +1306,6 @@ MethodInst* makeClone(MethodInst*, OpndManager&, OpndRenameTable&); MethodCallInst* makeClone(MethodCallInst*, OpndManager&, OpndRenameTable&); CallInst* makeClone(CallInst*, OpndManager&, OpndRenameTable&); - IntrinsicCallInst* makeClone(IntrinsicCallInst*, OpndManager&, OpndRenameTable&); JitHelperCallInst* makeClone(JitHelperCallInst*, OpndManager&, OpndRenameTable&); VMHelperCallInst* makeClone(VMHelperCallInst*, OpndManager&, OpndRenameTable&); PhiInst* makeClone(PhiInst*, OpndManager&, OpndRenameTable&); @@ -1499,13 +1457,6 @@ Opnd* ptr, uint32 nArgs, Opnd** args); - IntrinsicCallInst* makeIntrinsicCallInst(Opcode op, - Modifier mod, - Type::Tag, - Opnd* dst, - uint32 nArgs, - Opnd** args_, - IntrinsicCallId id); JitHelperCallInst* makeJitHelperCallInst(Opcode op, Modifier mod, Type::Tag, @@ -1654,9 +1605,6 @@ caseIndirectMemoryCall(CallInst* inst)=0;//{return caseDefault(inst);} virtual Inst* - caseIntrinsicCall(IntrinsicCallInst* inst)=0;//{return caseDefault(inst);} - - virtual Inst* caseJitHelperCall(JitHelperCallInst* inst)=0;//{return caseDefault(inst);} virtual Inst* Index: vm/jitrino/src/optimizer/IRBuilder.h =================================================================== --- vm/jitrino/src/optimizer/IRBuilder.h (revision 589051) +++ vm/jitrino/src/optimizer/IRBuilder.h (working copy) @@ -156,24 +156,22 @@ uint32 numArgs, Opnd* args[]); - Opnd* genIntrinsicCall( - IntrinsicCallId intrinsicId, //TR - Type* returnType, - Opnd* tauNullCheckedRefArgs, // 0 for unsafe - Opnd* tauTypesChecked, // 0 to let IRBuilder find it - uint32 numArgs, - Opnd* args[]); - Opnd* genJitHelperCall(JitHelperCallId helperId, - Type* returnType, - uint32 numArgs, - Opnd* args[]); - - Opnd* genVMHelperCall(VM_RT_SUPPORT helperId, Type* returnType, uint32 numArgs, Opnd* args[]); + Opnd* genJitHelperCall(JitHelperCallId helperId, + Type* returnType, + Opnd* tauNullCheckedRefArgs, + Opnd* tauTypesChecked, + uint32 numArgs, + Opnd* args[]); + Opnd* genVMHelperCall(VM_RT_SUPPORT helperId, + Type* returnType, + uint32 numArgs, + Opnd* args[]); + void genReturn(Opnd* src, Type* retType);//TR void genReturn();//TR Index: vm/jitrino/src/optimizer/FastArrayFilling.cpp =================================================================== --- vm/jitrino/src/optimizer/FastArrayFilling.cpp (revision 589051) +++ vm/jitrino/src/optimizer/FastArrayFilling.cpp (working copy) @@ -362,7 +362,7 @@ // insert the helper. // this helper should be expanded in the code generator phase Inst* initInst = irManager.getInstFactory().makeJitHelperCall( - OpndManager::getNullOpnd(), FillArrayWithConst, 4, args); + OpndManager::getNullOpnd(), FillArrayWithConst, NULL, NULL, 4, args); prepNode->appendInst(initInst); fg.addEdge(prepNode, outEdge->getTargetNode()); @@ -371,4 +371,3 @@ } } - Index: vm/jitrino/src/optimizer/escapeanalyzer.cpp =================================================================== --- vm/jitrino/src/optimizer/escapeanalyzer.cpp (revision 589051) +++ vm/jitrino/src/optimizer/escapeanalyzer.cpp (working copy) @@ -71,7 +71,6 @@ switch (inst->getOpcode()) { case Op_DirectCall: case Op_TauVirtualCall: case Op_IndirectCall: case Op_IndirectMemoryCall: - case Op_IntrinsicCall: case Op_Return: case Op_Throw: case Op_TauStInd: case Op_TauStRef: case Op_TauStField: case Op_TauStElem: case Op_TauStStatic: @@ -107,7 +106,7 @@ if (srcIndex == 0) return false; break; - case Op_DirectCall: case Op_TauVirtualCall: case Op_IntrinsicCall: + case Op_DirectCall: case Op_TauVirtualCall: break; // // return & throw @@ -182,7 +181,7 @@ // // calls should already be marked as escaping // - case Op_DirectCall: case Op_TauVirtualCall: case Op_IntrinsicCall: + case Op_DirectCall: case Op_TauVirtualCall: case Op_IndirectCall: case Op_IndirectMemoryCall: break; // @@ -339,7 +338,6 @@ break; case Op_DirectCall: case Op_TauVirtualCall: - case Op_IntrinsicCall: { if (isRefOrPtrType(inst->getDst())) { // this instruction creates a free ptr/ref Index: vm/jitrino/src/optimizer/Inst.cpp =================================================================== --- vm/jitrino/src/optimizer/Inst.cpp (revision 589051) +++ vm/jitrino/src/optimizer/Inst.cpp (working copy) @@ -440,26 +440,6 @@ } } -void IntrinsicCallInst::handlePrintEscape(::std::ostream& os, char code) const { - switch(code) { - case 'd': - switch(intrinsicId) { - case CharArrayCopy: - os << "charArrayCopy"; break; - case ArrayCopyDirect: - os << "ArrayCopyDirect"; break; - case ArrayCopyReverse: - os << "ArrayCopyReverse"; break; - default: - assert(0); break; - } - break; - default: - Inst::handlePrintEscape(os, code); - break; - } -} - void JitHelperCallInst::handlePrintEscape(::std::ostream& os, char code) const { switch(code) { case 'd': @@ -476,6 +456,12 @@ os << "AddValueProfileValue"; break; case FillArrayWithConst: os << "FillArrayWithConst"; break; + case ArrayCopyDirect: + os << "ArrayCopyDirect"; break; + case ArrayCopyReverse: + os << "ArrayCopyReverse"; break; + case ArrayCopyFast: + os << "ArrayCopyFast"; break; case StringCompareTo: os << "StringCompareTo"; break; case StringRegionMatches: @@ -622,9 +608,6 @@ void accept(CatchLabelInst* inst) { clone = instFactory.makeClone(inst, opndManager, renameTable); } - void accept(IntrinsicCallInst* inst) { - clone = instFactory.makeClone(inst, opndManager, renameTable); - } void accept(JitHelperCallInst* inst) { clone = instFactory.makeClone(inst, opndManager, renameTable); } @@ -1042,25 +1025,6 @@ return newInst; } -IntrinsicCallInst* -InstFactory::makeClone(IntrinsicCallInst* inst, - OpndManager& opndManager, - OpndRenameTable& table) { - uint32 nsrcs = inst->getNumSrcOperands(); - Opnd** newArgs = new (memManager) Opnd*[nsrcs]; - for (uint32 i=0; igetSrc(i)); - IntrinsicCallInst *newInst = makeIntrinsicCallInst(inst->getOpcode(), - inst->getModifier(), - inst->getType(), - table.duplicate(opndManager, inst->getDst()), - nsrcs, - newArgs, - inst->getIntrinsicId()); - newInst->setPersistentInstructionId(inst->getPersistentInstructionId()); - return newInst; -} - JitHelperCallInst* InstFactory::makeClone(JitHelperCallInst* inst, OpndManager& opndManager, @@ -1576,19 +1540,6 @@ return inst; } -IntrinsicCallInst* -InstFactory::makeIntrinsicCallInst(Opcode op, Modifier mod, - Type::Tag type, - Opnd* dst, - uint32 nArgs, - Opnd** args_, - IntrinsicCallId id) { - IntrinsicCallInst * inst = - new (memManager) IntrinsicCallInst(op, mod, type, dst, nArgs, args_, id); - inst->id = numInsts++; - return inst; -} - JitHelperCallInst* InstFactory::makeJitHelperCallInst(Opcode op, Modifier mod, @@ -2024,24 +1975,18 @@ } Inst* -InstFactory::makeIntrinsicCall(Opnd* dst, - IntrinsicCallId id, - Opnd* tauNullChecked, - Opnd* tauTypesChecked, - uint32 numArgs, - Opnd** args) { - assert(tauNullChecked->getType()->tag == Type::Tau); - assert(tauTypesChecked->getType()->tag == Type::Tau); +InstFactory::makeJitHelperCall(Opnd* dst, JitHelperCallId id, + Opnd* tauNullChecked, Opnd* tauTypesChecked, + uint32 numArgs, Opnd** args) +{ Type::Tag returnType = dst->isNull()? Type::Void : dst->getType()->tag; - args = copyOpnds(tauNullChecked, tauTypesChecked, args, numArgs); - return makeIntrinsicCallInst(Op_IntrinsicCall, Modifier(Exception_Sometimes), - returnType, dst, numArgs+2, args, id); -} - -Inst* -InstFactory::makeJitHelperCall(Opnd* dst, JitHelperCallId id, uint32 numArgs, Opnd** args) { - Type::Tag returnType = dst->isNull()? Type::Void : dst->getType()->tag; - args = copyOpnds(args, numArgs); + if (id == ArrayCopyDirect || id == ArrayCopyReverse || id == ArrayCopyFast) // these three need taus + { + args = copyOpnds(tauNullChecked, tauTypesChecked, args, numArgs); + numArgs = numArgs+2; + } else { + args = copyOpnds(args, numArgs); + } Modifier mod; switch(id) { case StringCompareTo: @@ -2699,7 +2644,6 @@ case Op_TauVirtualCall: return caseTauVirtualCall(inst->asMethodCallInst()); case Op_IndirectCall: return caseIndirectCall(inst->asCallInst()); case Op_IndirectMemoryCall: return caseIndirectMemoryCall(inst->asCallInst()); - case Op_IntrinsicCall: return caseIntrinsicCall(inst->asIntrinsicCallInst()); case Op_JitHelperCall: return caseJitHelperCall(inst->asJitHelperCallInst()); case Op_VMHelperCall: return caseVMHelperCall(inst->asVMHelperCallInst()); case Op_Return: return caseReturn(inst); Index: vm/jitrino/src/optimizer/hashvaluenumberer.cpp =================================================================== --- vm/jitrino/src/optimizer/hashvaluenumberer.cpp (revision 589051) +++ vm/jitrino/src/optimizer/hashvaluenumberer.cpp (working copy) @@ -198,8 +198,6 @@ Inst* caseIndirectMemoryCall(CallInst* inst) { return caseDefault(inst); } - Inst* caseIntrinsicCall(IntrinsicCallInst* inst) { return caseDefault(inst); } - Inst* caseJitHelperCall(JitHelperCallInst* inst) {return caseDefault(inst);} Inst* caseVMHelperCall(VMHelperCallInst* inst) {return caseDefault(inst);} @@ -2312,7 +2310,7 @@ case Op_TauCheckDivOpnds: break; case Op_DirectCall: case Op_TauVirtualCall: case Op_IndirectCall: - case Op_IndirectMemoryCall: case Op_IntrinsicCall: case Op_InitType: + case Op_IndirectMemoryCall: case Op_JitHelperCall: case Op_InitType: break; case Op_TauMonitorExit: break; Index: vm/jitrino/src/optimizer/IRBuilder.cpp =================================================================== --- vm/jitrino/src/optimizer/IRBuilder.cpp (revision 589051) +++ vm/jitrino/src/optimizer/IRBuilder.cpp (working copy) @@ -931,7 +931,7 @@ } if (!dst) { dst = createOpnd(dstType); - Inst* inst = instFactory->makeConv(ovfMod, toType, dst, src); + Inst* inst = instFactory->makeConv(ovfMod, toType, dst, src); appendInst(inst); } insertHash(hashcode, src->getId(), dst->getInst()); @@ -983,7 +983,7 @@ } if (!dst) { dst = createOpnd(dstType); - Inst* inst = instFactory->makeConvZE(ovfMod, toType, dst, src); + Inst* inst = instFactory->makeConvZE(ovfMod, toType, dst, src); appendInst(inst); } insertHash(hashcode, src->getId(), dst->getInst()); @@ -1398,44 +1398,30 @@ } Opnd* -IRBuilder::genIntrinsicCall(IntrinsicCallId intrinsicId, +IRBuilder::genJitHelperCall(JitHelperCallId helperId, Type* returnType, - Opnd* tauNullCheckedRefArgs, - Opnd* tauTypesChecked, uint32 numArgs, Opnd* args[]) { for (uint32 i=0; igetType()); - Opnd *tauTypesCheckedDst = genTauHasType(args[2], args[2]->getType()); - tauTypesChecked = genTauAnd(tauTypesCheckedSrc, - tauTypesCheckedDst); - } else { - tauTypesChecked = propagateCopy(tauTypesChecked); - } - - appendInst(instFactory->makeIntrinsicCall(dst, intrinsicId, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs, args)); + appendInst(instFactory->makeJitHelperCall(dst, helperId, NULL, NULL, numArgs, args)); return dst; } Opnd* IRBuilder::genJitHelperCall(JitHelperCallId helperId, Type* returnType, + Opnd* tauNullCheckedRefArgs, + Opnd* tauTypesChecked, uint32 numArgs, Opnd* args[]) { for (uint32 i=0; imakeJitHelperCall(dst, helperId, numArgs, args)); + appendInst(instFactory->makeJitHelperCall(dst, helperId, tauNullCheckedRefArgs, tauTypesChecked, numArgs, args)); return dst; } Index: vm/jitrino/src/optimizer/CodeSelectors.cpp =================================================================== --- vm/jitrino/src/optimizer/CodeSelectors.cpp (revision 589051) +++ vm/jitrino/src/optimizer/CodeSelectors.cpp (working copy) @@ -388,19 +388,6 @@ return ConvertToIntOp::NoOvf; // to keep the compiler quiet } -// -// Maps intrinsic id -// -IntrinsicCallOp::Id _BlockCodeSelector::convertIntrinsicId(IntrinsicCallId callId) { - switch(callId) { - case CharArrayCopy: return IntrinsicCallOp::CharArrayCopy; - case ArrayCopyDirect: return IntrinsicCallOp::ArrayCopyDirect; - case ArrayCopyReverse: return IntrinsicCallOp::ArrayCopyReverse; - } - assert(0); - return IntrinsicCallOp::CharArrayCopy; // to keep compiler quiet -} - JitHelperCallOp::Id _BlockCodeSelector::convertJitHelperId(JitHelperCallId callId) { switch(callId) { case InitializeArray: return JitHelperCallOp::InitializeArray; @@ -409,6 +396,9 @@ case LockedCompareAndExchange: return JitHelperCallOp::LockedCompareAndExchange; case AddValueProfileValue: return JitHelperCallOp::AddValueProfileValue; case FillArrayWithConst: return JitHelperCallOp::FillArrayWithConst; + case ArrayCopyDirect: return JitHelperCallOp::ArrayCopyDirect; + case ArrayCopyReverse: return JitHelperCallOp::ArrayCopyReverse; + case ArrayCopyFast: return JitHelperCallOp::ArrayCopyFast; case StringCompareTo: return JitHelperCallOp::StringCompareTo; case StringRegionMatches: return JitHelperCallOp::StringRegionMatches; } @@ -717,11 +707,11 @@ (opType==CompareOp::S) || (opType==CompareOp::D)) { switch (cmpOp) { - case CompareOp::Gt: cmpOp2 = CompareOp::Gtu; ifNaNResult = 1; break; - case CompareOp::Gtu: cmpOp2 = CompareOp::Gt; ifNaNResult = -1; break; - case CompareOp::Ge: cmpOp2 = CompareOp::Geu; ifNaNResult = 1; break; - case CompareOp::Geu: cmpOp2 = CompareOp::Ge; ifNaNResult = -1; break; - default: break; + case CompareOp::Gt: cmpOp2 = CompareOp::Gtu; ifNaNResult = 1; break; + case CompareOp::Gtu: cmpOp2 = CompareOp::Gt; ifNaNResult = -1; break; + case CompareOp::Ge: cmpOp2 = CompareOp::Geu; ifNaNResult = 1; break; + case CompareOp::Geu: cmpOp2 = CompareOp::Ge; ifNaNResult = -1; break; + default: break; }; } @@ -792,11 +782,11 @@ uint32 numArgs = inst->getNumSrcOperands()-2; // also omit from count cgInst = instructionCallback.tau_call(numArgs, - args, - inst->getDst()->getType(), - methodDesc, - getCGInst(tauNullChecked), - getCGInst(tauTypesChecked)); + args, + inst->getDst()->getType(), + methodDesc, + getCGInst(tauNullChecked), + getCGInst(tauTypesChecked)); } break; case Op_TauVirtualCall: @@ -811,11 +801,11 @@ MethodDesc * methodDesc = call->getMethodDesc(); cgInst = instructionCallback.tau_callvirt(inst->getNumSrcOperands()-2, // omit taus - genCallArgs(call, 2), // omit taus - inst->getDst()->getType(), - methodDesc, - getCGInst(tauNullChecked), - getCGInst(tauTypesChecked)); + genCallArgs(call, 2), // omit taus + inst->getDst()->getType(), + methodDesc, + getCGInst(tauNullChecked), + getCGInst(tauTypesChecked)); } break; case Op_IndirectCall: @@ -829,11 +819,11 @@ assert(inst->isCall()); cgInst = instructionCallback.tau_calli(inst->getNumSrcOperands() - 3, // omit taus and fnAddr - genCallArgs(inst, 3), // omit taus and fnAddr - inst->getDst()->getType(), - getCGInst(fnAddr), - getCGInst(tauNullChecked), - getCGInst(tauTypesChecked)); + genCallArgs(inst, 3), // omit taus and fnAddr + inst->getDst()->getType(), + getCGInst(fnAddr), + getCGInst(tauNullChecked), + getCGInst(tauTypesChecked)); } break; case Op_IndirectMemoryCall: @@ -847,58 +837,29 @@ assert(inst->isCall()); cgInst = instructionCallback.tau_calli(inst->getNumSrcOperands() - 3, // omit taus andfnAddr - genCallArgs(inst, 3), // omit taus and fnAddr - inst->getDst()->getType(), - getCGInst(fnAddr), - getCGInst(tauNullChecked), - getCGInst(tauTypesChecked)); + genCallArgs(inst, 3), // omit taus and fnAddr + inst->getDst()->getType(), + getCGInst(fnAddr), + getCGInst(tauNullChecked), + getCGInst(tauTypesChecked)); } break; - case Op_IntrinsicCall: - { - assert(inst->getNumSrcOperands() >= 2); - Opnd *tauNullChecked = inst->getSrc(0); - Opnd *tauTypesChecked = inst->getSrc(1); - assert(tauNullChecked->getType()->tag == Type::Tau); - assert(tauTypesChecked->getType()->tag == Type::Tau); - - IntrinsicCallInst * call = (IntrinsicCallInst *)inst; - IntrinsicCallId callId = call->getIntrinsicId(); - - if (callId == ArrayCopyDirect) - { - cgInst = - instructionCallback.arraycopy(inst->getNumSrcOperands()-2, // omit taus - genCallArgs(call,2) // omit taus - ); - } else if (callId == ArrayCopyReverse) - { - cgInst = - instructionCallback.arraycopyReverse(inst->getNumSrcOperands()-2, // omit taus - genCallArgs(call,2) // omit taus - ); - } else { - - cgInst = - instructionCallback.tau_callintr(inst->getNumSrcOperands()-2, // omit taus - genCallArgs(call,2), // omit taus - inst->getDst()->getType(), - convertIntrinsicId(callId), - getCGInst(tauNullChecked), - getCGInst(tauTypesChecked)); - } - - } - break; case Op_JitHelperCall: { JitHelperCallInst* call = inst->asJitHelperCallInst(); JitHelperCallId callId = call->getJitHelperId(); - cgInst = + if (callId == ArrayCopyDirect || callId == ArrayCopyReverse || callId == ArrayCopyFast) + cgInst = + instructionCallback.callhelper(inst->getNumSrcOperands()-2, // omit taus + genCallArgs(call,2), // omit taus + inst->getDst()->getType(), + convertJitHelperId(callId)); + else + cgInst = instructionCallback.callhelper(inst->getNumSrcOperands(), - genCallArgs(call,0), - inst->getDst()->getType(), - convertJitHelperId(callId)); + genCallArgs(call,0), + inst->getDst()->getType(), + convertJitHelperId(callId)); } break; case Op_VMHelperCall: @@ -907,9 +868,9 @@ VM_RT_SUPPORT callId = call->getVMHelperId(); cgInst = instructionCallback.callvmhelper(inst->getNumSrcOperands(), - genCallArgs(call,0), - inst->getDst()->getType(), - callId); + genCallArgs(call,0), + inst->getDst()->getType(), + callId); } break; case Op_Return: Index: vm/jitrino/src/optimizer/inliner.cpp =================================================================== --- vm/jitrino/src/optimizer/inliner.cpp (revision 589051) +++ vm/jitrino/src/optimizer/inliner.cpp (working copy) @@ -136,6 +136,9 @@ _inlineSkipMethodTable->add_method_record("java/lang/Long", "numberOfLeadingZeros", "(J)I", des, false); _inlineSkipMethodTable->add_method_record("java/lang/Long", "numberOfTrailingZeros", "(J)I", des, false); #endif + if(argSource->getBoolArg("System_arraycopy_as_magic",true)) { + _inlineSkipMethodTable->add_method_record("java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", des, false); + } if(argSource->getBoolArg("String_compareTo_as_magic",true)) { _inlineSkipMethodTable->add_method_record("java/lang/String", "compareTo", "(Ljava/lang/String;)I", des, false); } Index: vm/jitrino/src/optimizer/simplifier.h =================================================================== --- vm/jitrino/src/optimizer/simplifier.h (revision 589051) +++ vm/jitrino/src/optimizer/simplifier.h (working copy) @@ -488,8 +488,6 @@ Inst* caseIndirectMemoryCall(CallInst* inst); - Inst* caseIntrinsicCall(IntrinsicCallInst* inst) {return caseDefault(inst);} - Inst* caseJitHelperCall(JitHelperCallInst* inst) {return caseDefault(inst);} Inst* caseVMHelperCall(VMHelperCallInst* inst) {return caseDefault(inst);} @@ -536,9 +534,9 @@ inst->getDst()->getType(), inst->getToken(), inst->getEnclosingMethod()); - if (opnd != NULL) - return opnd->getInst(); - return inst; + if (opnd != NULL) + return opnd->getInst(); + return inst; } Inst* caseLdVar(Inst* inst) {return caseDefault(inst);} Index: vm/jitrino/src/optimizer/Opcode.h =================================================================== --- vm/jitrino/src/optimizer/Opcode.h (revision 589051) +++ vm/jitrino/src/optimizer/Opcode.h (working copy) @@ -263,12 +263,6 @@ NewModifier2_BitsConsumed = 2 }; -enum IntrinsicCallId { - CharArrayCopy, - ArrayCopyDirect, - ArrayCopyReverse -}; - enum JitHelperCallId { InitializeArray, FillArrayWithConst, @@ -276,6 +270,9 @@ ReadThisState, //todo: replace with GetTLS + offset sequence LockedCompareAndExchange, AddValueProfileValue, + ArrayCopyDirect, + ArrayCopyReverse, + ArrayCopyFast, StringCompareTo, StringRegionMatches }; @@ -313,7 +310,6 @@ Op_TauVirtualCall, Op_IndirectCall, Op_IndirectMemoryCall, - Op_IntrinsicCall, Op_JitHelperCall, // call to a jit helper routine Op_VMHelperCall, // call to a vm (runtime) helper routine Op_Return, Index: vm/jitrino/src/optimizer/simplifytaus.cpp =================================================================== --- vm/jitrino/src/optimizer/simplifytaus.cpp (revision 589051) +++ vm/jitrino/src/optimizer/simplifytaus.cpp (working copy) @@ -477,7 +477,6 @@ case Op_TauVirtualCall: case Op_IndirectCall: case Op_IndirectMemoryCall: - case Op_IntrinsicCall: if (handleCalls) { return genTauSafe(); } else { Index: vm/jitrino/src/optimizer/memoryopt.cpp =================================================================== --- vm/jitrino/src/optimizer/memoryopt.cpp (revision 589051) +++ vm/jitrino/src/optimizer/memoryopt.cpp (working copy) @@ -618,42 +618,6 @@ thePass->effectAnyGlobal(n, i); } break; - case Op_IntrinsicCall: - { - IntrinsicCallInst *calli = i->asIntrinsicCallInst(); - IntrinsicCallId callId = calli->getIntrinsicId(); - switch (callId) { - case CharArrayCopy: - case ArrayCopyDirect: - case ArrayCopyReverse: - { - assert(calli->getNumSrcOperands() == 7); -#ifndef NDEBUG - Opnd *tauNullChecked = calli->getSrc(0); - assert(tauNullChecked->getType()->tag == Type::Tau); - Opnd *tauTypesChecked = calli->getSrc(1); - assert(tauTypesChecked->getType()->tag == Type::Tau); -#endif - Opnd *srcarray = calli->getSrc(2); - Opnd *srcoffset = calli->getSrc(3); - Opnd *dstarray = calli->getSrc(4); - Opnd *dstoffset = calli->getSrc(5); - Opnd *length = calli->getSrc(6); - - // effectXXXArrayElements actually does not depends on offset parameter - // so we do not need any special managing for the case of reverse copying - thePass->effectReadArrayLength(n, i, srcarray); - thePass->effectReadArrayElements(n, i, srcarray, srcoffset, length); - thePass->effectReadArrayLength(n, i, dstarray); - thePass->effectWriteArrayElements(n, i, dstarray, dstoffset, length); - } - break; - default: - assert(0); - break; - } - } - break; case Op_VMHelperCall: break; case Op_JitHelperCall: @@ -666,6 +630,9 @@ case ReadThisState: case LockedCompareAndExchange: case AddValueProfileValue: + case ArrayCopyDirect: + case ArrayCopyReverse: + case ArrayCopyFast: case StringCompareTo: case StringRegionMatches: break; Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.h =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.h (revision 589051) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.h (working copy) @@ -273,12 +273,6 @@ bool genVMMagic(const char* mname, uint32 numArgs,Opnd ** srcOpnds,Type * returnType); bool genVMHelper(const char* mname, uint32 numArgs,Opnd ** srcOpnds,Type * returnType); - bool methodIsArraycopy(MethodDesc * methodDesc); - bool arraycopyOptimizable(MethodDesc * methodDesc, uint32 numArgs, Opnd ** srcOpnds); - - bool genCharArrayCopy(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds, Type * returnType); - bool genArrayCopyRepMove(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds); - bool genArrayCopy(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds); bool genMinMax(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds, Type * returnType); void newFallthroughBlock(); Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 589051) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -1642,24 +1642,13 @@ returnType = typeManager.getNullObjectType(); } // - // Try some optimizations for System::arraycopy(...), Min, Max, Abs... + // Try some optimizations for Min, Max, Abs... // - if (!compilationInterface.needWriteBarriers() //genArrayCopyRepMove is not ready to work in WB mode - && translationFlags.genArrayCopyRepMove == true - && genArrayCopyRepMove(methodDesc,numArgs,srcOpnds)) { - return; - } else if (translationFlags.genArrayCopy == true && - genArrayCopy(methodDesc,numArgs,srcOpnds)) { - return; - } else if (translationFlags.genCharArrayCopy == true && - genCharArrayCopy(methodDesc,numArgs,srcOpnds,returnType)) { - return; - } else if (translationFlags.genMinMaxAbs == true && + if (translationFlags.genMinMaxAbs == true && genMinMax(methodDesc,numArgs,srcOpnds,returnType)) { return; - } else { + } else genInvokeStatic(methodDesc,numArgs,srcOpnds,returnType); - } } void @@ -2347,579 +2336,6 @@ } bool -JavaByteCodeTranslator::methodIsArraycopy(MethodDesc * methodDesc) { - - return (strcmp(methodDesc->getName(),"arraycopy") == 0 && - strcmp(methodDesc->getParentType()->getName(),"java/lang/System") ==0); -} - -bool -JavaByteCodeTranslator::arraycopyOptimizable(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - // - // an ArrayStoreException is thrown and the destination is not modified: - // - // - The src argument refers to an object that is not an array. - // - The dest argument refers to an object that is not an array. - // - The src argument and dest argument refer to arrays whose component types are different primitive types. - // - The src argument refers to an array with a primitive component type and the dest argument - // refers to an array with a reference component type. - // - The src argument refers to an array with a reference component type and the dest argument - // refers to an array with a primitive component type. - // - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Type * srcType = src->getType(); - Opnd * dst = srcOpnds[2]; - Type * dstType = dst->getType(); - assert(srcType->isObject() && - srcOpnds[1]->getType()->isInt4() && // 1 - srcPos - dstType->isObject() && - srcOpnds[3]->getType()->isInt4() && // 3 - dstPos - srcOpnds[4]->getType()->isInt4()); // 4 - length - - bool throwsASE = false; - bool srcIsArray = srcType->isArray() && !srcType->isUnresolvedType(); - bool dstIsArray = dstType->isArray() && !dstType->isUnresolvedType(); - ArrayType* srcAsArrayType = srcType->asArrayType(); - ArrayType* dstAsArrayType = dstType->asArrayType(); - bool srcIsArrOfPrimitive = srcIsArray && VMInterface::isArrayOfPrimitiveElements(srcAsArrayType->getVMTypeHandle()); - bool dstIsArrOfPrimitive = dstIsArray && VMInterface::isArrayOfPrimitiveElements(dstAsArrayType->getVMTypeHandle()); - if ( !(srcIsArray && dstIsArray) ) { - throwsASE = true; - } else if ( srcIsArrOfPrimitive ) { - if( !dstIsArrOfPrimitive || srcType != dstType ) - throwsASE = true; - } else if( dstIsArrOfPrimitive ) { - throwsASE = true; - } else { // the both are of objects - // Here is some inaccuracy. If src is a subclass of dst there is no ASE for sure. - // If it is not, we should check the assignability of each element being copied. - // To avoid this we just reject the inlining of System::arraycopy call in this case. - NamedType* srcElemType = srcAsArrayType->getElementType(); - NamedType* dstElemType = dstAsArrayType->getElementType(); - throwsASE = srcElemType->getVMTypeHandle() != dstElemType->getVMTypeHandle(); - } - if ( throwsASE ) - return false; - else - return true; -} - -bool -JavaByteCodeTranslator::genArrayCopyRepMove(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - if( !methodIsArraycopy(methodDesc) || - !arraycopyOptimizable(methodDesc,numArgs,srcOpnds) ) - { - // reject the inlining of System::arraycopy call - return false; - } - - if (Log::isEnabled()) { - Log::out() << "XXX array copy into 'rep move': "; - methodDesc->printFullName(Log::out()); - Log::out() << ::std::endl; - } - - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Opnd * srcPos = srcOpnds[1]; - Type * srcPosType = srcPos->getType(); - Opnd * dst = srcOpnds[2]; - Opnd * dstPos = srcOpnds[3]; - Type * dstPosType = dstPos->getType(); - Opnd * len = srcOpnds[4]; - - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // Skip trivial: - // cmpbr (src == dst) && (dstPos == srcPos), Exit - // Choose a direction: - // cmpbr (dstPos > srcPos) && (src == dst), Reverse - // - // Intrinsic calls will be codeselected into rep move instruction. - // Direct: - // IntrinsicCall id=ArrayCopyDirect - // goto Exit - // Reverse: - // srcPos = srcPos + len - 1 - // dstPos = dstPos + len - 1 - // IntrinsicCall id=ArrayCopyReverse - // goto Exit - // - // boundsException: - // chkbounds -1, src - // Exit: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - Opnd *tauNullCheckedRefArgs = irBuilder.genTauAnd(tauSrcNullChecked,tauDstNullChecked); - - LabelInst * reverseCopying = irBuilder.createLabel(); - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * Exit = irBuilder.createLabel(); - - Type * intType = typeManager.getInt32Type(); - Type::Tag intTag = intType->tag; - Type * voidType = typeManager.getVoidType(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - Opnd * minusone = irBuilder.genLdConstant((int32)-1); - - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,len); - - Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,intTag,src); - Opnd * srcEnd = irBuilder.genAdd(intType,mod,srcPos,len); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,mod,dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,intTag,dst); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - - // The case of same arrays and same positions - Opnd * diff = irBuilder.genCmp3(intType,intTag,Cmp_GT,dstPos,srcPos); - Opnd * sameArrays = irBuilder.genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst); - Opnd * zeroDiff = irBuilder.genCmp(intType,intTag,Cmp_EQ,diff,zero); - Opnd * nothingToCopy = irBuilder.genAnd(intType,sameArrays,zeroDiff); - irBuilder.genBranch(intTag,Cmp_GT,Exit,nothingToCopy,zero); - - newFallthroughBlock(); - - Opnd* tauTypesChecked = irBuilder.genTauSafe(); - - // Choosing direction - Opnd * dstIsGreater = irBuilder.genCmp(intType,intTag,Cmp_GT,diff,zero); - Opnd * reverseCopy = irBuilder.genAnd(intType,sameArrays,dstIsGreater); - irBuilder.genBranch(intTag,Cmp_GT,reverseCopying,reverseCopy,zero); - - newFallthroughBlock(); - - { // Direct Copying - irBuilder.genIntrinsicCall(ArrayCopyDirect,voidType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,srcOpnds); - irBuilder.genJump(Exit); - } // End of Direct Copying - - irBuilder.genLabel(reverseCopying); - cfgBuilder.genBlockAfterCurrent(reverseCopying); - { // Reverse Copying - - Opnd* lastSrcIdx = irBuilder.genAdd(srcPosType,mod,srcEnd,minusone); - Opnd* lastDstIdx = irBuilder.genAdd(dstPosType,mod,dstEnd,minusone); - - Opnd** reverseArgs = new (memManager) Opnd*[numArgs]; - reverseArgs[0] = srcOpnds[0]; // src - reverseArgs[1] = lastSrcIdx; // srcPos+len-1 - reverseArgs[2] = srcOpnds[2]; // dst - reverseArgs[3] = lastDstIdx; // dstPos+len-1 - reverseArgs[4] = srcOpnds[4]; // len - // copy - irBuilder.genIntrinsicCall(ArrayCopyReverse,voidType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,reverseArgs); - irBuilder.genJump(Exit); - } // End of Reverse Copying - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - irBuilder.genTauCheckBounds(src,minusone,tauSrcNullChecked); - - irBuilder.genLabel(Exit); - cfgBuilder.genBlockAfterCurrent(Exit); - - return true; -} - -bool -JavaByteCodeTranslator::genArrayCopy(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - if( !methodIsArraycopy(methodDesc) || - !arraycopyOptimizable(methodDesc,numArgs,srcOpnds) ) - { - // reject the inlining of System::arraycopy call - return false; - } - - if (Log::isEnabled()) { - Log::out() << "XXX array copy: "; methodDesc->printFullName(Log::out()); Log::out() << ::std::endl; - } - - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Type * srcType = src->getType(); - Opnd * srcPos = srcOpnds[1]; - Type * srcPosType = srcPos->getType(); - Opnd * dst = srcOpnds[2]; - Type * dstType = dst->getType(); - Opnd * dstPos = srcOpnds[3]; - Type * dstPosType = dstPos->getType(); - Opnd * len = srcOpnds[4]; - - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // - // diff = Cmp3(dstPos,srcPos) - // // 1 if dstPos > srcPos - // // 0 if dstPos == srcPos - // // -1 if dstPos < srcPos - // if (src == dst && diff == 0) // nothing to do - // goto L1: - // - // if (diff > 0) - // goto reverseCopying: - // - // indexSrc = srcPos - // indexDst = dstPos - // increment = 1 - // copyDirectLoopHeader: - // if (indexSrc == srcEnd) - // goto L1: - // dst[indexDst] = src[indexSrc] - // indexSrc += increment - // indexDst += increment - // goto copyDirectLoopHeader: - // - // reverseCopying: - // indexSrc = srcPos + len - 1 - // indexDst = dstPos + len - 1 - // decrement = 1 - // copyReverseLoopHeader: - // if (indexSrc < srcPos) - // goto L1: - // dst[indexDst] = src[indexSrc] - // indexSrc -= decrement - // indexDst -= decrement - // goto copyReverseLoopHeader: - // - // boundsException: - // chkbounds -1, src - // L1: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - - LabelInst * reverseCopying = irBuilder.createLabel(); - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * L1 = irBuilder.createLabel(); - Type * intType = typeManager.getInt32Type(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - Opnd * one = irBuilder.genLdConstant((int32)1); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,len); - - Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,Type::Int32,src); - Opnd * srcEnd = irBuilder.genAdd(intType,mod,srcPos,len); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,mod,dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,Type::Int32,dst); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - - // The case of same arrays and same positions - Opnd * diff = irBuilder.genCmp3(intType,Type::Int32,Cmp_GT,dstPos,srcPos); - Opnd * sameArrays = irBuilder.genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst); - Opnd * zeroDiff = irBuilder.genCmp(intType,Type::Int32,Cmp_EQ,diff,zero); - Opnd * nothingToCopy = irBuilder.genAnd(intType,sameArrays,zeroDiff); - irBuilder.genBranch(Type::Int32,Cmp_GT,L1,nothingToCopy,zero); - - newFallthroughBlock(); - - // Choosing direction - - irBuilder.genBranch(Type::Int32,Cmp_GT,reverseCopying,diff,zero); - - newFallthroughBlock(); - - { //Direct Copying - - // indexes for using inside the loop - VarOpnd* srcPosVar = irBuilder.genVarDef(srcPosType, false); - VarOpnd* dstPosVar = irBuilder.genVarDef(dstPosType, false); - - irBuilder.genStVar(srcPosVar, srcPos); - irBuilder.genStVar(dstPosVar, dstPos); - - Opnd* srcPosOpnd = NULL; - Opnd* dstPosOpnd = NULL; - - // Loop Header - LabelInst * loopHead = irBuilder.createLabel(); - irBuilder.genLabel(loopHead); - cfgBuilder.genBlockAfterCurrent(loopHead); - - // loop exit condition (srcIndex = srcStartIndex + len) - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - irBuilder.genBranch(Type::Int32,Cmp_EQ,L1,srcPosOpnd,srcEnd); - - newFallthroughBlock(); - // array bounds have been checked directly - // the types have been checked above so tauAddressInRange is tauSafe - Opnd *tauSrcAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstBaseTypeChecked = irBuilder.genTauSafe(); - - // load indexes - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - dstPosOpnd = irBuilder.genLdVar(dstPosType,dstPosVar); - - Type* srcElemType = srcType->asArrayType()->getElementType(); - Type* dstElemType = dstType->asArrayType()->getElementType(); - - // copy element - // (Checks are performed before the loop) - Opnd* elem = irBuilder.genLdElem(srcElemType,src,srcPosOpnd, - tauSrcNullChecked, tauSrcAddressInRange); - irBuilder.genStElem(dstElemType,dst,dstPosOpnd,elem, - tauDstNullChecked, tauDstBaseTypeChecked, tauDstAddressInRange); - - // increment indexes - srcPosOpnd = irBuilder.genAdd(srcPosType,mod,srcPosOpnd,one); - dstPosOpnd = irBuilder.genAdd(dstPosType,mod,dstPosOpnd,one); - - // store indexes - irBuilder.genStVar(srcPosVar, srcPosOpnd); - irBuilder.genStVar(dstPosVar, dstPosOpnd); - - // back edge - irBuilder.genPseudoThrow(); - irBuilder.genJump(loopHead); - - } // End of Direct Copying - - { //Reverse Copying - irBuilder.genLabel(reverseCopying); - cfgBuilder.genBlockAfterCurrent(reverseCopying); - - // indexes for using inside the loop - VarOpnd* srcPosVar = irBuilder.genVarDef(srcPosType, false); - VarOpnd* dstPosVar = irBuilder.genVarDef(dstPosType, false); - - Opnd* lastSrcIdx = irBuilder.genSub(srcPosType,mod,srcEnd,one); - Opnd* lastDstIdx = irBuilder.genSub(dstPosType,mod,dstEnd,one); - - irBuilder.genStVar(srcPosVar, lastSrcIdx); - irBuilder.genStVar(dstPosVar, lastDstIdx); - - Opnd* srcPosOpnd = NULL; - Opnd* dstPosOpnd = NULL; - - // Loop Header - LabelInst * loopHead = irBuilder.createLabel(); - irBuilder.genLabel(loopHead); - cfgBuilder.genBlockAfterCurrent(loopHead); - - // loop exit condition (srcIndex < srcPos) - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - irBuilder.genBranch(Type::Int32,Cmp_GT,L1,srcPos,srcPosOpnd); - - newFallthroughBlock(); - // array bounds have been checked directly - // the types have been checked above so tauAddressInRange is tauSafe - Opnd *tauSrcAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstBaseTypeChecked = irBuilder.genTauSafe(); - - // load indexes - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - dstPosOpnd = irBuilder.genLdVar(dstPosType,dstPosVar); - - Type* srcElemType = srcType->asArrayType()->getElementType(); - Type* dstElemType = dstType->asArrayType()->getElementType(); - - // copy element - // (Checks are performed before the loop) - Opnd* elem = irBuilder.genLdElem(srcElemType,src,srcPosOpnd, - tauSrcNullChecked, tauSrcAddressInRange); - irBuilder.genStElem(dstElemType,dst,dstPosOpnd,elem, - tauDstNullChecked, tauDstBaseTypeChecked, tauDstAddressInRange); - - // decrement indexes - srcPosOpnd = irBuilder.genSub(srcPosType,mod,srcPosOpnd,one); - dstPosOpnd = irBuilder.genSub(dstPosType,mod,dstPosOpnd,one); - - // store indexes - irBuilder.genStVar(srcPosVar, srcPosOpnd); - irBuilder.genStVar(dstPosVar, dstPosOpnd); - - // back edge - irBuilder.genPseudoThrow(); - irBuilder.genJump(loopHead); - - } // End of Reverse Copying - - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - Opnd * minusOne = irBuilder.genLdConstant((int32)-1); - irBuilder.genTauCheckBounds(src,minusOne,tauSrcNullChecked); - - irBuilder.genLabel(L1); - cfgBuilder.genBlockAfterCurrent(L1); - - return true; -} - -bool -JavaByteCodeTranslator::genCharArrayCopy(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds, - Type * returnType) { - // - // Check if method is java/lang/System.arraycopy - // (Object src, int srcPos, Object dst, int dstPos, int len) - // - if (strcmp(methodDesc->getName(),"arraycopy") != 0 || - strcmp(methodDesc->getParentType()->getName(),"java/lang/System") !=0) - return false; - // - // Check if arguments are arrays of characters - // - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Opnd * srcPos = srcOpnds[1]; - Opnd * dst = srcOpnds[2]; - Opnd * dstPos = srcOpnds[3]; - Opnd * len = srcOpnds[4]; - assert(src->getType()->isObject() && - srcPos->getType()->isInt4() && - dst->getType()->isObject() && - dstPos->getType()->isInt4() && - len->getType()->isInt4()); - Type * srcType = src->getType(); - Type * dstType = dst->getType(); - if (!(srcType->isArray() && dstType->isArray() && - ((ArrayType *)srcType)->getElementType()->isChar() && - ((ArrayType *)dstType)->getElementType()->isChar())) - return false; - - if (Log::isEnabled()) { - Log::out() << "XXX char array copy: "; methodDesc->printFullName(Log::out()); Log::out() << ::std::endl; - } - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // callintr charArrayCopy(src,srcPos,dst,dstPos,len) - // goto L1: - // boundsException: - // chkbounds -1, src - // L1: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * L1 = irBuilder.createLabel(); - Type * intType = typeManager.getInt32Type(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,len); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,Type::Int32,src); - Opnd * srcEnd = irBuilder.genAdd(intType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),srcPos,len); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,Type::Int32,dst); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - Opnd *tauNullCheckedRefArgs = - irBuilder.genTauAnd(tauSrcNullChecked, tauDstNullChecked); - Opnd *tauTypesChecked = 0; - irBuilder.genIntrinsicCall(CharArrayCopy,returnType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,srcOpnds); - irBuilder.genJump(L1); - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - Opnd * minusOne = irBuilder.genLdConstant((int32)-1); - irBuilder.genTauCheckBounds(src,minusOne,tauSrcNullChecked); - - irBuilder.genLabel(L1); - cfgBuilder.genBlockAfterCurrent(L1); - return true; -} - -bool JavaByteCodeTranslator::genMinMax(MethodDesc * methodDesc, uint32 numArgs, Opnd ** srcOpnds, @@ -3322,12 +2738,12 @@ if (loadConst) { ConstInst::ConstValue v; #ifdef _EM64T_ - v.i8 = theConst; + v.i8 = theConst; #else - v.i4 = theConst; + v.i4 = theConst; #endif Opnd* res = irBuilder.genLdConstant(typeManager.getUIntPtrType(), v); - + if (resType->isPtr()) { res = irBuilder.genConv(resType, resType->tag, mod, res); } Index: vm/jitrino/src/translator/TranslatorIntfc.h =================================================================== --- vm/jitrino/src/translator/TranslatorIntfc.h (revision 589051) +++ vm/jitrino/src/translator/TranslatorIntfc.h (working copy) @@ -50,9 +50,6 @@ // to select which byte code translator optimizations are done struct TranslatorFlags { bool propValues : 1; // do value propagation - bool genCharArrayCopy : 1; // generate intrinsic calls to CharArrayCopy - bool genArrayCopy : 1; // inline java/lang/System::arraycopy call as a copying loop - bool genArrayCopyRepMove: 1; // inline java/lang/System::arraycopy call as 'rep move' instruction bool onlyBalancedSync : 1; // treat all method synchronization as balanced bool ignoreSync : 1; // do not generate monitor enter/exit instructions bool syncAsEnterFence : 1; // implement monitor enter as enter fence and Index: vm/jitrino/src/translator/TranslatorIntfc.cpp =================================================================== --- vm/jitrino/src/translator/TranslatorIntfc.cpp (revision 589051) +++ vm/jitrino/src/translator/TranslatorIntfc.cpp (working copy) @@ -92,9 +92,6 @@ static const char* help = \ " propValues[={ON|off}] - propagate values during translation\n"\ - " genCharArrayCopy[={on|off}] - generate intrinsic calls to char array copy\n"\ - " genArrayCopy[={ON|off}] - inline java/lang/System::arraycopy call as a copying loop\n"\ - " genArrayCopyRepMove[={ON|off}] - inline java/lang/System::arraycopy call as 'rep move' instruction\n"\ " balancedSync[={on|OFF}] - treat all synchronization as balanced\n"\ " ignoreSync[={on|OFF}] - do not generate synchronization\n"\ " syncAsEnterFence[={on|OFF}] - implement synchronization as monitor enter fence\n"\ @@ -116,14 +113,10 @@ void TranslatorAction::readFlags() { flags.propValues = getBoolArg("propValues", true); #if defined(_IPF_) - flags.genCharArrayCopy = getBoolArg("genCharArrayCopy", true); flags.optArrayInit = getBoolArg("optArrayInit", false); #else - flags.genCharArrayCopy = getBoolArg("genCharArrayCopy", false); flags.optArrayInit = getBoolArg("optArrayInit", true); #endif - flags.genArrayCopy = getBoolArg("genArrayCopy", false); - flags.genArrayCopyRepMove = getBoolArg("genArrayCopyRepMove", true); flags.onlyBalancedSync = getBoolArg("balancedSync", false); flags.ignoreSync = getBoolArg("ignoreSync",false); Index: vm/jitrino/src/dynopt/ValueProfiler.cpp =================================================================== --- vm/jitrino/src/dynopt/ValueProfiler.cpp (revision 589051) +++ vm/jitrino/src/dynopt/ValueProfiler.cpp (working copy) @@ -110,7 +110,7 @@ Opnd* valueOpnd = vtableInst->getDst(); const uint32 numArgs = 2; Opnd* args[numArgs] = {indexOpnd, valueOpnd}; - Inst* addValueInst = instFactory.makeJitHelperCall(opndManager.getNullOpnd(), AddValueProfileValue, numArgs, args); + Inst* addValueInst = instFactory.makeJitHelperCall(opndManager.getNullOpnd(), AddValueProfileValue, NULL, NULL, numArgs, args); addValueInst->setBCOffset(call->getBCOffset()); ((CFGInst *)addValueInst)->insertBefore(call); ((CFGInst *)loadIndexInst)->insertBefore(addValueInst); Index: vm/jitrino/src/dynopt/EdgeProfiler.cpp =================================================================== --- vm/jitrino/src/dynopt/EdgeProfiler.cpp (revision 589051) +++ vm/jitrino/src/dynopt/EdgeProfiler.cpp (working copy) @@ -751,7 +751,7 @@ } Inst* last = (Inst*)node->getLastInst(); // This method is not a leaf method. - if( last->getOpcode() >= Op_DirectCall && last->getOpcode() <= Op_IntrinsicCall ){ + if( last->getOpcode() >= Op_DirectCall && last->getOpcode() <= Op_VMHelperCall ){ return false; } Edges::const_iterator eiter; Index: vm/jitrino/src/dynopt/StaticProfiler.cpp =================================================================== --- vm/jitrino/src/dynopt/StaticProfiler.cpp (revision 589051) +++ vm/jitrino/src/dynopt/StaticProfiler.cpp (working copy) @@ -346,7 +346,7 @@ double dprob = (*fn)(c); assert(dprob>0 && dprob<1); if (dprob!=PROB_HEURISTIC_FAIL) { - double newprob = prob * dprob / (prob*dprob + (1-prob)*(1-dprob)); + double newprob = prob*dprob / (prob*dprob + (1-prob)*(1-dprob)); assert(newprob>0 && newprob<1); prob = newprob; } @@ -415,8 +415,8 @@ static double callHeuristic(const StaticProfilerContext* c) { Node* node1 = c->edge1->getTargetNode(); Node* node2 = c->edge2->getTargetNode(); - bool node1HasCall = findInst(node1, Op_DirectCall, Op_IntrinsicCall)!=NULL; - bool node2HasCall = findInst(node2, Op_DirectCall, Op_IntrinsicCall)!=NULL; + bool node1HasCall = findInst(node1, Op_DirectCall, Op_VMHelperCall)!=NULL; + bool node2HasCall = findInst(node2, Op_DirectCall, Op_VMHelperCall)!=NULL; if (!node1HasCall && !node2HasCall) { return PROB_HEURISTIC_FAIL;