private void handleInvoke ( InvokeInstruction obj ) { if ( obj instanceof INVOKEDYNAMIC ) { // should not happen return ; } Type returnType = obj . getReturnType ( getCPG ( ) ) ; Location location = getLocation ( ) ; if ( trackValueNumbers ) { try { ValueNumberFrame vnaFrame = vnaDataflow . getFactAtLocation ( location ) ; Set < ValueNumber > nonnullParameters = UnconditionalValueDerefAnalysis . checkAllNonNullParams ( location , vnaFrame , cpg , null , null , typeDataflow ) ; if ( ! nonnullParameters . isEmpty ( ) ) { IsNullValue kaboom = IsNullValue . noKaboomNonNullValue ( location ) ; IsNullValueFrame frame = getFrame ( ) ; for ( ValueNumber vn : nonnullParameters ) { IsNullValue knownValue = frame . getKnownValue ( vn ) ; if ( knownValue != null && ! knownValue . isDefinitelyNotNull ( ) ) { if ( knownValue . isDefinitelyNull ( ) ) { frame . setTop ( ) ; return ; } frame . setKnownValue ( vn , kaboom ) ; } for ( int i = 0 ; i < vnaFrame . getNumSlots ( ) ; i ++ ) { IsNullValue value = frame . getValue ( i ) ; if ( vnaFrame . getValue ( i ) . equals ( vn ) && ! value . isDefinitelyNotNull ( ) ) { frame . setValue ( i , kaboom ) ; if ( value . isDefinitelyNull ( ) ) { frame . setTop ( ) ; return ; } } } } } } catch ( DataflowAnalysisException e ) { AnalysisContext . logError ( "Error looking up nonnull parameters for invoked method" , e ) ; } } // Determine if we are going to model the return value of this call. boolean modelCallReturnValue = MODEL_NONNULL_RETURN && returnType instanceof ReferenceType ; if ( ! modelCallReturnValue ) { // Normal case: Assume returned values are non-reporting non-null. handleNormalInstruction ( obj ) ; } else { // Special case: some special value is pushed on the stack for the // return value IsNullValue result = null ; TypeFrame typeFrame ; try { typeFrame = typeDataflow . getFactAtLocation ( location ) ; Set < XMethod > targetSet = Hierarchy2 . resolveMethodCallTargets ( obj , typeFrame , cpg ) ; if ( targetSet . isEmpty ( ) ) { XMethod calledMethod = XFactory . createXMethod ( obj , getCPG ( ) ) ; result = getReturnValueNullness ( calledMethod ) ; } else { for ( XMethod calledMethod : targetSet ) { IsNullValue pushValue = getReturnValueNullness ( calledMethod ) ; if ( result == null ) { result = pushValue ; } else { result = IsNullValue . merge ( result , pushValue ) ; } } } } catch ( DataflowAnalysisException e ) { result = IsNullValue . nonReportingNotNullValue ( ) ; } catch ( ClassNotFoundException e ) { result = IsNullValue . nonReportingNotNullValue ( ) ; } modelInstruction ( obj , getNumWordsConsumed ( obj ) , getNumWordsProduced ( obj ) , result ) ; newValueOnTOS ( ) ; } }
Handle method invocations . Generally we want to get rid of null information following a call to a likely exception thrower or assertion .