Index: vm/jitrino/src/vm/drl/DrlVMInterface.cpp =================================================================== --- vm/jitrino/src/vm/drl/DrlVMInterface.cpp (revision 516310) +++ vm/jitrino/src/vm/drl/DrlVMInterface.cpp (working copy) @@ -265,6 +265,10 @@ bool DrlVMTypeManager::isSubClassOf(void* vmTypeHandle1,void* vmTypeHandle2) { + if (vmTypeHandle1 == (void*)(POINTER_SIZE_INT)0xdeadbeef || + vmTypeHandle2 == (void*)(POINTER_SIZE_INT)0xdeadbeef ) { + return false; + } return class_is_instanceof((Class_Handle) vmTypeHandle1,(Class_Handle) vmTypeHandle2)?true:false; } Index: vm/jitrino/src/shared/Type.cpp =================================================================== --- vm/jitrino/src/shared/Type.cpp (revision 516310) +++ vm/jitrino/src/shared/Type.cpp (working copy) @@ -427,7 +427,7 @@ } type = new (memManager) ArrayType(elemNamedType,arrayVMTypeHandle,*this, isCompressed); - if (type->getAllocationHandle()!=0) { // type is resolved + if (arrayVMTypeHandle != (void*)(POINTER_SIZE_INT)0xdeadbeef && type->getAllocationHandle()!=0) { // type is resolved lookupTable.insert(elemNamedType,type); } } Index: vm/jitrino/src/translator/java/JavaLabelPrepass.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaLabelPrepass.cpp (revision 516310) +++ vm/jitrino/src/translator/java/JavaLabelPrepass.cpp (working copy) @@ -1413,22 +1413,45 @@ pushType(type); } -void JavaLabelPrepass::pseudoInvoke(const char* mdesc) { +void JavaLabelPrepass::pseudoInvoke(const char* methodSig) { - assert(mdesc); - unsigned numArgs = 0; - unsigned index; + assert(methodSig); + uint32 index = 0; + uint32 numArgs = getNumArgsBySignature(methodSig,index); + // the last observed index should point to ')' after getNumArgsBySignature call + assert(methodSig[index] == ')'); + // pop numArgs items + for (int i=numArgs-1; i>=0; i--) + popType(); + // move index to the first position after ')' + index++; + // recognize and push respective returnType + Type* retType = getRetTypeBySignature(methodSig,index,typeManager); + assert(retType); + + // push the return type + if (retType->tag != Type::Void) { + pushType(typeManager.toInternalType(retType)); + } +} + +uint32 JavaLabelPrepass::getNumArgsBySignature(const char* methodSig, uint32& index) { + assert(methodSig); + assert(index == 0); + assert(methodSig[0] == '('); + uint32 numArgs = 0; + // start just after '(' and go until ')' counting 'numArgs' - for( index = 1; mdesc[index] != ')'; index++ ) { - switch( mdesc[index] ) + for( index = 1; methodSig[index] != ')'; index++ ) { + switch( methodSig[index] ) { case 'L': - // skip method name + // skip class name do { index++; - assert( mdesc[index] ); - } while( mdesc[index] != ';' ); + assert( methodSig[index] ); + } while( methodSig[index] != ';' ); numArgs++; break; case 'B': @@ -1452,16 +1475,34 @@ assert(0); // impossible! Verifier must check and catch this break; } - } - // pop numArgs items - for (int i=numArgs-1; i>=0; i--) - popType(); - // move index to the first position after ')' - index++; - // recognize and push respective returnType + } + return numArgs; +} + +Type* JavaLabelPrepass::getRetTypeBySignature(const char* methodSig, uint32& index, TypeManager& typeManager) { + + if(index == 0) { // getNumArgsBySignature was not run earlier + // skip all till ')' + do{ + index++; + } while( methodSig[index-1] != ')'); + } + assert(index > 0 && methodSig[index-1] == ')'); + Type* retType = 0; - switch( mdesc[index] ) + uint32 arrayDim = 0; + + // collect array dimension if any + while( methodSig[index] == '[') { + arrayDim++; + index++; + } + + switch( methodSig[index] ) { + case 'L': + retType = typeManager.getNullObjectType(); + break; case 'B': retType = typeManager.getInt8Type(); break; @@ -1486,13 +1527,14 @@ case 'Z': retType = typeManager.getBooleanType(); break; - case 'L': - case '[': { + case '[': // all '[' are already skipped + case '(': // we have already pass it + case ')': // we have just leave it back + { + assert(0); retType = typeManager.getNullObjectType(); break; } - case '(': // we have already pass it - case ')': // we have just leave it back case 'V': retType = typeManager.getVoidType(); break; // leave stack as is @@ -1501,10 +1543,18 @@ break; } assert(retType); - // push the return type - if (retType->tag != Type::Void) { - pushType(typeManager.toInternalType(retType)); + + while(arrayDim > 0) { + arrayDim--; + void* arrVMTypeHandle = NULL; + if(retType == typeManager.getNullObjectType()) { + // VM can not operate with an array of NullObjects + // Let's cheat here + arrVMTypeHandle = (void*)(POINTER_SIZE_INT)0xdeadbeef; + } + retType = typeManager.getArrayType(retType, false, arrVMTypeHandle); } + return retType; } void JavaLabelPrepass::invoke(MethodDesc* methodDesc) { Index: vm/jitrino/src/translator/java/JavaLabelPrepass.h =================================================================== --- vm/jitrino/src/translator/java/JavaLabelPrepass.h (revision 516310) +++ vm/jitrino/src/translator/java/JavaLabelPrepass.h (working copy) @@ -330,6 +330,8 @@ void genCompare (Type *type); void invoke (MethodDesc *mdesc); void pseudoInvoke (const char* mdesc); + static uint32 getNumArgsBySignature(const char* methodSig, uint32& index); + static Type* getRetTypeBySignature(const char* methodSig, uint32& index, TypeManager& tm); // remaining instructions Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 516310) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -1746,95 +1746,31 @@ //----------------------------------------------------------------------------- // for invoke emulation if resolution fails //----------------------------------------------------------------------------- -void JavaByteCodeTranslator::pseudoInvoke(const char* mdesc) { +void JavaByteCodeTranslator::pseudoInvoke(const char* methodSig) { - assert(mdesc); - unsigned numArgs = 0; - unsigned index; + assert(methodSig); + uint32 index = 0; + uint32 numArgs = JavaLabelPrepass::getNumArgsBySignature(methodSig,index); + // the last observed index should point to ')' after getNumArgsBySignature call + assert(methodSig[index] == ')'); - // start just after '(' and go until ')' counting 'numArgs' - for( index = 1; mdesc[index] != ')'; index++ ) { - switch( mdesc[index] ) - { - case 'L': - // skip method name - do { - index++; - assert( mdesc[index] ); - } while( mdesc[index] != ';' ); - numArgs++; - break; - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - case 'Z': - numArgs++; - break; - case '[': // do nothing - break; - case '(': // we have started from index = 1 - case ')': // must go out earlier - case 'V': // 'V' can not be in the argument list - assert(0); - break; - default: - assert(0); // impossible! Verifier must check and catch this - break; - } - } // pop numArgs items - for (int i=numArgs-1; i>=0; i--) + for (uint32 i=numArgs-1; i>=0; i--) popOpnd(); + // move index to the first position after ')' index++; - // recognize and push respective returnType - Type* retType = 0; - switch( mdesc[index] ) - { - case 'L': - retType = typeManager.getNullObjectType(); - break; - case 'B': - retType = typeManager.getInt8Type(); - case 'C': - retType = typeManager.getCharType(); - case 'D': - retType = typeManager.getDoubleType(); - case 'F': - retType = typeManager.getSingleType(); - case 'I': - retType = typeManager.getInt32Type(); - case 'J': - retType = typeManager.getInt64Type(); - case 'S': - retType = typeManager.getInt16Type(); - case 'Z': - retType = typeManager.getBooleanType(); - break; - case '[': { - retType = typeManager.getNullObjectType(); - break; - } - case '(': // we have already pass it - case ')': // we have just leave it back - case 'V': - retType = typeManager.getVoidType(); - break; // leave stack as is - default: - assert(0); // impossible! Verifier must check and catch this - break; - } + // recognize and push respective returnType + Type* retType = JavaLabelPrepass::getRetTypeBySignature(methodSig,index,typeManager); assert(retType); - // push NULL as a return type + + // push NULL as a returned object if (retType->tag != Type::Void) { pushOpnd(irBuilder.genLdNull()); } } + //----------------------------------------------------------------------------- // method invocation byte codes //----------------------------------------------------------------------------- @@ -1978,7 +1914,9 @@ // inside the callee (with some "magic" custom class loader for example) // Or respective exception will be thrown there (in the callee) at the attempt to create (new) // an object of unresolved type - returnType = typeManager.getNullObjectType(); + const char* methodSig_string = methodSignatureString(constPoolIndex); + uint32 index = 0; + returnType = JavaLabelPrepass::getRetTypeBySignature(methodSig_string,index,typeManager); } Opnd* dst = irBuilder.genTauVirtualCall(methodDesc,returnType, @@ -2110,9 +2048,9 @@ jitrino_assert(compilationInterface,methodDesc); MethodSignatureDesc* methodSig = methodDesc->getMethodSig(); jitrino_assert(compilationInterface,methodSig); + Type* returnType = methodSig->getReturnType(); uint32 numArgs = methodSig->getNumParams(); Opnd** srcOpnds = popArgs(methodSig); - Type* returnType = methodSig->getReturnType(); // callintf can throw a null pointer exception Opnd *tauNullChecked = irBuilder.genTauCheckNull(srcOpnds[0]); Opnd* thisOpnd = srcOpnds[0]; @@ -2153,7 +2091,9 @@ // inside the callee (with some "magic" custom class loader for example) // Or respective exception will be thrown there (in the callee) at the attempt to create (new) // an object of unresolved type - returnType = typeManager.getNullObjectType(); + const char* methodSig_string = methodSignatureString(constPoolIndex); + uint32 index = 0; + returnType = JavaLabelPrepass::getRetTypeBySignature(methodSig_string,index,typeManager); } dst = irBuilder.genTauVirtualCall(methodDesc, returnType,