Index: vm/jitrino/src/vm/drl/DrlVMInterface.cpp =================================================================== --- vm/jitrino/src/vm/drl/DrlVMInterface.cpp (revision 518038) +++ 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 518038) +++ 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 518038) +++ vm/jitrino/src/translator/java/JavaLabelPrepass.cpp (working copy) @@ -1413,24 +1413,38 @@ pushType(type); } -void JavaLabelPrepass::pseudoInvoke(const char* mdesc) { +void JavaLabelPrepass::pseudoInvoke(const char* methodSig) { - assert(mdesc); - unsigned numArgs = 0; - unsigned index; + assert(methodSig); + uint32 numArgs = getNumArgsBySignature(methodSig); + // pop numArgs items + for (int i=numArgs-1; i>=0; i--) + popType(); + + // recognize and push respective returnType + Type* retType = getRetTypeBySignature(methodSig, typeManager); + assert(retType); + + // push the return type + if (retType->tag != Type::Void) { + pushType(typeManager.toInternalType(retType)); + } +} + +uint32 JavaLabelPrepass::getNumArgsBySignature(const char*& methodSig) +{ + assert(methodSig); + assert(*methodSig == '('); + uint32 numArgs = 0; + // start just after '(' and go until ')' counting 'numArgs' - for( index = 1; mdesc[index] != ')'; index++ ) { - switch( mdesc[index] ) + for(++methodSig ;*methodSig != ')'; methodSig++) { + switch( *methodSig ) { case 'L': - // skip method name - do { - index++; - assert( mdesc[index] ); - } while( mdesc[index] != ';' ); - numArgs++; - break; + // skip class name + while( *(++methodSig) != ';' ) assert(*methodSig); case 'B': case 'C': case 'D': @@ -1446,22 +1460,36 @@ 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--) - popType(); - // move index to the first position after ')' - index++; - // recognize and push respective returnType - Type* retType = 0; - switch( mdesc[index] ) + } + // the last observed index should point to ')' after getNumArgsBySignature call + assert(*methodSig == ')'); + + return numArgs; +} + +Type* JavaLabelPrepass::getRetTypeBySignature(const char* methodSig, TypeManager& typeManager) +{ + assert(*methodSig == '(' || *methodSig == ')'); + while( *(methodSig++) != ')' ); // in case getNumArgsBySignature was not run earlier + + Type* retType = NULL; + uint32 arrayDim = 0; + + // collect array dimension if any + while( *(methodSig) == '[' ) { + arrayDim++; + methodSig++; + } + + switch( *methodSig ) { + case 'L': + retType = typeManager.getNullObjectType(); + break; case 'B': retType = typeManager.getInt8Type(); break; @@ -1486,25 +1514,29 @@ case 'Z': retType = typeManager.getBooleanType(); break; - case 'L': - 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 + case '[': // all '[' are already skipped + case '(': // we have already pass it + case ')': // we have just leave it back + default: // impossible! Verifier must check and catch this + assert(0); + retType = typeManager.getNullObjectType(); break; } assert(retType); - // push the return type - if (retType->tag != Type::Void) { - pushType(typeManager.toInternalType(retType)); + + 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; } + for (;arrayDim > 0; arrayDim--) { + 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 518038) +++ 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); + static Type* getRetTypeBySignature(const char* methodSig, TypeManager& tm); // remaining instructions Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 518038) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -1746,95 +1746,24 @@ //----------------------------------------------------------------------------- // for invoke emulation if resolution fails //----------------------------------------------------------------------------- -void JavaByteCodeTranslator::pseudoInvoke(const char* mdesc) { +void JavaByteCodeTranslator::pseudoInvoke(const char* methodSig) +{ + uint32 numArgs = JavaLabelPrepass::getNumArgsBySignature(methodSig); - assert(mdesc); - unsigned numArgs = 0; - unsigned 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, 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 +1907,8 @@ // 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); + returnType = JavaLabelPrepass::getRetTypeBySignature(methodSig_string, typeManager); } Opnd* dst = irBuilder.genTauVirtualCall(methodDesc,returnType, @@ -2110,9 +2040,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 +2083,8 @@ // 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); + returnType = JavaLabelPrepass::getRetTypeBySignature(methodSig_string, typeManager); } dst = irBuilder.genTauVirtualCall(methodDesc, returnType,