Index: vm/vmcore/include/version_svn_tag.h =================================================================== --- vm/vmcore/include/version_svn_tag.h (revision 447400) +++ vm/vmcore/include/version_svn_tag.h (working copy) @@ -17,6 +17,6 @@ #ifndef _VERSION_SVN_TAG_ #define _VERSION_SVN_TAG_ -#define VERSION_SVN_TAG "447024" +#define VERSION_SVN_TAG "447400" #endif // _VERSION_SVN_TAG_ Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.h =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.h (revision 447400) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.h (working copy) @@ -314,6 +314,7 @@ 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); Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 447400) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -37,6 +37,31 @@ namespace Jitrino { + +static bool isMagicClass(NamedType* 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()); +} + +static bool isUnsignedMagicClass(NamedType* type) { + assert(isMagicClass(type)); + const char* name = type->getName(); + bool res = !strcmp(name, "org/vmmagic/unboxed/Extent"); + res = res || !strcmp(name, "org/vmmagic/unboxed/Word"); + return res; +} + + + //----------------------------------------------------------------------------- // inlining policy management //----------------------------------------------------------------------------- @@ -1723,7 +1748,12 @@ uint32 numArgs = methodSig->getNumParams(); Type* returnType = methodSig->getReturnType(); - // callvirt can throw a null pointer exception + 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]; if (methodDesc->getParentType() != thisOpnd->getType()) { @@ -2574,45 +2604,11 @@ uint32 numArgs, Opnd ** srcOpnds, Type * returnType) { + if (isMagicMethod(methodDesc)) { + genMagic(methodDesc, numArgs, srcOpnds, returnType); + return; + } 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 (inlineMethod(methodDesc)) { if(Log::isEnabled()) { Log::out() << "XXX inline static:"; methodDesc->printFullName(Log::out()); Log::out() << ::std::endl; @@ -3431,4 +3427,181 @@ return off - offset; } +void JavaByteCodeTranslator::genMagic(MethodDesc *md, uint32 numArgs, Opnd **srcOpnds, Type *magicRetType) { + const char* mname = md->getName(); + bool isUnsignedClass = isUnsignedMagicClass(md->getParentType()); + NamedType* int32Type = typeManager.getInt32Type(); + NamedType* resType = int32Type; //todo: support unsigned + Opnd* arg0 = numArgs >= 1 ? srcOpnds[0]: NULL; + Opnd* arg1 = numArgs >= 2 ? srcOpnds[1]: NULL; + + // 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) { + pushOpnd(irBuilder.genLdConstant(theConst));//todo: unsigned + 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) { + //todo: unsigned + assert(numArgs == 2); + Opnd* op0 = commuteOpnds ? arg1 : arg0; + Opnd* op1 = commuteOpnds ? arg0 : arg1; + Opnd* res = irBuilder.genCmp(resType, Type::Int32, cm, op0, op1); + pushOpnd(res); + return; + } + + + // + // toInt, toLong, toObjectRef, toWord(), etc. + // + Type::Tag type = Type::Void; + if (!strcmp(mname, "toInt")) { type = Type::Int32; } + else if (!strcmp(mname, "toLong")) { type = Type::Int64; } + else if (!strcmp(mname, "toObjectRef")) { type = Type::Int32; } + else if (!strcmp(mname, "toWord")) { type = Type::Int32; } + else if (!strcmp(mname, "toAddress")) { type = Type::Int32; } + else if (!strcmp(mname, "toObject")) { type = Type::Int32; } + else if (!strcmp(mname, "toExtent")) { type = Type::Int32; } + else if (!strcmp(mname, "toOffset")) { type = Type::Int32; } + + if (type!=Type::Void) { + //todo: unsigned! + assert(numArgs == 1); + pushOpnd(srcOpnds[0]); //push the value back + if (type == Type::Int64) { + i2l(); + } else { + assert(type == Type::Int32); + //do nothing + } + return; + } + + // + // plus, minus, xor, or, and ... etc - 1,2 args arithmetics + // + //todo: unsigned + Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); + if (!strcmp(mname, "plus")) { assert(numArgs==2); pushOpnd(irBuilder.genAdd(resType, mod, arg0, arg1)); return;} + if (!strcmp(mname, "minus")){ assert(numArgs==2); 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;} + + // + // fromXXX - static creation from something + // + if (!strcmp(mname, "fromInt") || !strcmp(mname, "fromIntSignExtend") || !strcmp(mname, "fromIntZeroExtend") + || !strcmp(mname, "fromObject") || !strcmp(mname, "toAddress") || !strcmp(mname, "toObjectReference")) + { + assert(numArgs == 1); + pushOpnd(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 + Opnd* tauSafe = irBuilder.genTauSafe(); + 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); + Opnd* res = irBuilder.genTauLdInd(AutoCompress_No, resType, type, arg0, tauSafe, tauSafe); + pushOpnd(res); + return; + } + + // + // store(XYZ) + // + if (!strcmp(mname, "store")) { + assert(numArgs==2); + irBuilder.genTauStInd(arg1->getType(), arg0, arg1, tauSafe, tauSafe, tauSafe); + return; + } + + + // + //Arrays + // + if (!strcmp(mname, "create")) { assert(numArgs==1); pushOpnd(irBuilder.genNewArray(resType,arg0)); return;} + if (!strcmp(mname, "set")) { + assert(numArgs == 3); + Opnd* arg2 = srcOpnds[2]; + irBuilder.genStElem(resType, arg0, arg1, arg2, tauSafe, tauSafe, tauSafe); //todo: check if tausafe is OK here + return; + } + if (!strcmp(mname, "get")) { + assert(numArgs == 2); + Opnd* res = irBuilder.genLdElem(resType, arg0, arg1, tauSafe, tauSafe); //todo: check if tausafe is OK here + pushOpnd(res); + return; + } + if (!strcmp(mname, "length")) { + pushOpnd(irBuilder.genArrayLen(int32Type, Type::Int32, arg0)); + return; + } + + assert(0); + return; +} + } //namespace Jitrino