Beispiel #1
0
    @Override
    public boolean enter(JMethod x, Context ctx) {
      if (!x.canBePolymorphic()) {
        /*
         * Don't prune parameters on unreferenced methods. The methods might not
         * be reachable through the current method traversal routines, but might
         * be used or checked elsewhere.
         *
         * Basically, if we never actually checked if the method parameters were
         * used or not, don't prune them. Doing so would leave a number of
         * dangling JParameterRefs that blow up in later optimizations.
         */
        if (!referencedNonTypes.contains(x)) {
          return true;
        }

        /*
         * We cannot prune parameters from staticImpls that still have a live
         * instance method, because doing so would screw up any subsequent
         * devirtualizations. If the instance method has been pruned, then it's
         * okay. Also, it's okay on the final pass (saveCodeTypes == false)
         * since no more devirtualizations will occur.
         *
         * TODO: prune params; MakeCallsStatic smarter to account for it.
         */
        JMethod instanceMethod = program.instanceMethodForStaticImpl(x);
        // Unless the instance method has already been pruned, of course.
        if (saveCodeGenTypes
            && instanceMethod != null
            && referencedNonTypes.contains(instanceMethod)) {
          // instance method is still live
          return true;
        }

        priorParametersByMethod.putAll(x, x.getParams());

        for (int i = 0; i < x.getParams().size(); ++i) {
          JParameter param = x.getParams().get(i);
          if (!referencedNonTypes.contains(param)) {
            x.removeParam(i);
            madeChanges();
            --i;
          }
        }
      }

      return true;
    }
Beispiel #2
0
    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod target = x.getTarget();
      JDeclaredType type = target.getEnclosingType();

      if (type instanceof JClassType) {
        JClassType cType = (JClassType) type;

        if (target == enumNameMethod
            || target == enumToStringMethod
            || target == enumValueOfMethod) {
          warn(x);
        } else if (cType.isEnumOrSubclass() != null) {
          if ("valueOf".equals(target.getName())) {
            /*
             * Check for calls to the auto-generated
             * EnumSubType.valueOf(String). Note, the check of the signature for
             * the single String arg version is to avoid flagging user-defined
             * overloaded versions of the method, which are presumably ok.
             */
            List<JParameter> jParameters = target.getParams();
            if (jParameters.size() == 1 && jParameters.get(0).getType() == stringType) {
              warn(x);
            }
          }
        }
      }
    }
Beispiel #3
0
    public EnumNameCallChecker(JProgram jprogram, TreeLogger logger) {
      this.logger = logger;
      this.enumNameMethod = jprogram.getIndexedMethod("Enum.name");
      this.enumToStringMethod = jprogram.getIndexedMethod("Enum.toString");
      this.classType = jprogram.getIndexedType("Class");
      this.enumType = jprogram.getIndexedType("Enum");
      this.stringType = jprogram.getIndexedType("String");

      /*
       * Find the correct version of enumValueOfMethod.
       *
       * Note: it doesn't work to check against a ref returned by
       * jprogram.getIndexedMethod("Enum.valueOf"), since there are 2 different
       * versions of Enum.valueOf in our jre emulation library, and the indexed
       * ref won't reliably flag the public instance, which is the one we want
       * here (i.e. Enum.valueOf(Class<T>,String)). The other version is
       * protected, but is called by the generated constructors for sub-classes
       * of Enum, and we don't want to warn for those cases.
       */
      JMethod foundMethod = null;
      List<JMethod> enumMethods = enumType.getMethods();
      for (JMethod enumMethod : enumMethods) {
        if ("valueOf".equals(enumMethod.getName())) {
          List<JParameter> jParameters = enumMethod.getParams();
          if (jParameters.size() == 2
              && jParameters.get(0).getType() == classType
              && jParameters.get(1).getType() == stringType) {
            foundMethod = enumMethod;
            break;
          }
        }
      }
      this.enumValueOfMethod = foundMethod;
    }
Beispiel #4
0
 private static JMethod createEmptyMethodFromExample(
     JDeclaredType inType, JMethod exampleMethod, boolean isAbstract) {
   JMethod emptyMethod =
       new JMethod(
           exampleMethod.getSourceInfo(),
           exampleMethod.getName(),
           inType,
           exampleMethod.getType(),
           isAbstract,
           false,
           false,
           exampleMethod.getAccess());
   emptyMethod.addThrownExceptions(exampleMethod.getThrownExceptions());
   emptyMethod.setSynthetic();
   // Copy parameters.
   for (JParameter param : exampleMethod.getParams()) {
     emptyMethod.addParam(
         new JParameter(
             param.getSourceInfo(),
             param.getName(),
             param.getType(),
             param.isFinal(),
             param.isThis(),
             emptyMethod));
   }
   JMethodBody body = new JMethodBody(exampleMethod.getSourceInfo());
   emptyMethod.setBody(body);
   emptyMethod.freezeParamTypes();
   inType.addMethod(emptyMethod);
   return emptyMethod;
 }
Beispiel #5
0
  /**
   * Creates a synthetic forwarding stub in {@code type} with the same signature as {@code
   * superTypeMethod} that dispatchs to that method..
   */
  public static JMethod createForwardingMethod(JDeclaredType type, JMethod methodToDelegateTo) {
    JMethod forwardingMethod = createEmptyMethodFromExample(type, methodToDelegateTo, false);
    forwardingMethod.setForwarding();

    // This is a synthetic forwading method due to a default.
    if (methodToDelegateTo.isDefaultMethod()) {
      forwardingMethod.setDefaultMethod();
    }

    // Create the forwarding body.
    JMethodBody body = (JMethodBody) forwardingMethod.getBody();
    // Invoke methodToDelegate
    JMethodCall forwardingCall =
        new JMethodCall(
            methodToDelegateTo.getSourceInfo(),
            new JThisRef(methodToDelegateTo.getSourceInfo(), type),
            methodToDelegateTo);
    forwardingCall.setStaticDispatchOnly();
    // copy params
    for (JParameter p : forwardingMethod.getParams()) {
      forwardingCall.addArg(new JParameterRef(p.getSourceInfo(), p));
    }

    // return statement if not void return type
    body.getBlock().addStmt(makeMethodEndStatement(forwardingMethod.getType(), forwardingCall));
    return forwardingMethod;
  }
    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod method = x.getTarget();

      // A quick check to reduce extra work needed otherwise...
      if (isNotOptimizable(method)) {
        return;
      }

      List<JExpression> args = x.getArgs();
      List<JParameter> params = method.getParams();

      for (int i = 0; i < args.size() && i < params.size(); i++) {
        JParameter param = params.get(i);
        JExpression arg = args.get(i);

        if (!(arg instanceof JValueLiteral)) {
          parameterValues.put(param, null);
          continue;
        }

        if (!parameterValues.containsKey(param)) {
          parameterValues.put(param, (JValueLiteral) arg);
          continue;
        }

        JValueLiteral commonParamValue = parameterValues.get(param);
        if (commonParamValue == null) {
          continue;
        }

        if (!equalLiterals(commonParamValue, (JValueLiteral) arg)) {
          parameterValues.put(param, null);
        }
      }
    }