/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2010. */ package x10.optimizations.inlining; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.ProcedureDecl; import polyglot.frontend.Job; import polyglot.types.ClassDef; import polyglot.types.ClassType; import polyglot.types.ConstructorDef; import polyglot.types.Flags; import polyglot.types.MemberDef; import polyglot.types.SemanticException; import polyglot.types.TypeSystem; import polyglot.types.Types; import polyglot.util.Position; import polyglot.visit.ContextVisitor; import polyglot.visit.NodeVisitor; import x10.types.X10ClassDef; import x10.types.X10ProcedureDef; import x10.visit.ExpressionFlattener; /** * @author Bowen Alpern * TODO: cache the Decl's and there inline cost info * */ public class DeclPackager extends ContextVisitor { private DeclStore repository; private InlineUtils utils; /** * @param job * @param ts * @param nf */ public DeclPackager(Job job, TypeSystem ts, NodeFactory nf) { super(job, ts, nf); } /* (non-Javadoc) * @see polyglot.visit.ContextVisitor#begin() */ @Override public NodeVisitor begin() { repository = job.compiler().getInlinerData(job, ts, nf); utils = new InlineUtils(job); return super.begin(); } /* (non-Javadoc) * @see polyglot.visit.ErrorHandlingVisitor#enterCall(polyglot.ast.Node) */ @Override protected NodeVisitor enterCall(Node n) throws SemanticException { if (n instanceof ProcedureDecl) { ProcedureDecl decl = (ProcedureDecl) n; X10ProcedureDef pdef = (X10ProcedureDef) decl.procedureInstance(); X10ClassDef cdef = ((ClassType) Types.baseType(((MemberDef) pdef).container().get())).def(); DeclPackage pkg; if ( (Position.COMPILER_GENERATED == n.position()) || utils.inliningProhibited(decl) || utils.inliningProhibited(cdef) || utils.inliningProhibited(pdef) || ExpressionFlattener.cannotFlatten(n) || isNative(pdef, cdef) || null == decl.body() ) { pkg = new DeclPackage("Call is uninlinable"); // inlining prohibited repository.putDeclPackage(pdef, pkg); } else if (isVirtual(pdef, cdef)) { pkg = new DeclPackage("Only non-virtual call is inlinable", job, decl); repository.putDeclPackage(pdef, pkg); } else { pkg = new DeclPackage(job, decl); } return pkg; } return this; } /* (non-Javadoc) * @see polyglot.visit.ErrorHandlingVisitor#leaveCall(polyglot.ast.Node, polyglot.ast.Node, polyglot.visit.NodeVisitor) */ @Override protected Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException { if (n instanceof ProcedureDecl && v instanceof DeclPackage) { X10ProcedureDef def = (X10ProcedureDef) ((ProcedureDecl) n).procedureInstance(); repository.putDeclPackage(def, (DeclPackage) v); } return n; } /** * Check that a method is eligible to be inlined. * * @param def the method considered for inlining * @param container the class containing the def * @return true, if the method obviously should not be inlined; false, otherwise */ private boolean isNative(X10ProcedureDef def, ClassDef container) { Flags mf = ((MemberDef) def).flags(); Flags cf = container.flags(); if (mf.isNative() || cf.isNative()) return true; return false; } /** * Check that a method is eligible to be inlined for non-virtual call. * * @param def the method considered for inlining * @param container the class containing the def * @return true, if the method obviously should not be inlined; false, otherwise */ private boolean isVirtual(X10ProcedureDef def, ClassDef container) { Flags mf = ((MemberDef) def).flags(); Flags cf = container.flags(); if (mf.isStatic() || mf.isFinal() || mf.isPrivate() || (def instanceof ConstructorDef)) return false; if ( cf.isFinal() || container.isStruct()) return false; return true; } }