@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; }
@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); } } } } }
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; }
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; }
/** * 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); } } }