/** * Transform a call to a pruned instance method (or static impl) into a call to the null method, * which will be used to replace <code>x</code>. */ public static JMethodCall transformToNullMethodCall(JMethodCall x, JProgram program) { JExpression instance = x.getInstance(); List<JExpression> args = x.getArgs(); if (program.isStaticImpl(x.getTarget())) { instance = args.get(0); args = args.subList(1, args.size()); } else { /* * We assert that method must be non-static, otherwise it would have been * rescued. */ // assert !x.getTarget().isStatic(); /* * HACK HACK HACK: ControlFlowAnalyzer has special hacks for dealing with * ClassLiterals, which causes the body of ClassLiteralHolder's clinit to * never be rescured. This in turn causes invalid references to static * methods, which violates otherwise good assumptions about compiler * operation. * * TODO: Remove this when ControlFlowAnalyzer doesn't special-case * CLH.clinit(). */ if (x.getTarget().isStatic() && instance == null) { instance = program.getLiteralNull(); } } assert (instance != null); if (!instance.hasSideEffects()) { instance = program.getLiteralNull(); } JMethodCall newCall = new JMethodCall( x.getSourceInfo(), instance, program.getNullMethod(), primitiveTypeOrNullTypeOrArray(program, x.getType())); // Retain the original arguments, they will be evaluated for side effects. for (JExpression arg : args) { if (arg.hasSideEffects()) { newCall.addArg(arg); } } return newCall; }
/** * Transform a reference to a pruned instance field into a reference to the null field, which will * be used to replace <code>x</code>. */ public static JFieldRef transformToNullFieldRef(JFieldRef x, JProgram program) { JExpression instance = x.getInstance(); /* * We assert that field must be non-static if it's an rvalue, otherwise it * would have been rescued. */ // assert !x.getField().isStatic(); /* * HACK HACK HACK: ControlFlowAnalyzer has special hacks for dealing with * ClassLiterals, which causes the body of ClassLiteralHolder's clinit to * never be rescured. This in turn causes invalid references to static * methods, which violates otherwise good assumptions about compiler * operation. * * TODO: Remove this when ControlFlowAnalyzer doesn't special-case * CLH.clinit(). */ if (x.getField().isStatic() && instance == null) { instance = program.getLiteralNull(); } assert instance != null; if (!instance.hasSideEffects()) { instance = program.getLiteralNull(); } JFieldRef fieldRef = new JFieldRef( x.getSourceInfo(), instance, program.getNullField(), x.getEnclosingType(), primitiveTypeOrNullTypeOrArray(program, x.getType())); return fieldRef; }
/** Returns an ast node representing the expression {@code expression != null}. */ public static JExpression createOptimizedNotNullComparison( JProgram program, SourceInfo info, JExpression expression) { JReferenceType type = (JReferenceType) expression.getType(); if (type.isNullType()) { return program.getLiteralBoolean(false); } if (!type.canBeNull()) { return createOptimizedMultiExpression(expression, program.getLiteralBoolean(true)); } return new JBinaryOperation( info, program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, expression, program.getLiteralNull()); }