All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teavm.javascript.Optimizer Maven / Gradle / Ivy

There is a newer version: 0.10.2
Show newest version
/*
 *  Copyright 2012 Alexey Andreev.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.teavm.javascript;

import java.util.BitSet;
import java.util.List;
import org.teavm.common.Graph;
import org.teavm.javascript.ast.AsyncMethodNode;
import org.teavm.javascript.ast.AsyncMethodPart;
import org.teavm.javascript.ast.RegularMethodNode;
import org.teavm.model.Instruction;
import org.teavm.model.Program;
import org.teavm.model.Variable;
import org.teavm.model.util.AsyncProgramSplitter;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.LivenessAnalyzer;
import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.UsageExtractor;

/**
 *
 * @author Alexey Andreev
 */
public class Optimizer {
    public void optimize(RegularMethodNode method, Program program) {
        ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
        stats.analyze(program);
        boolean[] preservedVars = new boolean[stats.writes.length];
        for (int i = 0; i < preservedVars.length; ++i) {
            if (stats.writes[i] != 1) {
                preservedVars[i] = true;
            }
        }
        BreakEliminator breakEliminator = new BreakEliminator();
        breakEliminator.eliminate(method.getBody());
        OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads);
        method.getBody().acceptVisitor(optimizer);
        method.setBody(optimizer.resultStmt);
        int paramCount = method.getReference().parameterCount();
        UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables());
        method.getBody().acceptVisitor(unusedEliminator);
        method.getVariables().subList(unusedEliminator.lastIndex, method.getVariables().size()).clear();
        RedundantLabelEliminator labelEliminator = new RedundantLabelEliminator();
        method.getBody().acceptVisitor(labelEliminator);
        for (int i = 0; i < method.getVariables().size(); ++i) {
            method.getVariables().set(i, i);
        }
    }

    public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter) {
        LivenessAnalyzer liveness = new LivenessAnalyzer();
        liveness.analyze(splitter.getOriginalProgram());

        Graph cfg = ProgramUtils.buildControlFlowGraph(splitter.getOriginalProgram());

        for (int i = 0; i < splitter.size(); ++i) {
            boolean[] preservedVars = new boolean[method.getVariables().size()];
            ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
            stats.analyze(splitter.getProgram(i));
            for (int j = 0; j < stats.writes.length; ++j) {
                if (stats.writes[j] != 1 && stats.reads[j] > 0) {
                    preservedVars[j] = true;
                }
            }

            AsyncMethodPart part = method.getBody().get(i);
            BreakEliminator breakEliminator = new BreakEliminator();
            breakEliminator.eliminate(part.getStatement());
            findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
            OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads);
            part.getStatement().acceptVisitor(optimizer);
            part.setStatement(optimizer.resultStmt);
        }
        int paramCount = method.getReference().parameterCount();
        UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables());
        for (AsyncMethodPart part : method.getBody()) {
            part.getStatement().acceptVisitor(unusedEliminator);
        }
        method.getVariables().subList(unusedEliminator.lastIndex, method.getVariables().size()).clear();
        RedundantLabelEliminator labelEliminator = new RedundantLabelEliminator();
        for (AsyncMethodPart part : method.getBody()) {
            part.getStatement().acceptVisitor(labelEliminator);
        }
        for (int i = 0; i < method.getVariables().size(); ++i) {
            method.getVariables().set(i, i);
        }
    }

    private void findEscapingLiveVars(LivenessAnalyzer liveness, Graph cfg, AsyncProgramSplitter splitter,
            int partIndex, boolean[] output) {
        Program originalProgram = splitter.getOriginalProgram();
        Program program = splitter.getProgram(partIndex);
        int[] successors = splitter.getBlockSuccessors(partIndex);
        int[] splitPoints = splitter.getSplitPoints(partIndex);
        int[] originalBlocks = splitter.getOriginalBlocks(partIndex);

        for (int i = 0; i < program.basicBlockCount(); ++i) {
            if (successors[i] < 0 || originalBlocks[i] < 0) {
                continue;
            }

            // Determine live-out vars
            BitSet liveVars = new BitSet();
            for (int succ : cfg.outgoingEdges(originalBlocks[i])) {
                liveVars.or(liveness.liveIn(succ));
            }

            // Remove from live set all variables that are defined in these blocks
            DefinitionExtractor defExtractor = new DefinitionExtractor();
            UsageExtractor useExtractor = new UsageExtractor();
            List instructions = originalProgram.basicBlockAt(originalBlocks[i]).getInstructions();
            int splitPoint = splitPoints[i];
            for (int j = instructions.size() - 1; j >= splitPoint; --j) {
                instructions.get(j).acceptVisitor(defExtractor);
                instructions.get(j).acceptVisitor(useExtractor);
                for (Variable var : defExtractor.getDefinedVariables()) {
                    liveVars.clear(var.getIndex());
                }
                for (Variable var : useExtractor.getUsedVariables()) {
                    liveVars.set(var.getIndex());
                }
            }

            // Add live variables to output
            for (int j = liveVars.nextSetBit(0); j >= 0; j = liveVars.nextSetBit(j + 1)) {
                output[j] = true;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy