private static List<String> makeSetPropertyArgs(ListMultimap<String, String> properties) { List<String> propertyArgs = Lists.newArrayList(); for (String propertyName : properties.keySet()) { propertyArgs.add("-setProperty"); StringBuilder nameValues = new StringBuilder(propertyName + "="); for (String propertyValue : properties.get(propertyName)) { nameValues.append(propertyValue + ","); } propertyArgs.add(nameValues.substring(0, nameValues.length() - 1)); } return propertyArgs; }
@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; }
// Arguments for pruned parameters will be pushed right into a multiexpression that will be // evaluated with the next arg, e.g. m(arg1, (prunnedArg2, prunnedArg3, arg4)). private void maybeReplaceForPrunedParameters(JMethodCall x, Context ctx) { if (!priorParametersByMethod.containsKey(x.getTarget())) { // No parameter was pruned. return; } JMethodCall replacementCall = x.cloneWithoutParameters(); assert !x.getTarget().canBePolymorphic(); List<JParameter> originalParams = priorParametersByMethod.get(x.getTarget()); // The method and the call agree in the number of parameters. assert originalParams.size() == x.getArgs().size(); // Traverse the call arguments left to right. SourceInfo sourceInfo = x.getSourceInfo(); JMultiExpression unevaluatedArgumentsForPrunedParameters = new JMultiExpression(sourceInfo); List<JExpression> args = x.getArgs(); for (int currentArgumentIndex = 0; currentArgumentIndex < args.size(); ++currentArgumentIndex) { JExpression arg = args.get(currentArgumentIndex); // If the parameter was not pruned . if (referencedNonTypes.contains(originalParams.get(currentArgumentIndex))) { // Add the current argument to the list of unevaluated arguments and pass the multi // expression to the call. unevaluatedArgumentsForPrunedParameters.addExpressions(arg); replacementCall.addArg(unevaluatedArgumentsForPrunedParameters); // Reset the accumulating multi expression. unevaluatedArgumentsForPrunedParameters = new JMultiExpression(sourceInfo); } else if (arg.hasSideEffects()) { // If the argument was pruned and has sideffects accumulate it; otherwise discard. unevaluatedArgumentsForPrunedParameters.addExpressions(arg); } } if (unevaluatedArgumentsForPrunedParameters.isEmpty()) { // We are done, all (side effectful) parameters have been evaluated. ctx.replaceMe(replacementCall); return; } // If the last few parameters where pruned, we need to evaluate the (side effectful) arguments // for those parameters. if (replacementCall.getArgs().isEmpty()) { // All parameters have been pruned, replace by (prunedArg1, ..., prunedArgn, m()). unevaluatedArgumentsForPrunedParameters.addExpressions(replacementCall); ctx.replaceMe(unevaluatedArgumentsForPrunedParameters); return; } // Some parameters have been pruned from the end, replace by // m(arg1,..., (lastArg = lastUnprunedArg, remainingArgs, lastArg)) JExpression lastArg = Iterables.getLast(replacementCall.getArgs()); JLocal tempVar = createTempLocal( sourceInfo, Iterables.getLast(Iterables.filter(originalParams, Predicates.in(referencedNonTypes))) .getType()); unevaluatedArgumentsForPrunedParameters.addExpressions( 0, JProgram.createAssignment( lastArg.getSourceInfo(), new JLocalRef(sourceInfo, tempVar), lastArg)); unevaluatedArgumentsForPrunedParameters.addExpressions(new JLocalRef(sourceInfo, tempVar)); replacementCall.setArg( replacementCall.getArgs().size() - 1, unevaluatedArgumentsForPrunedParameters); ctx.replaceMe(replacementCall); }