Index: vm/jitrino/src/vm/drl/DrlVMInterface.cpp =================================================================== --- vm/jitrino/src/vm/drl/DrlVMInterface.cpp (revision 551181) +++ vm/jitrino/src/vm/drl/DrlVMInterface.cpp (working copy) @@ -837,8 +837,7 @@ NamedType* CompilationInterface::getNamedType(Class_Handle enclClass, uint32 cpIndex, ResolveNewCheck checkNew) { Class_Handle ch = NULL; - bool lazy = typeManager.isLazyResolutionMode(); - if (lazy && !class_is_cp_entry_resolved(compileHandle, enclClass, cpIndex)) { + if (typeManager.isLazyResolutionMode() && !class_is_cp_entry_resolved(compileHandle, enclClass, cpIndex)) { NamedType * res = getUnresolvedType(typeManager, enclClass, cpIndex); return res; } else { @@ -848,12 +847,7 @@ ch = resolve_class(compileHandle,enclClass,cpIndex); } if (ch == NULL) { - if (lazy) {//instantiation of abstract/private class -> do it lazily - assert(checkNew == ResolveNewCheck_DoCheck); - return typeManager.getUnresolvedObjectType(); - } else { - return NULL; - } + return typeManager.getUnresolvedObjectType(); } } if (class_is_primitive(ch)) { @@ -961,7 +955,7 @@ assert(fieldTypeName); return getTypeFromDescriptor(enclClass, fieldTypeName); } - return typeManager.getNullObjectType(); + return typeManager.getUnresolvedObjectType(); case JAVA_TYPE_VOID: // class_get_cp_field_type can't return VOID case JAVA_TYPE_STRING: // class_get_cp_field_type can't return STRING Index: vm/jitrino/src/shared/Type.cpp =================================================================== --- vm/jitrino/src/shared/Type.cpp (revision 551181) +++ vm/jitrino/src/shared/Type.cpp (working copy) @@ -275,7 +275,7 @@ if (type1->isUnresolvedType() || type2->isUnresolvedType()) { if (type1->isNullObject()) return type2; if (type2->isNullObject()) return type1; - return type1->isUnresolvedType() ? type2 : type1; + return type1->isUnresolvedType() ? type1 : type2; } if ( type2->isObject() && (oneIsCompressed ? (type1 == getCompressedNullObjectType()) @@ -446,8 +446,7 @@ } } type = new (memManager) ArrayType(elemNamedType,arrayVMTypeHandle,*this, isCompressed); - if (arrayVMTypeHandle != (void*)(POINTER_SIZE_INT)0xdeadbeef - && (type->isUnresolvedType() || type->getAllocationHandle()!=0)) + if (type->isUnresolvedType() || type->getAllocationHandle()!=0) { // type can be cached lookupTable.insert(elemNamedType,type); } Index: vm/jitrino/src/translator/java/JavaLabelPrepass.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaLabelPrepass.cpp (revision 551181) +++ vm/jitrino/src/translator/java/JavaLabelPrepass.cpp (working copy) @@ -394,11 +394,13 @@ Type* exceptionType = NULL; if (exceptionTypeToken != 0) { exceptionType = compilationInterface.getNamedType(enclosingMethod->getParentHandle(),exceptionTypeToken, ResolveNewCheck_NoCheck); - if(!exceptionType) { // the type can not be resolved. LinkingException must be thrown - return 0; - } + assert(exceptionType); if (exceptionType->isUnresolvedObject()) { - //WORKAROUND! resolving exception type during a compilation session!!! + if(!compilationInterface.getTypeManager().isLazyResolutionMode()) { + // the type can not be resolved. LinkingException must be thrown + return 0; + } + //WORKAROUND! resolving exception type during a compilation session!!! //Details: using singleton UnresolvedObjectType we unable to //distinct exception types if there are several unresolved exceptions in a single try block //usually verifier loads all exception types caught for in method @@ -1121,12 +1123,8 @@ Type* nType = compilationInterface.getNamedType(methodDesc.getParentHandle(), constPoolIndex, ResolveNewCheck_DoCheck); - if (nType) { - slot.type = nType; - } else { - assert(!typeManager.isLazyResolutionMode()); - slot.type = typeManager.getNullObjectType(); - } + assert(nType); + slot.type = nType; slot.vars = NULL; jitrino_assert( slot.type); pushType(slot); @@ -1162,13 +1160,8 @@ StateInfo::setExactType(&slot); Type* type = compilationInterface.getNamedType(methodDesc.getParentHandle(), constPoolIndex); - - if (type) { - slot.type = typeManager.getArrayType(type); - } else { - assert(!typeManager.isLazyResolutionMode()); - slot.type = typeManager.getNullObjectType(); - } + assert(type); + slot.type = typeManager.getArrayType(type); slot.vars = NULL; jitrino_assert( slot.type); pushType(slot); @@ -1191,13 +1184,7 @@ return; } Type* type = compilationInterface.getNamedType(methodDesc.getParentHandle(), constPoolIndex); - if (!type) { - assert(!typeManager.isLazyResolutionMode()); - // leave stack as is as in case of success because - // resolution of item by constPoolIndex fails and - // respective exception will be thrown - return; - } + assert(type); popAndCheck(A); pushType(type); } @@ -1339,11 +1326,7 @@ popAndCheck(int32Type); } Type *type = compilationInterface.getNamedType(methodDesc.getParentHandle(), constPoolIndex); - if ( !type ) { - assert(!typeManager.isLazyResolutionMode()); - type = typeManager.getNullObjectType(); - } - jitrino_assert( type); + jitrino_assert(type); pushType(type); } @@ -1427,7 +1410,7 @@ { case 'L': { if (!typeManager.isLazyResolutionMode()) { - retType = typeManager.getNullObjectType(); + retType = typeManager.getUnresolvedObjectType(); } else { retType = ci.getTypeFromDescriptor(enclClass, origSig); //in lazy resolution mode retType is already valid array type @@ -1467,21 +1450,14 @@ case ')': // we have just leave it back default: // impossible! Verifier must check and catch this assert(0); - retType = typeManager.getNullObjectType(); + retType = typeManager.getUnresolvedObjectType(); break; } assert(retType); - void* arrVMTypeHandle = NULL; - if(retType == typeManager.getNullObjectType()) { - assert(!typeManager.isLazyResolutionMode()); - // VM can not operate with an array of NullObjects - // Let's cheat here - arrVMTypeHandle = (void*)(POINTER_SIZE_INT)0xdeadbeef; - } if (!arrayIsWrapped && arrayDim > 0) { for (;arrayDim > 0; arrayDim--) { - retType = typeManager.getArrayType(retType, false, arrVMTypeHandle); + retType = typeManager.getArrayType(retType, false); } } return retType; Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 551181) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -623,13 +623,10 @@ opnd = irBuilder.genLdRef(&methodToCompile,constPoolIndex,constantType); } else if (constantType->isSystemClass()) { NamedType *literalType = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex); - if (!literalType) { + if (!typeManager.isLazyResolutionMode() && literalType->isUnresolvedType()) { linkingException(constPoolIndex, OPCODE_LDC); - pushOpnd(irBuilder.genLdNull()); - return; - } else { - opnd = irBuilder.genLdRef(&methodToCompile,constPoolIndex,constantType); } + opnd = irBuilder.genLdRef(&methodToCompile,constPoolIndex,constantType); } else { const void* constantAddress = compilationInterface.getConstantValue(&methodToCompile,constPoolIndex); @@ -772,19 +769,17 @@ if (!fieldValueInlined){ pushOpnd(irBuilder.genLdStatic(fieldType, field)); } - } else if (typeManager.isLazyResolutionMode()) { + } else { + if (!typeManager.isLazyResolutionMode()) { + // generate helper call for throwing respective exception + linkingException(constPoolIndex, OPCODE_GETSTATIC); + } const char* fieldTypeName = const_pool_get_field_descriptor(methodToCompile.getParentHandle(), constPoolIndex); bool fieldIsMagic = isVMMagicClass(fieldTypeName); Type* fieldType = fieldIsMagic ? convertVMMagicType2HIR(typeManager, fieldTypeName) : compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex); Opnd* res = irBuilder.genLdStaticWithResolve(fieldType, methodToCompile.getParentType()->asObjectType(), constPoolIndex); pushOpnd(res); - } else { - // generate helper call for throwing respective exception - linkingException(constPoolIndex, OPCODE_GETSTATIC); - Type* type = compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex); - ConstInst::ConstValue nullValue; - pushOpnd(irBuilder.genLdConstant(type,nullValue)); } } @@ -799,17 +794,17 @@ fieldType = convertVMMagicType2HIR(typeManager, fieldType); } irBuilder.genStStatic(fieldType,field,popOpnd()); - } else if (typeManager.isLazyResolutionMode()) { + } else { + if (!typeManager.isLazyResolutionMode()) { + // generate helper call for throwing respective exception + linkingException(constPoolIndex, OPCODE_PUTSTATIC); + } const char* fieldTypeName = const_pool_get_field_descriptor(methodToCompile.getParentHandle(), constPoolIndex); bool fieldIsMagic = isVMMagicClass(fieldTypeName); Type* fieldType = fieldIsMagic ? convertVMMagicType2HIR(typeManager, fieldTypeName) : compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex); Opnd* value = popOpnd(); irBuilder.genStStaticWithResolve(fieldType, methodToCompile.getParentType()->asObjectType(), constPoolIndex, value); - } else { - // generate helper call for throwing respective exception - linkingException(constPoolIndex, OPCODE_PUTSTATIC); - popOpnd(); } } @@ -822,7 +817,11 @@ fieldType = convertVMMagicType2HIR(typeManager, fieldType); } pushOpnd(irBuilder.genLdField(fieldType,popOpnd(),field)); - } else if (typeManager.isLazyResolutionMode()) { + } else { + if (!typeManager.isLazyResolutionMode()) { + // generate helper call for throwing respective exception + linkingException(constPoolIndex, OPCODE_GETFIELD); + } Type* fieldType = compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex); if (isVMMagicClass(fieldType->getName())) { fieldType = convertVMMagicType2HIR(typeManager, fieldType); @@ -830,11 +829,6 @@ Opnd* base = popOpnd(); Opnd* res = irBuilder.genLdFieldWithResolve(fieldType, base, methodToCompile.getParentType()->asObjectType(), constPoolIndex); pushOpnd(res); - } else { - // generate helper call for throwing respective exception - linkingException(constPoolIndex, OPCODE_GETFIELD); - popOpnd(); - pushOpnd(irBuilder.genLdNull()); } } @@ -847,16 +841,15 @@ Opnd* value = popOpnd(); Opnd* ref = popOpnd(); irBuilder.genStField(fieldType,ref,field,value); - } else if (typeManager.isLazyResolutionMode()) { + } else { + if (!typeManager.isLazyResolutionMode()) { + // generate helper call for throwing respective exception + linkingException(constPoolIndex, OPCODE_PUTFIELD); + } Type* type = compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex); Opnd* value = popOpnd(); Opnd* base = popOpnd(); irBuilder.genStFieldWithResolve(type, base, methodToCompile.getParentType()->asObjectType(), constPoolIndex, value); - } else { - // generate helper call for throwing respective exception - linkingException(constPoolIndex, OPCODE_PUTFIELD); - popOpnd(); - popOpnd(); } } //----------------------------------------------------------------------------- @@ -1501,14 +1494,10 @@ JavaByteCodeTranslator::invokevirtual(uint32 constPoolIndex) { MethodDesc* methodDesc = compilationInterface.getVirtualMethod(methodToCompile.getParentHandle(), constPoolIndex); if (!methodDesc) { - if (typeManager.isLazyResolutionMode()) { - genCallWithResolve(OPCODE_INVOKEVIRTUAL, constPoolIndex); - } else { + if (!typeManager.isLazyResolutionMode()) { linkingException(constPoolIndex, OPCODE_INVOKEVIRTUAL); - const char* methodSig_string = methodSignatureString(constPoolIndex); - popOpnd(); // is not static - pseudoInvoke(methodSig_string); } + genCallWithResolve(OPCODE_INVOKEVIRTUAL, constPoolIndex); return; } jitrino_assert(methodDesc); @@ -1565,14 +1554,10 @@ JavaByteCodeTranslator::invokespecial(uint32 constPoolIndex) { MethodDesc* methodDesc = compilationInterface.getSpecialMethod(methodToCompile.getParentHandle(), constPoolIndex); if (!methodDesc) { - if (typeManager.isLazyResolutionMode()) { - genCallWithResolve(OPCODE_INVOKESPECIAL, constPoolIndex); - } else { + if (!typeManager.isLazyResolutionMode()) { linkingException(constPoolIndex, OPCODE_INVOKESPECIAL); - const char* methodSig_string = methodSignatureString(constPoolIndex); - popOpnd(); // is not static - pseudoInvoke(methodSig_string); } + genCallWithResolve(OPCODE_INVOKESPECIAL, constPoolIndex); return; } jitrino_assert(methodDesc); @@ -1609,13 +1594,10 @@ JavaByteCodeTranslator::invokestatic(uint32 constPoolIndex) { MethodDesc* methodDesc = compilationInterface.getStaticMethod(methodToCompile.getParentHandle(), constPoolIndex); if (!methodDesc) { - if (typeManager.isLazyResolutionMode()) { - genCallWithResolve(OPCODE_INVOKESTATIC, constPoolIndex); - } else { + if (!typeManager.isLazyResolutionMode()) { linkingException(constPoolIndex, OPCODE_INVOKESTATIC); - const char* methodSig_string = methodSignatureString(constPoolIndex); - pseudoInvoke(methodSig_string); } + genCallWithResolve(OPCODE_INVOKESTATIC, constPoolIndex); return; } @@ -1654,14 +1636,10 @@ JavaByteCodeTranslator::invokeinterface(uint32 constPoolIndex,uint32 count) { MethodDesc* methodDesc = compilationInterface.getInterfaceMethod(methodToCompile.getParentHandle(), constPoolIndex); if (!methodDesc) { - if (typeManager.isLazyResolutionMode()) { - genCallWithResolve(OPCODE_INVOKEINTERFACE, constPoolIndex); - } else { + if (!typeManager.isLazyResolutionMode()) { linkingException(constPoolIndex, OPCODE_INVOKEINTERFACE); - const char* methodSig_string = methodSignatureString(constPoolIndex); - popOpnd(); // is not static - pseudoInvoke(methodSig_string); } + genCallWithResolve(OPCODE_INVOKEINTERFACE, constPoolIndex); return; } jitrino_assert(methodDesc); @@ -1709,15 +1687,11 @@ void JavaByteCodeTranslator::new_(uint32 constPoolIndex) { NamedType* type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex, ResolveNewCheck_DoCheck); - - if (!type) { - assert(!typeManager.isLazyResolutionMode()); - linkingException(constPoolIndex, OPCODE_NEW); - pushOpnd(irBuilder.genLdNull()); - return; - } jitrino_assert(type); if (type->isUnresolvedObject()) { + if (!typeManager.isLazyResolutionMode()) { + linkingException(constPoolIndex, OPCODE_NEW); + } pushOpnd(irBuilder.genNewObjWithResolve(methodToCompile.getParentType()->asObjectType(), constPoolIndex)); } else { pushOpnd(irBuilder.genNewObj(type)); @@ -1759,16 +1733,11 @@ void JavaByteCodeTranslator::anewarray(uint32 constPoolIndex) { NamedType* type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex); - if (!type) { - assert(!typeManager.isLazyResolutionMode()); - linkingException(constPoolIndex, OPCODE_ANEWARRAY); - popOpnd(); - pushOpnd(irBuilder.genLdNull()); - return; - } Opnd* sizeOpnd = popOpnd(); if (type->isUnresolvedType()) { - assert(typeManager.isLazyResolutionMode()); + if (!typeManager.isLazyResolutionMode()) { + linkingException(constPoolIndex, OPCODE_ANEWARRAY); + } //res type can be an array of multi array with uninitialized dimensions. pushOpnd(irBuilder.genNewArrayWithResolve(type, sizeOpnd, methodToCompile.getParentType()->asObjectType(), constPoolIndex)); } else { @@ -1779,23 +1748,17 @@ void JavaByteCodeTranslator::multianewarray(uint32 constPoolIndex,uint8 dimensions) { NamedType* arraytype = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex); - if (!arraytype) { - linkingException(constPoolIndex, OPCODE_MULTIANEWARRAY); - // pop the sizes - for (int i=dimensions-1; i>=0; i--) { - popOpnd(); - } - pushOpnd(irBuilder.genLdNull()); - return; - } assert(arraytype->isArray()); jitrino_assert(dimensions > 0); Opnd** countOpnds = new (memManager) Opnd*[dimensions]; // pop the sizes - for (int i=dimensions-1; i>=0; i--) { + for (int i = dimensions - 1; i >= 0; i--) { countOpnds[i] = popOpnd(); } if (arraytype->isUnresolvedType()) { + if (!typeManager.isLazyResolutionMode()) { + linkingException(constPoolIndex, OPCODE_MULTIANEWARRAY); + } pushOpnd(irBuilder.genMultianewarrayWithResolve( arraytype, methodToCompile.getParentType()->asObjectType(),constPoolIndex, dimensions,countOpnds )); @@ -1824,14 +1787,11 @@ void JavaByteCodeTranslator::checkcast(uint32 constPoolIndex) { NamedType *type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex); - if (!type) { - assert(!typeManager.isLazyResolutionMode()); - linkingException(constPoolIndex, OPCODE_CHECKCAST); - return; // can be left as is - } Opnd* objOpnd = popOpnd(); if (type->isUnresolvedType()) { - assert(typeManager.isLazyResolutionMode()); + if (!typeManager.isLazyResolutionMode()) { + linkingException(constPoolIndex, OPCODE_CHECKCAST); + } pushOpnd(irBuilder.genCastWithResolve(objOpnd, type, methodToCompile.getParentType()->asObjectType(), constPoolIndex)); } else { pushOpnd(irBuilder.genCast(objOpnd, type)); @@ -1841,18 +1801,14 @@ int JavaByteCodeTranslator::instanceof(const uint8* bcp, uint32 constPoolIndex, uint32 off) { NamedType *type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex); - if (!type) { - linkingException(constPoolIndex, OPCODE_INSTANCEOF); - popOpnd(); // emulation of unsuccessful 'instanceof' - pushOpnd(irBuilder.genLdConstant((int32)0)); - return 3; - } Opnd* src = popOpnd(); Type* srcType = src->getType(); Opnd* res = NULL; if (type->isUnresolvedType()) { - assert(typeManager.isLazyResolutionMode()); + if (!typeManager.isLazyResolutionMode()) { + linkingException(constPoolIndex, OPCODE_INSTANCEOF); + } res = irBuilder.genInstanceOfWithResolve(src, methodToCompile.getParentType()->asObjectType(), constPoolIndex); } else if( !srcType->isUnresolvedType() && !srcType->isInterface() Index: src/test/regression/H4267/run.test.xml =================================================================== --- src/test/regression/H4267/run.test.xml (revision 0) +++ src/test/regression/H4267/run.test.xml (revision 0) @@ -0,0 +1,12 @@ + + + + + + + + Index: src/test/regression/H4267/UnresolvedArrayElem.java =================================================================== --- src/test/regression/H4267/UnresolvedArrayElem.java (revision 0) +++ src/test/regression/H4267/UnresolvedArrayElem.java (revision 0) @@ -0,0 +1,30 @@ +package org.apache.harmony.drlvm.tests.regression.h4267; + +import junit.framework.TestCase; + +public class UnresolvedArrayElem extends TestCase { + + public void test() throws Exception { + try { + new TClass().test1(); + System.out.println("FAILED: NoClassDefFoundError was not thrown"); + fail(); + } catch (NoClassDefFoundError e) { + System.out.println("PASSED: " + e.getMessage()); + } + } +} + +class TClass { + + void test1() { + RemoveMe[] arr = test(); + RemoveMe element = arr[3]; + } + + RemoveMe[] test() { + return new RemoveMe[10]; + } +} + +class RemoveMe {}