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)); }
private Result assertThat(String expr, String type, String decls) throws UnableToCompleteException { ConstantsAssumption.Updater updater = new ConstantsAssumption.Updater(new ConstantsAssumption()); String codeSnippet = decls; codeSnippet += "return " + expr + ";"; JProgram program = compileSnippet(type, codeSnippet); JMethod mainMethod = findMainMethod(program); JBlock block = ((JMethodBody) mainMethod.getBody()).getBlock(); List<JStatement> statements = block.getStatements(); // TODO: not a pretty assumption detection. for (JStatement stmt : statements) { if (!(stmt instanceof JDeclarationStatement)) { continue; } JDeclarationStatement decl = (JDeclarationStatement) stmt; if (decl.getInitializer() != null) { updater.set(decl.getVariableRef().getTarget(), (JValueLiteral) decl.getInitializer()); } } JReturnStatement returnStatement = (JReturnStatement) statements.get(statements.size() - 1); return new Result(ExpressionEvaluator.evaluate(returnStatement.getExpr(), updater.unwrap())); }
/** * 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(); 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); }
public LocalVariableExtruder(JMethod method) { methodBody = (JMethodBody) method.getBody(); }
public static void replaceMethodBody(JMethod method, JExpression returnValue) { JMethodBody body = (JMethodBody) method.getBody(); JBlock block = body.getBlock(); block.clear(); block.addStmt(returnValue.makeReturnStatement()); }