Index: codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- codegenerator/ia32/Ia32InstCodeSelector.cpp (revision 447400) +++ codegenerator/ia32/Ia32InstCodeSelector.cpp (working copy) @@ -293,11 +293,15 @@ OpndSize srcSize=irManager.getTypeSize(srcType); OpndSize dstSize=irManager.getTypeSize(dstType); - if (dstSize==srcSize){ // trivial conversion without changing type - if (dstOpnd==NULL) + if (dstSize==srcSize){ // trivial conversion + if (dstOpnd==NULL && dstType == srcType) { dstOpnd=srcOpnd; - else + } else { + if (dstOpnd == NULL) { + dstOpnd = irManager.newOpnd(dstType); + } copyOpndTrivialOrTruncatingConversion(dstOpnd, srcOpnd); + } }else if (dstSize<=srcSize){ // truncating conversion if (dstOpnd==NULL) dstOpnd=irManager.newOpnd(dstType); @@ -386,6 +390,52 @@ } //_______________________________________________________________________________________________________________ +Opnd * InstCodeSelector::convertToUnmanagedPtr(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd) { + assert(dstType->isUnmanagedPtr()); + Type* srcType = srcOpnd->getType(); + if (dstOpnd == NULL) { + dstOpnd = irManager.newOpnd(dstType); + } + + if (srcType->isObject() || srcType->isInteger()) { + appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dstOpnd, srcOpnd)); + } else { + assert(0); + } + return dstOpnd; +} + + +//_______________________________________________________________________________________________________________ +Opnd * InstCodeSelector::convertUnmanagedPtr(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd) { + Type * srcType=srcOpnd->getType(); + assert(srcType->isUnmanagedPtr()); + + if (dstOpnd == NULL) { + dstOpnd = irManager.newOpnd(dstType); + } + + if (dstType->isObject()) { + appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dstOpnd, srcOpnd)); + } else { + assert(dstType->isInteger()); + OpndSize srcSize=irManager.getTypeSize(srcType); + OpndSize dstSize=irManager.getTypeSize(dstType); + if (dstSize<=srcSize) { + copyOpndTrivialOrTruncatingConversion(dstOpnd, srcOpnd); + } else { + assert(dstSize==OpndSize_64); +#ifdef _EM64T_ + appendInsts(irManager.newInstEx(srcType->isSignedInteger()?Mnemonic_MOVSX:Mnemonic_MOVZX, 1, dstOpnd, srcOpnd)); +#else + appendInsts(irManager.newI8PseudoInst(srcType->isSignedInteger()?Mnemonic_MOVSX:Mnemonic_MOVZX, 1, dstOpnd, srcOpnd)); +#endif + } + } + return dstOpnd; +} + +//_______________________________________________________________________________________________________________ Opnd * InstCodeSelector::convert(CG_OpndHandle * oph, Type * dstType, Opnd * dstOpnd) { if (!oph) @@ -398,10 +448,13 @@ if (isIntegerType(dstType)){ dstOpnd=convertIntToInt(srcOpnd, dstType, dstOpnd); converted=true; - }else if (dstType->isFP()){ + } else if (dstType->isFP()){ dstOpnd=convertIntToFp(srcOpnd, dstType, dstOpnd); converted=true; - } + } else if (dstType->isUnmanagedPtr()) { + dstOpnd = convertToUnmanagedPtr(srcOpnd, dstType, dstOpnd); + converted = true; + } }else if (srcType->isFP()){ if (dstType->isInteger()){ dstOpnd=convertFpToInt(srcOpnd, dstType, dstOpnd); @@ -410,6 +463,9 @@ dstOpnd=convertFpToFp(srcOpnd, dstType, dstOpnd); converted=true; } + } else if (srcType->isUnmanagedPtr() && !dstType->isUnmanagedPtr()) { + dstOpnd = convertUnmanagedPtr(srcOpnd, dstType, dstOpnd); + converted = true; } if (!converted){ @@ -464,7 +520,19 @@ return convert(src, dstType); } +//_______________________________________________________________________________________________________________ +// Convert to objects to unmanaged pointers and via versa +/// convert unmanaged pointer to object. Boxing +CG_OpndHandle* InstCodeSelector::convUPtrToObject(ObjectType * dstType, CG_OpndHandle* val) { + return convert(val, dstType); +} + +/// convert object or integer to unmanaged pointer. +CG_OpndHandle* InstCodeSelector::convToUPtr(PtrType * dstType, CG_OpndHandle* src) { + return convert(src, dstType); +} + //_______________________________________________________________________________________________________________ Opnd * InstCodeSelector::createResultOpnd(Type * dstType) { @@ -1788,7 +1856,7 @@ indexOpnd=convert(indexOpnd, indexType); Opnd * scaledIndexOpnd=NULL; - if (indexOpnd->isPlacedIn(OpndKind_Imm)){ + if (indexOpnd->isPlacedIn(OpndKind_Imm) || elemSize == 1){ scaledIndexOpnd=irManager.newImmOpnd(indexType, indexOpnd->getImmValue()*elemSize); }else{ scaledIndexOpnd=irManager.newOpnd(indexType); Index: codegenerator/ia32/Ia32I8Lowerer.cpp =================================================================== --- codegenerator/ia32/Ia32I8Lowerer.cpp (revision 447400) +++ codegenerator/ia32/Ia32I8Lowerer.cpp (working copy) @@ -214,6 +214,10 @@ if (mn==Mnemonic_MOVSX){ irManager->newInstEx(Mnemonic_CDQ, 1, dst_2, dst_1)->insertBefore(inst); inst->unlink(); + } else { + Opnd* zero = irManager->newImmOpnd(irManager->getTypeManager().getInt32Type(), 0); + irManager->newInstEx(Mnemonic_MOV, 1, dst_2, zero)->insertBefore(inst); + inst->unlink(); } break; case Mnemonic_PUSH : Index: codegenerator/ia32/Ia32InstCodeSelector.h =================================================================== --- codegenerator/ia32/Ia32InstCodeSelector.h (revision 447400) +++ codegenerator/ia32/Ia32InstCodeSelector.h (working copy) @@ -116,6 +116,10 @@ ConvertToIntOp::OverflowMod,Type* dstType, CG_OpndHandle* src); CG_OpndHandle* convToFp(ConvertToFpOp::Types, Type* dstType, CG_OpndHandle* src); + /// convert unmanaged pointer to object. Boxing + CG_OpndHandle* convUPtrToObject(ObjectType * dstType, CG_OpndHandle* val); + /// convert object or integer to unmanaged pointer. + CG_OpndHandle* convToUPtr(PtrType * dstType, CG_OpndHandle* src); CG_OpndHandle* ldc_i4(uint32 val); @@ -309,7 +313,9 @@ Opnd * convertIntToFp(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd=NULL); Opnd * convertFpToInt(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd=NULL); Opnd * convertFpToFp(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd=NULL); - + Opnd* convertUnmanagedPtr(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd=NULL); + Opnd* convertToUnmanagedPtr(Opnd * srcOpnd, Type * dstType, Opnd * dstOpnd=NULL); + bool isIntegerType(Type * type) { return type->isInteger()||type->isBoolean()||type->isChar(); } void copyOpnd(Opnd *dst, Opnd *src); Index: codegenerator/CodeGenIntfc.h =================================================================== --- codegenerator/CodeGenIntfc.h (revision 447400) +++ codegenerator/CodeGenIntfc.h (working copy) @@ -243,6 +243,11 @@ virtual void throwSystemException(CompilationInterface::SystemExceptionId) = 0; virtual void throwLinkingException(Class_Handle encClass, uint32 cp_ndx, uint32 opcode) = 0; + /// convert unmanaged pointer to object. Boxing + virtual CG_OpndHandle* convUPtrToObject(ObjectType * dstType, CG_OpndHandle* val) = 0; + /// convert object or integer to unmanaged pointer. Unboxing + virtual CG_OpndHandle* convToUPtr(PtrType * dstType, CG_OpndHandle* op) = 0; + virtual CG_OpndHandle* convToInt(ConvertToIntOp::Types, bool isSigned, ConvertToIntOp::OverflowMod, Type* dstType, CG_OpndHandle* src) = 0; Index: optimizer/CodeGenerator.cpp =================================================================== --- optimizer/CodeGenerator.cpp (revision 447400) +++ optimizer/CodeGenerator.cpp (working copy) @@ -138,6 +138,7 @@ return ArithmeticOp::I8_Ovf; return ArithmeticOp::U8_Ovf; case Type::IntPtr: + case Type::UIntPtr: if ((modifier == Overflow_None) || (excModifier == Exception_Never)) return ArithmeticOp::I; if (modifier == Overflow_Signed) @@ -295,6 +296,7 @@ case Type::Int64: return IntegerOp::I8; case Type::IntPtr: + case Type::UIntPtr: return IntegerOp::I; default: assert(0); } @@ -312,6 +314,7 @@ case Type::Int64: return CompareOp::I8; case Type::IntPtr: + case Type::UIntPtr: return CompareOp::I; case Type::Float: return CompareOp::F; @@ -645,8 +648,11 @@ cgInst = instructionCallback.convToFp(mapToFpConvertOpType(inst), dstType, getCGInst(inst->getSrc(0))); - } - else { + } else if (dstType->isObject()){ + cgInst = instructionCallback.convUPtrToObject((ObjectType*)dstType, getCGInst(inst->getSrc(0))); + } else if (dstType->isUnmanagedPtr()) { + cgInst = instructionCallback.convToUPtr((PtrType*)dstType, getCGInst(inst->getSrc(0))); + } else { bool isSigned = Type::isSignedInteger(inst->getType()); cgInst = instructionCallback.convToInt(mapToIntConvertOpType(inst), isSigned, @@ -990,6 +996,9 @@ if (!genConsts) break; ConstInst* constInst = (ConstInst*)inst; switch (inst->getType()) { + case Type::UIntPtr://mfursov todo! + case Type::IntPtr://mfursov todo! + case Type::UnmanagedPtr://mfursov todo! case Type::Int32: cgInst = instructionCallback.ldc_i4(constInst->getValue().i4); break; Index: optimizer/Inst.cpp =================================================================== --- optimizer/Inst.cpp (revision 447400) +++ optimizer/Inst.cpp (working copy) @@ -372,6 +372,8 @@ os << (unsigned long)value.i8; break; case Type::IntPtr: + case Type::UIntPtr: + case Type::UnmanagedPtr: os << value.i; break; case Type::Single: Index: optimizer/Opnd.cpp =================================================================== --- optimizer/Opnd.cpp (revision 447400) +++ optimizer/Opnd.cpp (working copy) @@ -139,7 +139,8 @@ return typeManager.getInt32Type(); case Type::IntPtr: case Type::UIntPtr: - return typeManager.getIntPtrType(); + return ldType; + //return typeManager.getIntPtrType(); case Type::Int64: case Type::UInt64: return typeManager.getInt64Type(); @@ -170,7 +171,7 @@ } return ldType; case Type::UnmanagedPtr: - return typeManager.getIntPtrType(); + //return typeManager.getIntPtrType(); case Type::ManagedPtr: // Managed ptr is valid only for ldvar or ldarg case Type::TypedReference: // TypedReference is valid only for ldvar or ldarg return ldType; Index: optimizer/memoryopt.cpp =================================================================== --- optimizer/memoryopt.cpp (revision 447400) +++ optimizer/memoryopt.cpp (working copy) @@ -1273,7 +1273,7 @@ Type *eltType = NULL; Opnd *thePtr = addri->getSrc(0); Type *theType = thePtr->getType(); - if (theType->isManagedPtr()) { + if (theType->isManagedPtr() || theType->isUnmanagedPtr()) { PtrType *thePtrType = (PtrType *) theType; eltType = thePtrType->getPointedToType(); } else { @@ -1386,6 +1386,12 @@ case Op_LdVarAddr: case Op_Phi: break; + case Op_Conv: //the result of a conversion + case Op_TauLdInd: // the result of static field load + { + assert(addr->getType()->isUnmanagedPtr()); + break; + } default: assert(0); break; Index: shared/Type.cpp =================================================================== --- shared/Type.cpp (revision 447400) +++ shared/Type.cpp (working copy) @@ -133,6 +133,7 @@ case Type::NullObject: case Type::Array: case Type::Object: + case Type::UnmanagedPtr: case Type::ManagedPtr: case Type::CompressedSystemObject: case Type::CompressedSystemClass: Index: translator/java/JavaByteCodeTranslator.h =================================================================== --- translator/java/JavaByteCodeTranslator.h (revision 447400) +++ translator/java/JavaByteCodeTranslator.h (working copy) @@ -314,7 +314,8 @@ bool guardedInlineMethod(MethodDesc* methodDesc); bool needsReturnLabel(uint32 off); void genInvokeStatic(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds,Type * returnType); - + void genMagic(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds,Type * returnType); + bool genCharArrayCopy(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds, Type * returnType); bool genArrayCopy(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds, Type * returnType); bool genMinMax(MethodDesc * methodDesc,uint32 numArgs,Opnd ** srcOpnds, Type * returnType); Index: translator/java/JavaByteCodeTranslator.cpp =================================================================== --- translator/java/JavaByteCodeTranslator.cpp (revision 447400) +++ translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -37,6 +37,54 @@ namespace Jitrino { + +static bool isMagicClass(Type* type) { +#ifdef _EM64T_ + return false;//magics are not supported on EM64T today. +#endif + static const char unboxedName[] = "org/vmmagic/unboxed/"; + static const unsigned nameLen = sizeof(unboxedName)-1; + const char* name = type->getName(); + return !strncmp(name, unboxedName, nameLen); +} + +static bool isMagicMethod(MethodDesc* md) { + return isMagicClass(md->getParentType()); +} + +Type* convertMagicType2HIR(TypeManager& tm, Type* type) { + if (!type->isObject() || !type->isNamedType()) { + return type; + } + assert(isMagicClass(type)); + const char* name = type->getName(); + if (!strcmp(name, "org/vmmagic/unboxed/Address") + || !strcmp(name, "org/vmmagic/unboxed/ObjectReference")) + { + return tm.getUnmanagedPtrType(tm.getInt8Type()); + } else if (!strcmp(name, "org/vmmagic/unboxed/Word") + || !strcmp(name, "org/vmmagic/unboxed/Offset") + || !strcmp(name, "org/vmmagic/unboxed/Extent")) + { + return tm.getUIntPtrType(); + } else if (!strcmp(name, "org/vmmagic/unboxed/WordArray") + || !strcmp(name, "org/vmmagic/unboxed/OffsetArray") + || !strcmp(name, "org/vmmagic/unboxed/ExtentArray") + || !strcmp(name, "org/vmmagic/unboxed/AddressArray") + || !strcmp(name, "org/vmmagic/unboxed/ObjectReferenceArray")) + { +#ifdef _EM64T_ + return tm.getArrayType(tm.getInt64Type(), false); +#else + return tm.getArrayType(tm.getInt32Type(), false); +#endif + } + assert(0); + return NULL; +} + + + //----------------------------------------------------------------------------- // inlining policy management //----------------------------------------------------------------------------- @@ -999,6 +1047,9 @@ if (field && field->isStatic()) { Type* fieldType = getFieldType(field,constPoolIndex); assert(fieldType); + if (isMagicClass(fieldType)) { + fieldType = convertMagicType2HIR(typeManager, fieldType); + } pushOpnd(irBuilder.genLdStatic(fieldType,field)); return; } @@ -1027,6 +1078,9 @@ if (field && !field->isStatic()) { Type* fieldType = getFieldType(field,constPoolIndex); assert(fieldType); + if (isMagicClass(fieldType)) { + fieldType = convertMagicType2HIR(typeManager, fieldType); + } pushOpnd(irBuilder.genLdField(fieldType,popOpnd(),field)); return; } @@ -1723,6 +1777,10 @@ uint32 numArgs = methodSig->getNumParams(); Type* returnType = methodSig->getReturnType(); + if (isMagicClass(methodDesc->getParentType())) { + genMagic(methodDesc, numArgs, srcOpnds, returnType); + return; + } // callvirt can throw a null pointer exception Opnd *tauNullChecked = irBuilder.genTauCheckNull(srcOpnds[0]); Opnd* thisOpnd = srcOpnds[0]; @@ -2576,42 +2634,9 @@ Type * returnType) { Opnd *dst; - if ( (translationFlags.magicClass != NULL) && - strcmp(methodDesc->getParentType()->getName(),translationFlags.magicClass)==0) { - - const char *methodName = methodDesc->getName(); - if (strcmp(methodName,"add")==0) { - pushOpnd(irBuilder.genAdd(returnType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No), - srcOpnds[0],srcOpnds[1])); - return; - } - if (strncmp(methodName,"prefetch",8)==0) { - assert(numArgs == 3); - assert(returnType->isVoid()); - irBuilder.genPrefetch(srcOpnds[0],srcOpnds[1],srcOpnds[2]); - return; - } - if (strncmp(methodName,"loadField",9)==0) { - NamedType *fieldType = (NamedType *)returnType; - int index = ((ConstInst*)srcOpnds[1]->getInst())->getValue().i4; - FieldDesc *fd = compilationInterface.resolveFieldByIndex( - (NamedType*)srcOpnds[0]->getType(),index,&fieldType); - pushOpnd (irBuilder.genLdField(returnType,srcOpnds[0],fd)); - return; - } - if (strncmp(methodName,"loadElement",11)==0) { - Type *type = srcOpnds[0]->getType(); - assert(type->isArrayType()); - pushOpnd(irBuilder.genLdElem( - ((ArrayType*)type)->getElementType(),srcOpnds[0],srcOpnds[1])); - return; - } - if (strncmp(methodName,"distance",8)==0) { - pushOpnd(irBuilder.genSub(returnType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No), - srcOpnds[0],srcOpnds[1])); - return; - } - ::std::cerr << "Unknown Magic " << methodName << ::std::endl; + if (isMagicMethod(methodDesc)) { + genMagic(methodDesc, numArgs, srcOpnds, returnType); + return; } if (inlineMethod(methodDesc)) { if(Log::isEnabled()) { @@ -3431,4 +3456,206 @@ return off - offset; } +void JavaByteCodeTranslator::genMagic(MethodDesc *md, uint32 numArgs, Opnd **srcOpnds, Type *magicRetType) { + const char* mname = md->getName(); + PtrType* unmanagedPtrType = typeManager.getUnmanagedPtrType(typeManager.getInt8Type()); + Type* resType = convertMagicType2HIR(typeManager, magicRetType); + Opnd* tauSafe = irBuilder.genTauSafe(); + Opnd* arg0 = numArgs >= 1 ? srcOpnds[0]: NULL; + Opnd* arg1 = numArgs >= 2 ? srcOpnds[1]: NULL; + Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); + + + // max, one, zero + int theConst = 0; + bool loadConst = false; + if (!strcmp(mname, "max")) { loadConst = true; theConst = -1;} + else if (!strcmp(mname, "one")) { loadConst = true; theConst = 1;} + else if (!strcmp(mname, "zero")) { loadConst = true; theConst = 0;} + else if (!strcmp(mname, "nullReference")) { loadConst = true; theConst = 0;} + if (loadConst) { + //todo: recheck and fix the type of the const: + ConstInst::ConstValue v; v.i4 = theConst; + Opnd* res = irBuilder.genLdConstant(typeManager.getUIntPtrType(), v);//todo:clean typing + if (resType->isPtr()) { + res = irBuilder.genConv(resType, resType->tag, mod, res); + } + pushOpnd(res); + return; + } + + // + // fromXXX, toXXX - static creation from something + // + if (!strcmp(mname, "fromInt") + || !strcmp(mname, "fromIntSignExtend") + || !strcmp(mname, "fromIntZeroExtend") + || !strcmp(mname, "fromObject") + || !strcmp(mname, "toAddress") + || !strcmp(mname, "toObjectReference") + || !strcmp(mname, "toInt") + || !strcmp(mname, "toLong") + || !strcmp(mname, "toObjectRef") + || !strcmp(mname, "toWord") + || !strcmp(mname, "toAddress") + || !strcmp(mname, "toObject") + || !strcmp(mname, "toExtent") + || !strcmp(mname, "toOffset")) + { + assert(numArgs == 1); + if (resType == arg0->getType()) { + pushOpnd(irBuilder.genCopy(arg0)); + return; + } + Opnd* res = irBuilder.genConv(resType, resType->tag, mod, arg0); + pushOpnd(res); + return; + } + + // + // is one arg testing + // + bool isOp = false; + if (!strcmp(mname, "isZero")) { isOp = true; theConst = 0; } + else if (!strcmp(mname, "isMax")) { isOp = true; theConst = ~0; } + else if (!strcmp(mname, "isNull")) { isOp = true; theConst = 0; } + if (isOp) { + //todo: unsigned + assert(numArgs == 1); + Opnd* res = irBuilder.genCmp(resType, Type::Int32, Cmp_EQ, arg0, irBuilder.genLdConstant(theConst)); + pushOpnd(res); + return; + } + + + // + // EQ, GE, GT, LE, LT, sXX - 2 args compare + // + ComparisonModifier cm = Cmp_Mask; + bool commuteOpnds=false; + if (!strcmp(mname, "EQ")) { cm = Cmp_EQ; } + else if (!strcmp(mname, "equals")) { cm = Cmp_EQ; } + else if (!strcmp(mname, "NE")) { cm = Cmp_NE_Un; } + else if (!strcmp(mname, "GE")) { cm = Cmp_GTE;} + else if (!strcmp(mname, "GT")) { cm = Cmp_GT; } + else if (!strcmp(mname, "LE")) { cm = Cmp_GTE; commuteOpnds = true;} + else if (!strcmp(mname, "LT")) { cm = Cmp_GT; commuteOpnds = true;} + if (cm!=Cmp_Mask) { + assert(numArgs == 2); + assert(arg0->getType() == arg1->getType()); + Opnd* op0 = commuteOpnds ? arg1 : arg0; + Opnd* op1 = commuteOpnds ? arg0 : arg1; + Opnd* res = irBuilder.genCmp(resType, arg0->getType()->tag, cm, op0, op1); + pushOpnd(res); + return; + } + + + // + // plus, minus, xor, or, and ... etc - 1,2 args arithmetics + // + if (!strcmp(mname, "plus")) { + assert(numArgs==2); + if (resType->isPtr()) { + pushOpnd(irBuilder.genAddScaledIndex(arg0, arg1)); + } else { + pushOpnd(irBuilder.genAdd(resType, mod, arg0, arg1)); + } + return; + } + if (!strcmp(mname, "minus")){ + assert(numArgs==2); + if (resType->isPtr()) { + Opnd* negArg1 = irBuilder.genNeg(typeManager.getInt32Type(), arg1); + pushOpnd(irBuilder.genAddScaledIndex(arg0, negArg1)); + } else { + pushOpnd(irBuilder.genSub(resType, mod, arg0, arg1)); + } + return; + } + if (!strcmp(mname, "or")) { assert(numArgs==2); pushOpnd(irBuilder.genOr (resType, arg0, arg1)); return;} + if (!strcmp(mname, "xor")) { assert(numArgs==2); pushOpnd(irBuilder.genXor(resType, arg0, arg1)); return;} + if (!strcmp(mname, "and")) { assert(numArgs==2); pushOpnd(irBuilder.genAnd(resType, arg0, arg1)); return;} + if (!strcmp(mname, "not")) { assert(numArgs==1); pushOpnd(irBuilder.genNot(resType, arg0)); return;} + + + // + // shifts + // + //todo: fix shifts + mod = Modifier(ShiftMask_Masked)|Modifier(SignedOp); //todo: unsigned! + if (!strcmp(mname, "lsh")) {assert(numArgs==2); pushOpnd(irBuilder.genShl(resType,mod, arg0, arg1)); return;} + else if (!strcmp(mname, "rsha")){assert(numArgs==2); pushOpnd(irBuilder.genShr(resType,mod, arg0, arg1)); return;} + else if (!strcmp(mname, "rshl")){assert(numArgs==2); pushOpnd(irBuilder.genShr(resType,mod, arg0, arg1)); return;} + + + //TODO: test loads and stores!! + // + // loadXYZ.. + // + //todo: fix unsigned + Type::Tag type = Type::Void; + if (!strcmp(mname, "loadObjectReference")) { type = Type::Int32;} + else if (!strcmp(mname, "loadAddress")) { type = Type::Int32;} + else if (!strcmp(mname, "loadWord")) { type = Type::Int32;} + else if (!strcmp(mname, "loadByte")) { type = Type::Int8;} + else if (!strcmp(mname, "loadChar")) { type = Type::Char;} + else if (!strcmp(mname, "loadDouble")) { type = Type::Double;} + else if (!strcmp(mname, "loadFloat")) { type = Type::Float;} + else if (!strcmp(mname, "loadInt")) { type = Type::Int32;} + else if (!strcmp(mname, "loadLong")) { type = Type::Int64;} + else if (!strcmp(mname, "loadShort")) { type = Type::Int16;} + if (type !=Type::Void) { + assert(numArgs == 1 || numArgs == 2); + Opnd* effectiveAddress = arg0; + if (numArgs == 2) {//load by offset + effectiveAddress = irBuilder.genAddScaledIndex(arg0, arg1); + } + Opnd* res = irBuilder.genTauLdInd(AutoCompress_No, resType, type, effectiveAddress, tauSafe, tauSafe); + pushOpnd(res); + return; + } + + // + // store(XYZ) + // + if (!strcmp(mname, "store")) { + assert(numArgs==2 || numArgs == 3); + Opnd* effectiveAddress = arg0; + if (numArgs == 3) { // store by offset + effectiveAddress = irBuilder.genAddScaledIndex(arg0, srcOpnds[2]); + } + PtrType* t = (PtrType*)effectiveAddress->getType(); + irBuilder.genTauStInd(arg1->getType(), effectiveAddress, arg1, tauSafe, tauSafe, tauSafe); + return; + } + + + // + //Arrays + // + if (!strcmp(mname, "create")) { assert(numArgs==1); pushOpnd(irBuilder.genNewArray(resType->asNamedType(),arg0)); return;} + if (!strcmp(mname, "set")) { + assert(numArgs == 3); + Opnd* arg2 = srcOpnds[2]; + irBuilder.genStElem(resType, arg0, arg1, arg2, tauSafe, tauSafe, tauSafe); + return; + } + if (!strcmp(mname, "get")) { + assert(numArgs == 2); + //TODO: arrays are signed! check unsigned convertion! + //TODO: remove tausafe? + Opnd* res = irBuilder.genLdElem(resType, arg0, arg1, tauSafe, tauSafe); + pushOpnd(res); + return; + } + if (!strcmp(mname, "length")) { + pushOpnd(irBuilder.genArrayLen(typeManager.getInt32Type(), Type::Int32, arg0)); + return; + } + + assert(0); + return; +} + } //namespace Jitrino Index: translator/TranslatorIntfc.h =================================================================== --- translator/TranslatorIntfc.h (revision 447400) +++ translator/TranslatorIntfc.h (working copy) @@ -57,12 +57,10 @@ 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 magicMinMaxAbs : 1; // recognize, e.g., java/lang/Math.min/max/abs 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 - char *magicClass; // Name of the MagicClass. NULL if no class specified. }; class IRBuilderAction; Index: translator/TranslatorIntfc.cpp =================================================================== --- translator/TranslatorIntfc.cpp (revision 447400) +++ translator/TranslatorIntfc.cpp (working copy) @@ -87,11 +87,9 @@ " 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"\ - " useMagicMethods[={MagicClass name}] - use magic methods with magic class named MagicClass\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"\ - " magicMinMaxAbs[={on|OFF}] - treat java/lang/Math::min and max as magic\n"\ " genMinMaxAbs[={on|OFF}] - use special opcodes for Min/Max/Abs\n"\ " genFMinMaxAbs[={on|OFF}] - also use opcodes for float Min/Max/Abs\n"; @@ -126,7 +124,6 @@ flags.inlineMethods = getBoolArg("inlineMethods", false); flags.guardedInlining = getBoolArg("guardedInlining", false); - flags.magicMinMaxAbs = getBoolArg("magicMinMaxAbs", false); flags.genMinMaxAbs = getBoolArg("genMinMaxAbs", false); flags.genFMinMaxAbs = getBoolArg("genFMinMaxAbs", false); @@ -137,7 +134,6 @@ flags.inlineSkipTable = new Method_Table(strdup(skipMethods), "SKIP_METHODS", true); } - flags.magicClass=(char *)getStringArg("useMagicMethods", NULL); }