docs: 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();
          }
  
      }