Author: varlax
Date: Wed Nov 22 06:53:25 2006
New Revision: 478177
URL: http://svn.apache.org/viewvc?view=rev&rev=478177
Log:
Applied HARMONY-2247 [drlvm][jit][performance] System::arraycopy by 'rep move' instruction.
Tested on SUSE9, observed ~20% gain in default mode (no -Djit options).
Modified:
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeGenerator.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.h
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h Wed Nov 22 06:53:25
2006
@@ -156,7 +156,9 @@
class IntrinsicCallOp {
public:
enum Id {
- CharArrayCopy
+ CharArrayCopy,
+ ArrayCopyDirect,
+ ArrayCopyReverse
};
};
@@ -267,6 +269,8 @@
NamedType* vtableType) = 0;
virtual CG_OpndHandle* call(uint32 numArgs, CG_OpndHandle** args, Type* retType,
MethodDesc *desc, InlineInfo* ii = NULL) = 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,
@@ -345,6 +349,7 @@
virtual CG_OpndHandle* ldStaticAddr(Type* fieldRefType,FieldDesc *desc) = 0;
virtual CG_OpndHandle* ldElemBaseAddr(CG_OpndHandle* array) = 0;
virtual CG_OpndHandle* addElemIndex(Type*, CG_OpndHandle *elemBase,CG_OpndHandle* index)
= 0;
+ virtual CG_OpndHandle* addElemIndexWithLEA(Type*, CG_OpndHandle *elemBase,CG_OpndHandle*
index) = 0;
virtual CG_OpndHandle* ldElemAddr(CG_OpndHandle* array,CG_OpndHandle* index) = 0;
// COMPRESSED_PTR note:
// if we are using compressed references, and ptr is Ptr<CompressedRef>, then
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Encoder.cpp Wed Nov
22 06:53:25 2006
@@ -276,9 +276,7 @@
break;
}
}
- if (inst->getId() == 12) {
- // raise(SIGTRAP);
- }
+
return (uint8*)EncoderBase::encode((char*)stream, mnemonic, args);
}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp Wed
Nov 22 06:53:25 2006
@@ -439,7 +439,16 @@
int32 offset = MPTR_OFFSET_UNKNOWN;
assert(fromOpnd->getType()->isObject() || fromOpnd->getType()->isManagedPtr());
uint32 useIndex2 = opnds.next(useIndex1);
- if (useIndex2 < opnds.end()) {
+ if (inst->getMnemonic() == Mnemonic_LEA) {
+ assert(fromOpnd->isPlacedIn(OpndKind_Memory));
+ Opnd* scaleOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Scale);
+ if (scaleOpnd == NULL) {
+ Opnd* displOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement);
+ assert(displOpnd!=NULL);
+ offset = (int32)displOpnd->getImmValue();
+ }
+ fromOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
+ } else if (useIndex2 < opnds.end()) {
Opnd* offsetOpnd = inst->getOpnd(useIndex2);
offset = getOffsetFromImmediate(offsetOpnd);
}
@@ -449,7 +458,10 @@
} else { // mode == MODE_2_CALC_OFFSETS - 2 addr form
//we can't rely on base/mptr type info here.
//algorithm:
- if (inst->hasKind(Inst::Kind_ControlTransferInst)) {
+ if (inst->hasKind(Inst::Kind_ControlTransferInst) ||
+ inst->getMnemonic() == Mnemonic_MOVS8 ||
+ inst->getMnemonic() == Mnemonic_MOVS16 ||
+ inst->getMnemonic() == Mnemonic_MOVS32 ) {
//Do nothing, calls return only bases
} else {
Opnd* fromOpnd = NULL;
@@ -491,6 +503,7 @@
} else {
offset = MPTR_OFFSET_UNKNOWN;
}
+ fromOpnd = fromOpnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
}
break;
default: assert(0);
@@ -501,7 +514,7 @@
if (fromPair != NULL || offset!=0) {//opnd is mptr -> update pairs
updateMptrInfoInPairs(res, opnd, fromOpnd, offset, fromPair == NULL);
} else {
- //new def of base -> we must to remove all pairs where opnd acts as base
or mptr
+ //new def of base -> we must remove all pairs where opnd acts as base
or mptr
//the problem is that in MODE2 we do not save info about bases (no ambiguity
resolution is done)
//so we can't match pairs where opnd is a base.
//Solution: let pairs derived from this base to live, due to the fact that
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp Wed Nov
22 06:53:25 2006
@@ -1750,6 +1750,10 @@
stackDepth+=getByteSize(inst->getOpnd(it)->getSize());
} else if (inst->getMnemonic() == Mnemonic_POP) {
stackDepth-=getByteSize(inst->getOpnd(it)->getSize());
+ } else if (inst->getMnemonic() == Mnemonic_PUSHFD) {
+ stackDepth+=4;
+ } else if (inst->getMnemonic() == Mnemonic_POPFD) {
+ stackDepth-=4;
} else if (inst->getMnemonic() == Mnemonic_CALL && ((CallInst
*)inst)->getCallingConventionClient().getCallingConvention()->calleeRestoresStack())
{
stackDepth -= ((CallInst *)inst)->getArgStackDepth();
}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h Wed Nov 22 06:53:25
2006
@@ -697,7 +697,22 @@
/** Returns true if the instruction has side effect not described by its operands */
virtual bool hasSideEffect()const
- { return false; }
+ {
+ Mnemonic m = getMnemonic();
+ if(m==Mnemonic_MOVS8 ||
+ m==Mnemonic_MOVS16 ||
+ m==Mnemonic_MOVS32 ||
+ m==Mnemonic_STD ||
+ m==Mnemonic_CLD ||
+ m==Mnemonic_POPFD ||
+ m==Mnemonic_PUSHFD ||
+ m==Mnemonic_POP ||
+ m==Mnemonic_PUSH )
+ {
+ return true;
+ }
+ return false;
+ }
/* Checks that inst is valid*/
virtual void verify() const { assert(node!=NULL);}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp
(original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp
Wed Nov 22 06:53:25 2006
@@ -1845,6 +1845,43 @@
//_______________________________________________________________________________________________________________
// Compute address of the array element given
// address of the first element and index
+// using 'LEA' instruction
+
+CG_OpndHandle* InstCodeSelector::addElemIndexWithLEA(Type * eType,
+ CG_OpndHandle * array,
+ CG_OpndHandle * index)
+{
+ ArrayType * arrayType=((Opnd*)array)->getType()->asArrayType();
+ Type * elemType=arrayType->getElementType();
+ Type * dstType=irManager.getManagedPtrType(elemType);
+
+ uint32 elemSize = getByteSize(irManager.getTypeSize(elemType));
+
+
+#ifdef _EM64T_
+ Type * indexType = typeManager.getInt64Type();
+ Type * offType = typeManager.getInt64Type();
+#else
+ Type * indexType = typeManager.getInt32Type();
+ Type * offType = typeManager.getInt32Type();
+#endif
+
+ Opnd * indexOpnd = (Opnd *)index;
+ indexOpnd = convert(indexOpnd, indexType);
+
+ Opnd * addr = irManager.newMemOpnd(dstType,(Opnd*)array, (Opnd*)index,
+ irManager.newImmOpnd(indexType, elemSize),
+ irManager.newImmOpnd(offType, arrayType->getArrayElemOffset())
+ );
+ Opnd * dst = irManager.newOpnd(dstType);
+ appendInsts(irManager.newInstEx(Mnemonic_LEA, 1, dst, addr));
+ return dst;
+}
+
+//_______________________________________________________________________________________________________________
+// Compute address of the array element given
+// address of the first element and index
+// using 'ADD' instruction
CG_OpndHandle* InstCodeSelector::addElemIndex(Type * eType,
CG_OpndHandle * elemBase,
@@ -2505,6 +2542,107 @@
InlineInfo* ii)
{
return tau_call(numArgs, args, retType, desc, getTauUnsafe(), getTauUnsafe());
+}
+
+//_______________________________________________________________________________________________________________
+// 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.getInt32Type();
+ 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;
+ switch(tag) {
+ case Type::Int8 :
+ case Type::UInt8 :
+ case Type::Boolean:
+ {
+ mn = Mnemonic_MOVS8; break;
+ }
+ case Type::Char :
+ case Type::Int16 :
+ case Type::UInt16 :
+ {
+ mn = Mnemonic_MOVS16; break;
+ }
+ case Type::IntPtr :
+ case Type::Int32 :
+ case Type::UIntPtr:
+ case Type::UInt32 :
+ case Type::Single :
+ case Type::Float :
+ case Type::Object :
+ case Type::SystemObject :
+ case Type::SystemString :
+ case Type::Array :
+ {
+ mn = Mnemonic_MOVS32; break;
+ }
+ case Type::Int64 :
+ case Type::UInt64 :
+ case Type::Double :
+ {
+ 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;
}
//_______________________________________________________________________________________________________________
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
(original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
Wed Nov 22 06:53:25 2006
@@ -156,6 +156,7 @@
CG_OpndHandle* ldStaticAddr(Type* fieldRefType,FieldDesc *desc);
CG_OpndHandle* ldElemBaseAddr(CG_OpndHandle *array);
CG_OpndHandle* addElemIndex(Type*, CG_OpndHandle *elemBase,CG_OpndHandle* index);
+ CG_OpndHandle* addElemIndexWithLEA(Type*, CG_OpndHandle *elemBase,CG_OpndHandle* index);
CG_OpndHandle* ldElemAddr(CG_OpndHandle* array,CG_OpndHandle* index) {
return addElemIndex(NULL,ldElemBaseAddr(array),index);
}
@@ -215,6 +216,8 @@
CG_OpndHandle* tauTypesChecked, InlineInfo* ii = NULL);
CG_OpndHandle* call(uint32 numArgs, CG_OpndHandle** args, Type* retType,
MethodDesc *desc, InlineInfo* ii = NULL);
+ 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, InlineInfo* ii = NULL);
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeGenerator.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeGenerator.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeGenerator.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeGenerator.cpp Wed Nov 22 06:53:25
2006
@@ -428,7 +428,9 @@
//
IntrinsicCallOp::Id convertIntrinsicId(IntrinsicCallId callId) {
switch(callId) {
- case CharArrayCopy: return IntrinsicCallOp::CharArrayCopy;
+ case CharArrayCopy: return IntrinsicCallOp::CharArrayCopy;
+ case ArrayCopyDirect: return IntrinsicCallOp::ArrayCopyDirect;
+ case ArrayCopyReverse: return IntrinsicCallOp::ArrayCopyReverse;
}
assert(0);
return IntrinsicCallOp::CharArrayCopy; // to keep compiler quiet
@@ -894,13 +896,29 @@
IntrinsicCallInst * call = (IntrinsicCallInst *)inst;
IntrinsicCallId callId = call->getIntrinsicId();
- cgInst =
- instructionCallback.tau_callintr(inst->getNumSrcOperands()-2, // omit
taus
- genCallArgs(call,2), // omit taus
- inst->getDst()->getType(),
- convertIntrinsicId(callId),
- getCGInst(tauNullChecked),
- getCGInst(tauTypesChecked));
+ 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:
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp Wed Nov 22 06:53:25 2006
@@ -438,6 +438,10 @@
switch(intrinsicId) {
case CharArrayCopy:
os << "charArrayCopy"; break;
+ case ArrayCopyDirect:
+ os << "ArrayCopyDirect"; break;
+ case ArrayCopyReverse:
+ os << "ArrayCopyReverse"; break;
default:
assert(0); break;
}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h Wed Nov 22 06:53:25 2006
@@ -264,7 +264,9 @@
};
enum IntrinsicCallId {
- CharArrayCopy
+ CharArrayCopy,
+ ArrayCopyDirect,
+ ArrayCopyReverse
};
enum JitHelperCallId {
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp Wed Nov 22 06:53:25
2006
@@ -624,6 +624,8 @@
IntrinsicCallId callId = calli->getIntrinsicId();
switch (callId) {
case CharArrayCopy:
+ case ArrayCopyDirect:
+ case ArrayCopyReverse:
{
assert(calli->getNumSrcOperands() == 7);
#ifndef NDEBUG
@@ -638,6 +640,8 @@
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);
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.cpp Wed Nov 22
06:53:25 2006
@@ -87,7 +87,8 @@
" propValues[={ON|off}] - propagate values during translation\n"\
" guardedInlining[={on|OFF}] - do guarded inlining during translation\n"\
" genCharArrayCopy[={on|off}] - generate intrinsic calls to char array copy\n"\
- " genArrayCopy[={ON|off}] - inline java/lang/System::arraycopy call\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"\
@@ -115,7 +116,8 @@
flags.genCharArrayCopy = getBoolArg("genCharArrayCopy", false);
flags.optArrayInit = getBoolArg("optArrayInit", true);
#endif
- flags.genArrayCopy = getBoolArg("genArrayCopy", true);
+ flags.genArrayCopy = getBoolArg("genArrayCopy", false);
+ flags.genArrayCopyRepMove = getBoolArg("genArrayCopyRepMove", true);
flags.onlyBalancedSync = getBoolArg("balancedSync", false);
flags.ignoreSync = getBoolArg("ignoreSync",false);
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/TranslatorIntfc.h Wed Nov 22 06:53:25
2006
@@ -49,18 +49,19 @@
// to select which byte code translator optimizations are done
struct TranslatorFlags {
- bool propValues : 1; // do value propagation
- bool inlineMethods : 1; // do method inlining
- bool guardedInlining : 1; // a step further for inlining
- bool genCharArrayCopy : 1; // generate intrinsic calls to CharArrayCopy
- bool genArrayCopy : 1; // inline java/lang/System::arraycopy call
- 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
- bool newCatchHandling : 1; // use fix for catch handler ordering problem
- bool genMinMaxAbs : 1; // gen min/max/abs opcodes instead of using select
- bool genFMinMaxAbs : 1; // gen min/max/abs opcodes for floats
- bool optArrayInit : 1; // skip array initializers from optimizations
+ bool propValues : 1; // do value propagation
+ bool inlineMethods : 1; // do method inlining
+ bool guardedInlining : 1; // a step further for inlining
+ 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
+ bool newCatchHandling : 1; // use fix for catch handler ordering problem
+ bool genMinMaxAbs : 1; // gen min/max/abs opcodes instead of using select
+ bool genFMinMaxAbs : 1; // gen min/max/abs opcodes for floats
+ bool optArrayInit : 1; // skip array initializers from optimizations
Method_Table* inlineSkipTable; // do not inline these methods
};
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp
(original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp
Wed Nov 22 06:53:25 2006
@@ -2013,10 +2013,13 @@
returnType = typeManager.getNullObjectType();
}
//
- // Try to match to charArrayCopy
+ // Try some optimizations for System::arraycopy(...), Min, Max, Abs...
//
- if (translationFlags.genArrayCopy == true &&
- genArrayCopy(methodDesc,numArgs,srcOpnds,returnType)) {
+ if (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)) {
@@ -2699,18 +2702,16 @@
}
bool
-JavaByteCodeTranslator::genArrayCopy(MethodDesc * methodDesc,
- uint32 numArgs,
- Opnd ** srcOpnds,
- Type * returnType) {
+JavaByteCodeTranslator::methodIsArraycopy(MethodDesc * methodDesc) {
- //
- // 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;
+ 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:
@@ -2725,19 +2726,14 @@
//
assert(numArgs == 5);
Opnd * src = srcOpnds[0];
- Opnd * srcPos = srcOpnds[1];
Type * srcType = src->getType();
- Type * srcPosType = srcPos->getType();
Opnd * dst = srcOpnds[2];
- Opnd * dstPos = srcOpnds[3];
Type * dstType = dst->getType();
- Type * dstPosType = dstPos->getType();
- Opnd * len = srcOpnds[4];
assert(srcType->isObject() &&
- srcPosType->isInt4() &&
+ srcOpnds[1]->getType()->isInt4() && // 1 - srcPos
dstType->isObject() &&
- dstPosType->isInt4() &&
- len->getType()->isInt4());
+ srcOpnds[3]->getType()->isInt4() && // 3 - dstPos
+ srcOpnds[4]->getType()->isInt4()); // 4 - length
bool throwsASE = false;
bool srcIsArray = srcType->isArray();
@@ -2762,11 +2758,190 @@
throwsASE = ! typeManager.isSubClassOf(srcElemType->getVMTypeHandle(),dstElemType->getVMTypeHandle());
}
if ( throwsASE )
- return false; // reject the inlining of System::arraycopy call
+ 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 * voidType = typeManager.getVoidType();
+
+ 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);
+
+ 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,Exit,nothingToCopy,zero);
+
+ newFallthroughBlock();
+
+ Opnd* tauTypesChecked = irBuilder.genTauSafe();
+
+ // Choosing direction
+ Opnd * dstIsGreater = irBuilder.genCmp(intType,Type::Int32,Cmp_GT,diff,zero);
+ Opnd * reverseCopy = irBuilder.genAnd(intType,sameArrays,dstIsGreater);
+ irBuilder.genBranch(Type::Int32,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* minusone = irBuilder.genLdConstant((int32)-1);
+ 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);
+ Opnd * minusOne = irBuilder.genLdConstant((int32)-1);
+ 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
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.h?view=diff&rev=478177&r1=478176&r2=478177
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/translator/java/JavaByteCodeTranslator.h Wed
Nov 22 06:53:25 2006
@@ -317,8 +317,12 @@
void genInvokeStatic(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds,Type
* returnType);
void genMagic(MethodDesc * methodDesc,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 genArrayCopy(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();
|