Package joust.tree.annotatedtree

Source Code of joust.tree.annotatedtree.AJCForest

package joust.tree.annotatedtree;

import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Pair;
import joust.analysers.sideeffects.Effects;
import joust.joustcache.JOUSTCache;
import joust.optimisers.normalise.TreeNormalisingTranslator;
import joust.analysers.sideeffects.SideEffectVisitor;
import joust.optimisers.shortfunc.ShortFuncFunctionTemplates;
import joust.optimisers.unbox.UnboxingFunctionTemplates;
import joust.optimisers.unbox.UnboxingTranslator;
import joust.tree.conversion.TreePreparationTranslator;
import joust.tree.annotatedtree.treeinfo.TreeInfoManager;
import joust.utils.logging.LogUtils;
import joust.utils.logging.StatisticsManager;
import joust.utils.tree.CallDetector;
import joust.utils.tree.JCTreeStructurePrinter;
import joust.utils.tree.TreeUtils;
import lombok.Delegate;
import lombok.experimental.ExtensionMethod;
import lombok.extern.java.Log;

import java.util.HashMap;
import java.util.Queue;
import java.util.logging.Logger;

import static com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Symbol.*;
import static joust.tree.annotatedtree.AJCTree.*;

/**
* A forest of annotated Java ASTs. Typically, the input to the optimiser will be converted into a single such
* forest.
* Serves as a handy place for structures shared among all input trees to reside.
*/
@Log
@ExtensionMethod({Logger.class, LogUtils.LogExtensions.class})
public class AJCForest {
    private boolean analysisPerformed;

    private static AJCForest instance;

    public static Env<AttrContext> currentEnvironment;
    // TODO: Something something context.
    public static AJCForest getInstance() {
        return instance;
    }

    // The input root nodes, after conversion.
    public final List<AJCTree> rootNodes;

    public final HashMap<AJCTree, Env<AttrContext>> rootEnvironments;

    // Maps method symbols to their corresponding declaration nodes.
    public final HashMap<MethodSymbol, AJCMethodDecl> methodTable;

    public SideEffectVisitor effectVisitor = new SideEffectVisitor(analysisPerformed);

    @Delegate
    public StatisticsManager statisticsManager = new StatisticsManager();

    /**
     * Init the forest from the given set of root elements.
     * Iterate the root elements converting them to our tree representation, populating the various tables
     * as you go.
     */
    public static void init(Iterable<Pair<Env<AttrContext>, JCClassDecl>> rootElements) {
        if (instance != null) {
            throw new UnsupportedOperationException("Attempt to reassign AJCForest!");
        }

        log.info("Starting forest construction.");
        currentEnvironment = null;

        long t = System.currentTimeMillis();

        List<AJCTree> prospectiveRootNodes = List.nil();
        HashMap<AJCTree, Env<AttrContext>> environMap = new HashMap<AJCTree, Env<AttrContext>>();

        // Since it's stateless...
        final TreePreparationTranslator sanity = new TreePreparationTranslator();
        final TreeNormalisingTranslator normaliser = new TreeNormalisingTranslator();

        HashMap<MethodSymbol, AJCMethodDecl> prospectiveMethodTable = new HashMap<MethodSymbol, AJCMethodDecl>();

        InitialASTConverter.init();
        for (Pair<Env<AttrContext>, JCClassDecl> env : rootElements) {
            currentEnvironment = env.fst;
            JCClassDecl classTree = env.snd;
            log.trace("Input tree: {}", classTree);
            // Perform the sanity translations on the tree that are more convenient to do before the translation step...
            classTree.accept(sanity);
            log.trace("Prepared tree: {}", classTree);

            // Translate the tree to our tree representation...
            InitialASTConverter converter = new InitialASTConverter();
            classTree.accept(converter);

            AJCClassDecl translatedTree = (AJCClassDecl) converter.getResult();
            log.debug("Translated tree: {}", translatedTree);

            // Populate method and varsym tables.
            for (AJCMethodDecl defN : translatedTree.methods) {
                prospectiveMethodTable.put(defN.getTargetSymbol(), defN);
                log.debug("Method: {}", defN.getTargetSymbol());
            }

            // Normalise the tree.
            normaliser.visitTree(translatedTree);

            prospectiveRootNodes = prospectiveRootNodes.prepend(translatedTree);

            environMap.put(translatedTree, env.fst);
        }

        log.info("Tree converted and normalised in {}ms", System.currentTimeMillis() - t);

        // Deallocate the annoying lookup table.
        InitialASTConverter.uninit();
        initDirect(prospectiveRootNodes, prospectiveMethodTable, environMap);
    }

    public static void initDirect(List<AJCTree> trees, HashMap<MethodSymbol, AJCMethodDecl> mTable, HashMap<AJCTree, Env<AttrContext>> environMap) {
        if (instance != null) {
            throw new UnsupportedOperationException("Attempt to reassign AJCForest!");
        }

        // Effect handler utils...
        TreeInfoManager.init();
        JOUSTCache.init();
        TreeUtils.init();

        AJCForest ret = new AJCForest(trees, mTable, environMap);

        instance = ret;

        ret.initialAnalysis();
    }

    /**
     * *sigh*
     */
    public static void uninit() {
        log.warning("Uniniting AJCTree.");
        instance = null;
    }

    /**
     * Perform initial analysis on the converted tree that has to occur prior to other optimisation steps taking place.
     */
    public void initialAnalysis() {
        long t = System.currentTimeMillis();
        log.info("Initial side effect analysis started on {} nodes", rootNodes.size());

        effectVisitor = new SideEffectVisitor(!analysisPerformed);
        Effects.numCalls = 0;

        VisitorResultPurger purger = new VisitorResultPurger();

        log.info("Purging...");
        // Run the initial effect analysis on the tree (It's kept incrementally updated)...
        for (AJCTree tree : rootNodes) {
            purger.visitTree(tree);
        }

        log.info("Effect...");
        for (AJCTree tree : rootNodes) {
            effectVisitor.visitTree(tree);
        }

        // So now we've populated the direct effects of each method. Let's resolve all the loose ends...
        effectVisitor.bootstrap();

        analysisPerformed = true;
        log.info("numCalls: {}", Effects.numCalls);

        log.info("Initial side effect analysis completed in {}ms.", System.currentTimeMillis() - t);
    }

    // Prevent direct instantiation.
    private AJCForest(List<AJCTree> trees, HashMap<MethodSymbol, AJCMethodDecl> mTable, HashMap<AJCTree, Env<AttrContext>> environMap) {
        rootNodes = trees;
        methodTable = mTable;
        rootEnvironments = environMap;
        log.debug("trees: {}", trees);

        setEnvironment(trees.head);
    }

    public void setEnvironment(AJCTree tree) {
        currentEnvironment = rootEnvironments.get(tree);
        if (currentEnvironment == null) {
            log.fatal("Environment has been nulled for tree {}", tree);
        }
    }

    public boolean repeatAnalysis(AJCTree tree) {
        log.info("Repeat analysis for: {}", tree);
        CallDetector detector = new CallDetector();
        detector.visitTree(tree);

        if (detector.containsCall) {
            log.info("Shortcut aborted :(");
            initialAnalysis();
            return false;
        }

        log.info("Shortcut possible!");

        VisitorResultPurger purger = new VisitorResultPurger();

        log.info("Purging...");
        // Run the initial effect analysis on the tree (It's kept incrementally updated)...
        purger.visitTree(tree);

        log.info("Effect...");
        effectVisitor.visitTree(tree);

        return true;
    }
}
TOP

Related Classes of joust.tree.annotatedtree.AJCForest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.