diff --git a/vm/jitrino/src/translator/ByteCodeParser.h b/vm/jitrino/src/translator/ByteCodeParser.h index d6c7690..3e57727 100644 --- a/vm/jitrino/src/translator/ByteCodeParser.h +++ b/vm/jitrino/src/translator/ByteCodeParser.h @@ -40,6 +40,9 @@ public: virtual void parseInit() = 0; // called after the parsing ends, but not if an error occurs virtual void parseDone() = 0; + // if a callback during its construction determines some error + // the parsing can be ommitted with help of this: + virtual bool skipParsing() {return false;}; // called when an error occurs during the byte code parsing virtual void parseError() = 0; uint32 getNextOffset() {return nextOffset;} @@ -60,12 +63,14 @@ public: // void parse(ByteCodeParserCallback* cb) { cb->parseInit(); - byteCodeOffset = 0; - while (byteCodeOffset < byteCodeLength) { - if (cb->parseByteCode(byteCodes,byteCodeOffset) != true) { - return; + if (!cb->skipParsing()) { + byteCodeOffset = 0; + while (byteCodeOffset < byteCodeLength) { + if (cb->parseByteCode(byteCodes,byteCodeOffset) != true) { + return; + } + byteCodeOffset = cb->getNextOffset(); } - byteCodeOffset = cb->getNextOffset(); } cb->parseDone(); } diff --git a/vm/jitrino/src/translator/java/JavaByteCodeParser.h b/vm/jitrino/src/translator/java/JavaByteCodeParser.h index 7b7040f..97ac530 100644 --- a/vm/jitrino/src/translator/java/JavaByteCodeParser.h +++ b/vm/jitrino/src/translator/java/JavaByteCodeParser.h @@ -55,6 +55,7 @@ public: bytecodevisited = NULL; prepassVisited = NULL; labelStack = NULL; + noNeedToParse = false; } JavaByteCodeParserCallback(MemoryManager& memManager,uint32 byteCodeLength) { currentOffset = 0; @@ -65,6 +66,7 @@ public: bytecodevisited = new (memManager) BitSet(memManager,byteCodeLength); prepassVisited = NULL; labelStack = new (memManager) Queue(memManager); + noNeedToParse = false; } bool parseByteCode(const uint8* byteCodes,uint32 byteCodeOffset); BitSet* getVisited() { return visited; } @@ -77,6 +79,10 @@ protected: BitSet* bytecodevisited; BitSet* prepassVisited; Queue* labelStack; + + // for example when some exception type can not be resolved + bool noNeedToParse; + // called before each byte code to indicate the next byte code's offset virtual void offset(uint32 offset) = 0; virtual void offset_done(uint32 offset) = 0; @@ -227,6 +233,9 @@ protected: virtual void multianewarray(uint32 constPoolIndex,uint8 dimensions) = 0; virtual void ifnull(uint32 targetOffset,uint32 nextOffset) = 0; virtual void ifnonnull(uint32 targetOffset,uint32 nextOffset) = 0; + + virtual bool skipParsing() {return noNeedToParse;} + }; diff --git a/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp b/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp index 6b00a85..f412d29 100644 --- a/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp +++ b/vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp @@ -200,6 +200,13 @@ JavaByteCodeTranslator::JavaByteCodeTran genMethodMonitorEnter(); } } + + if(!prepass.allExceptionTypesResolved()) { + unsigned problemToken = prepass.getProblemTypeToken(); + assert(problemToken != MAX_UINT32); + linkingException(problemToken,OPCODE_CHECKCAST); // CHECKCAST is suitable here + noNeedToParse = true; + } } @@ -264,6 +271,15 @@ JavaByteCodeTranslator::JavaByteCodeTran } // create a prolog instruction irBuilder.genMethodEntryMarker(&methodDesc); + + if(!prepass.allExceptionTypesResolved()) { + unsigned problemToken = prepass.getProblemTypeToken(); + assert(problemToken != MAX_UINT32); + linkingException(problemToken,OPCODE_CHECKCAST); // CHECKCAST is suitable here + noNeedToParse = true; + return; + } + initLocalVars(); initArgs(); assert(numActualArgs == numArgs); @@ -352,7 +368,10 @@ JavaByteCodeTranslator::initArgs() { argTypes = new (memManager) Type*[numArgs]; args = new (memManager) Opnd*[numArgs]; for (uint16 i=0; igetParamType(i); + Type* argType = methodSignatureDesc->getParamType(i); + // argType == NULL if it fails to be resolved. Respective exception + // will be thrown at the point of usage + argTypes[i] = argType != NULL ? argType : typeManager.getNullObjectType(); } } diff --git a/vm/jitrino/src/translator/java/JavaLabelPrepass.cpp b/vm/jitrino/src/translator/java/JavaLabelPrepass.cpp index b0f79be..34dd3e1 100644 --- a/vm/jitrino/src/translator/java/JavaLabelPrepass.cpp +++ b/vm/jitrino/src/translator/java/JavaLabelPrepass.cpp @@ -294,13 +294,7 @@ public: void addHandlerForCatchBlock(CatchBlock* block, uint32 handlerOffset, uint32 handlerLength, - uint32 exceptionTypeToken) { - Type* exceptionType = NULL; - if (exceptionTypeToken != 0) { - exceptionType = compilationInterface.resolveNamedType(enclosingMethod,exceptionTypeToken); - } else { - exceptionType = prepass.typeManager.getSystemObjectType(); - } + Type* exceptionType) { jitrino_assert(compilationInterface, exceptionType); Log::out() << "Catch Exception Type = " << exceptionType->getName() << ::std::endl; @@ -347,7 +341,7 @@ public: return newBlock; } - virtual void catchBlock(uint32 tryOffset, + virtual bool catchBlock(uint32 tryOffset, uint32 tryLength, uint32 handlerOffset, uint32 handlerLength, @@ -366,9 +360,20 @@ public: bool unnested_try_regions_found = false; CatchBlock* catchBlock; + + Type* exceptionType = NULL; + if (exceptionTypeToken != 0) { + exceptionType = compilationInterface.resolveNamedType(enclosingMethod,exceptionTypeToken); + if(!exceptionType) { // the type can not be resolved. LinkingException must be thrown + return 0; + } + } else { + exceptionType = prepass.typeManager.getSystemObjectType(); + } + if (prevCatch != NULL && prevCatch->equals(tryOffset, endOffset) == true) { catchBlock = prevCatch; - addHandlerForCatchBlock(catchBlock, handlerOffset, handlerLength, exceptionTypeToken); + addHandlerForCatchBlock(catchBlock, handlerOffset, handlerLength, exceptionType); } else { prepass.stateTable->createStateInfo(tryOffset); // @@ -409,8 +414,9 @@ public: new (memManager) CatchBlock(nextRegionId++, tryOffset, endOffset, numCatch++); prepass.stateTable->getStateInfo(tryOffset)->addExceptionInfo(catchBlock); prepass.exceptionTable.push_back(catchBlock); - addHandlerForCatchBlock(catchBlock, handlerOffset, handlerLength, exceptionTypeToken); + addHandlerForCatchBlock(catchBlock, handlerOffset, handlerLength, exceptionType); } + return 1; // all exceptionTypes are OK } virtual void finallyBlock(uint32 tryOffset, uint32 tryLength, @@ -450,7 +456,8 @@ JavaLabelPrepass::JavaLabelPrepass(Memor localVars(mm), jsrEntriesMap(mm), retToSubEntryMap(mm), - exceptionTable(mm) + exceptionTable(mm), + problemTypeToken(MAX_UINT32) { uint32 numByteCodes = methodDesc.getByteCodeSize(); //nextIsLabel = false; @@ -482,8 +489,15 @@ JavaLabelPrepass::JavaLabelPrepass(Memor // parse and create exception info JavaExceptionParser exceptionTypes(irManager,*this,compilationInterface,&methodDesc); // fix exception handlers - methodDesc.parseJavaHandlers(exceptionTypes); - numCatchHandlers = exceptionTypes.numCatch; + unsigned problemToken = methodDesc.parseJavaHandlers(exceptionTypes); + if(problemToken != MAX_UINT32) + { + problemTypeToken = problemToken; + noNeedToParse = true; + numCatchHandlers = 0; + } else { + numCatchHandlers = exceptionTypes.numCatch; + } hasJsrLabels = false; isFallThruLabel = true; @@ -510,7 +524,12 @@ JavaLabelPrepass::JavaLabelPrepass(Memor if (Simplifier::isExactType(actual)) StateInfo::setExactType(slot); } else { type = methodSig->getParamType(i); - slot->type = typeManager.toInternalType(methodSig->getParamType(i)); + if (!type) { + // linkage error will happen at the usage point of this parameter + // here we just keep it as NullObj + type = typeManager.getNullObjectType(); + } + slot->type = typeManager.toInternalType(type); } slot->vars = new (memManager) SlotVar(getOrCreateVarInc(0, j, slot->type, NULL)); JavaVarType javaType = getJavaType(type); diff --git a/vm/jitrino/src/translator/java/JavaLabelPrepass.h b/vm/jitrino/src/translator/java/JavaLabelPrepass.h index c1b4541..e34d09d 100644 --- a/vm/jitrino/src/translator/java/JavaLabelPrepass.h +++ b/vm/jitrino/src/translator/java/JavaLabelPrepass.h @@ -258,6 +258,10 @@ public: void pushType(Type *type); bool isCategory2(struct StateInfo::SlotInfo slot) { return slot.type == int64Type || slot.type == doubleType; } + // + bool allExceptionTypesResolved() {return problemTypeToken == MAX_UINT32;} + unsigned getProblemTypeToken() {return problemTypeToken;} + // cut and paste from Java_Translator.cpp // field, method, and type resolution // @@ -527,6 +531,9 @@ private: Type *int32Type, *int64Type, *singleType, *doubleType; ExceptionTable exceptionTable; + // if an exception type can not be resolved, its token is being kept here + unsigned problemTypeToken; + // private helper methods void setLabel(uint32 offset); void setSubroutineEntry(uint32 offset) { subroutines->setBit(offset,true); } diff --git a/vm/jitrino/src/vm/VMInterface.h b/vm/jitrino/src/vm/VMInterface.h index 6b8750b..1058bb2 100644 --- a/vm/jitrino/src/vm/VMInterface.h +++ b/vm/jitrino/src/vm/VMInterface.h @@ -60,7 +60,7 @@ class ExceptionCallback { public: virtual ~ExceptionCallback() {} - virtual void catchBlock(uint32 tryOffset, + virtual bool catchBlock(uint32 tryOffset, uint32 tryLength, uint32 handlerOffset, uint32 handlerLength, @@ -159,7 +159,7 @@ public: virtual uint32 getNumHandlers() = 0; // Exception handler and signature parsing API - virtual void parseJavaHandlers(ExceptionCallback&) = 0; + virtual unsigned parseJavaHandlers(ExceptionCallback&) = 0; virtual void parseCliHandlers(ExceptionCallback&) = 0; virtual bool isVarPinned(uint32 varIndex) = 0; virtual Type* getVarType(uint32 varType) = 0; diff --git a/vm/jitrino/src/vm/drl/DrlVMInterface.cpp b/vm/jitrino/src/vm/drl/DrlVMInterface.cpp index 15c7f85..0f9c245 100644 --- a/vm/jitrino/src/vm/drl/DrlVMInterface.cpp +++ b/vm/jitrino/src/vm/drl/DrlVMInterface.cpp @@ -346,16 +346,22 @@ DrlVMMethodDesc::getParentType() { return typeManager.getObjectType(parentClassHandle); } -void +unsigned DrlVMMethodDesc::parseJavaHandlers(ExceptionCallback& callback) { uint32 numHandlers = getNumHandlers(); for (uint32 i=0; i