private InlineResult tryInlineMethodCall(JMethodCall x, Context ctx) { JMethod method = x.getTarget(); if (!method.isStatic() || method.isNative() || method.canBeImplementedExternally()) { // Only inline static methods that are not native. return InlineResult.BLACKLIST; } if (!method.isInliningAllowed()) { return InlineResult.BLACKLIST; } JMethodBody body = (JMethodBody) method.getBody(); List<JStatement> stmts = body.getStatements(); if (method.getEnclosingType() != null && method.getEnclosingType().getClinitMethod() == method && !stmts.isEmpty()) { // clinit() calls cannot be inlined unless they are empty return InlineResult.BLACKLIST; } // try to inline List<JExpression> expressions = extractExpressionsFromBody(body); if (expressions == null) { // If it will never be possible to inline the method, add it to a // blacklist return InlineResult.BLACKLIST; } return tryInlineBody(x, ctx, expressions, expressionsWhoseValuesAreIgnored.contains(x)); }
@Override public void endVisit(JMethodCall x, Context ctx) { JMethod method = x.getTarget(); if (currentMethod == method) { // Never try to inline a recursive call! return; } if (cannotInline.contains(method)) { return; } boolean possibleToInline = false; if (method.isStatic() && !method.isNative()) { JMethodBody body = (JMethodBody) method.getBody(); List<JStatement> stmts = body.getStatements(); if (method.getEnclosingType() != null && method.getEnclosingType().getClinitMethod() == method && !stmts.isEmpty()) { // clinit() calls cannot be inlined unless they are empty possibleToInline = false; } else if (!body.getLocals().isEmpty()) { // methods with local variables cannot be inlined possibleToInline = false; } else { JMultiExpression multi = createMultiExpressionFromBody(body, ignoringReturnValueFor == x); if (multi != null) { possibleToInline = tryInlineExpression(x, ctx, multi); } } } // If it will never be possible to inline the method, add it to a // blacklist if (!possibleToInline) { cannotInline.add(method); } }
private JMethodCall createClinitCall(JMethodCall x) { JDeclaredType targetType = x.getTarget().getEnclosingType().getClinitTarget(); if (!getCurrentMethod().getEnclosingType().checkClinitTo(targetType)) { // Access from this class to the target class won't trigger a clinit return null; } if (program.isStaticImpl(x.getTarget()) && !x.getTarget().getEnclosingType().isJsoType()) { // No clinit needed; target is really a non-jso instance method. return null; } if (JProgram.isClinit(x.getTarget())) { // This is a clinit call, doesn't need another clinit return null; } JMethod clinit = targetType.getClinitMethod(); // If the clinit is a non-native, empty body we can optimize it out here if (!clinit.isNative() && (((JMethodBody) clinit.getBody())).getStatements().size() == 0) { return null; } return new JMethodCall(x.getSourceInfo(), null, clinit); }