Package com.google.gwt.dev

Source Code of com.google.gwt.dev.CompilePerms

/*
* Copyright 2008 Google Inc.
*
* 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 com.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.Precompile.PrecompileOptions;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.PropertyPermutations;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.OptionLocalWorkers;
import com.google.gwt.util.tools.ArgHandlerString;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

/**
* Performs the second phase of compilation, converting the Precompile's AST
* into JavaScript outputs.
*/
public class CompilePerms {

  /**
   * Options for CompilePerms.
   */
  public interface CompilePermsOptions extends CompileTaskOptions,
      OptionLocalWorkers, OptionPerms {
  }

  /**
   * Handles options for which permutations to compile.
   */
  public interface OptionPerms {
    /**
     * Gets the ordered set of permutations to compile. Returns a zero-length
     * array if all permutations should be compiled.
     */
    int[] getPermsToCompile();

    /**
     * Adds another permutation to compile.
     */
    void setPermsToCompile(int[] permsToCompile);
  }

  /**
   * Argument handler for specifying the which perms to run.
   */
  protected static final class ArgHandlerPerms extends ArgHandlerString {
    private final OptionPerms option;

    public ArgHandlerPerms(OptionPerms option) {
      this.option = option;
    }

    @Override
    public String getPurpose() {
      return "Comma-delimited list of 0-based permutations to compile";
    }

    @Override
    public String getTag() {
      return "-perms";
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"permlist"};
    }

    @Override
    public boolean setString(String str) {
      String[] split = str.split(",");
      if (split.length < 1) {
        System.err.println(getTag()
            + " requires a comma-delimited list of integers");
        return false;
      }

      SortedSet<Integer> permSet = new TreeSet<Integer>();
      for (String item : split) {
        try {
          int value = Integer.parseInt(item);
          if (value < 0) {
            System.err.println(getTag() + " error: negative value '" + value
                + "' is not allowed");
            return false;
          }
          permSet.add(value);
        } catch (NumberFormatException e) {
          System.err.println(getTag()
              + " requires a comma-delimited list of integers; '" + item
              + "' is not an integer");
          return false;
        }
      }
      int[] permsToCompile = new int[permSet.size()];
      int i = 0;
      for (int perm : permSet) {
        permsToCompile[i++] = perm;
      }
      option.setPermsToCompile(permsToCompile);
      return true;
    }
  }

  static class ArgProcessor extends CompileArgProcessor {
    public ArgProcessor(CompilePermsOptions options) {
      super(options);
      registerHandler(new ArgHandlerPerms(options));
      registerHandler(new ArgHandlerLocalWorkers(options));
    }

    @Override
    protected String getName() {
      return CompilePerms.class.getName();
    }
  }

  /**
   * Concrete class to implement compiler perm options.
   */
  static class CompilePermsOptionsImpl extends CompileTaskOptionsImpl implements
      CompilePermsOptions {

    private int localWorkers;
    private int[] permsToCompile;

    public CompilePermsOptionsImpl() {
    }

    public CompilePermsOptionsImpl(CompilePermsOptions other) {
      copyFrom(other);
    }

    public void copyFrom(CompilePermsOptions other) {
      super.copyFrom(other);
      setPermsToCompile(other.getPermsToCompile());
      setLocalWorkers(other.getLocalWorkers());
    }

    public int getLocalWorkers() {
      return localWorkers;
    }

    public int[] getPermsToCompile() {
      return (permsToCompile == null) ? null : permsToCompile.clone();
    }

    public void setLocalWorkers(int localWorkers) {
      this.localWorkers = localWorkers;
    }

    public void setPermsToCompile(int[] permsToCompile) {
      this.permsToCompile = (permsToCompile == null) ? null
          : permsToCompile.clone();
    }
  }

  /**
   * Compile a single permutation.
   *
   * @throws UnableToCompleteException if the permutation compile fails
   */
  public static PermutationResult compile(TreeLogger logger,
      Permutation permutation, UnifiedAst unifiedAst)
      throws UnableToCompleteException {
    return unifiedAst.compilePermutation(logger, permutation);
  }

  /**
   * Compile multiple permutations.
   */
  public static void compile(TreeLogger logger, Precompilation precompilation,
      Permutation[] perms, int localWorkers,
      List<FileBackedObject<PermutationResult>> resultFiles)
      throws UnableToCompleteException {
    final TreeLogger branch = logger.branch(TreeLogger.INFO, "Compiling "
        + perms.length + " permutation" + (perms.length > 1 ? "s" : ""));
    PermutationWorkerFactory.compilePermutations(branch, precompilation, perms,
        localWorkers, resultFiles);
    logger.log(TreeLogger.INFO, "Compile of permutations succeeded");
  }

  public static void main(String[] args) {
    /*
     * NOTE: main always exits with a call to System.exit to terminate any
     * non-daemon threads that were started in Generators. Typically, this is to
     * shutdown AWT related threads, since the contract for their termination is
     * still implementation-dependent.
     */
    final CompilePermsOptions options = new CompilePermsOptionsImpl();
    if (new ArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          return new CompilePerms(options).run(logger);
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        // Exit w/ success code.
        System.exit(0);
      }
    }
    // Exit w/ non-success code.
    System.exit(1);
  }

  public static List<FileBackedObject<PermutationResult>> makeResultFiles(
      File compilerWorkDir, Permutation[] perms) {
    List<FileBackedObject<PermutationResult>> toReturn = new ArrayList<FileBackedObject<PermutationResult>>(
        perms.length);
    for (int i = 0; i < perms.length; ++i) {
      File f = makePermFilename(compilerWorkDir, perms[i].getId());
      toReturn.add(new FileBackedObject<PermutationResult>(
          PermutationResult.class, f));
    }
    return toReturn;
  }

  /**
   * Return the filename corresponding to the given permutation number,
   * one-based.
   */
  static File makePermFilename(File compilerWorkDir, int permNumber) {
    return new File(compilerWorkDir, "permutation-" + permNumber + ".js");
  }

  /**
   * Choose the subset of requested permutations that correspond to the
   * indicated precompilation.
   */
  private static Permutation[] selectPermutationsForPrecompilation(
      int[] permsToRun, Precompilation precompilation) {
    if (permsToRun == null) {
      // Special case: compile everything.
      return precompilation.getPermutations();
    }
    ArrayList<Permutation> subPermsList = new ArrayList<Permutation>();
    for (int id : permsToRun) {
      for (Permutation perm : precompilation.getPermutations()) {
        if (perm.getId() == id) {
          subPermsList.add(perm);
        }
      }
    }
    return subPermsList.toArray(new Permutation[subPermsList.size()]);
  }

  private final CompilePermsOptionsImpl options;

  public CompilePerms(CompilePermsOptions options) {
    this.options = new CompilePermsOptionsImpl(options);
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    for (String moduleName : options.getModuleNames()) {
      /*
       * NOTE: as a special case, null means "compile everything".
       */
      int[] permsToRun = options.getPermsToCompile();

      File compilerWorkDir = options.getCompilerWorkDir(moduleName);
      File precompilationFile = new File(compilerWorkDir,
          Precompile.PRECOMPILE_FILENAME);

      PrecompilationResult precompileResults;
      try {
        precompileResults = Util.readFileAsObject(precompilationFile,
            PrecompilationResult.class);
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Failed to read "
            + Precompile.PRECOMPILE_FILENAME + "; has Precompile been run?");
        return false;
      } catch (ClassNotFoundException e) {
        logger.log(TreeLogger.ERROR, "Failed to read "
            + Precompile.PRECOMPILE_FILENAME, e);
        return false;
      }

      /*
       * TODO(spoon) Check that all requested permutations have a permutation
       * available before starting. probably needs two branches.
       */

      if (precompileResults instanceof PrecompileOptions) {
        PrecompileOptions precompilationOptions = (PrecompileOptions) precompileResults;
        if (!precompileAndCompile(logger, moduleName, compilerWorkDir,
            precompilationOptions)) {
          return false;
        }
      } else {
        Precompilation precompilation = (Precompilation) precompileResults;
        // Choose which permutations go with this permutation
        Permutation[] subPerms = selectPermutationsForPrecompilation(
            permsToRun, precompilation);

        List<FileBackedObject<PermutationResult>> resultFiles = makeResultFiles(
            compilerWorkDir, subPerms);
        compile(logger, precompilation, subPerms, options.getLocalWorkers(),
            resultFiles);
      }
    }

    return true;
  }

  /**
   * Run both a precompile and a compile with the given precompilation options.
   */
  private boolean precompileAndCompile(TreeLogger logger, String moduleName,
      File compilerWorkDir, PrecompileOptions precompilationOptions)
      throws UnableToCompleteException {
    precompilationOptions.setOptimizePrecompile(false);
    precompilationOptions.setCompilationStateRetained(true);
    precompilationOptions.setGenDir(null);

    ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName);
    PropertyPermutations allPermutations = new PropertyPermutations(
        module.getProperties());
    int[] perms = options.getPermsToCompile();
    if (perms == null) {
      perms = new int[allPermutations.size()];
      for (int i = 0; i < perms.length; ++i) {
        perms[i] = i;
      }
    }

    logger = logger.branch(TreeLogger.INFO, "Compiling " + perms.length
        + " permutation" + (perms.length > 1 ? "s" : ""));
    for (int permId : perms) {
      /*
       * TODO(spoon,scottb): move Precompile out of the loop to run only once
       * per shard. We'll need a new PropertyPermutations constructor that can
       * take a precise list. Then figure out a way to avoid copying the
       * generated artifacts into every perm result on a shard.
       */
      module.getCompilationState(logger).refresh(logger);
      PropertyPermutations onePerm = new PropertyPermutations(allPermutations,
          permId, 1);

      assert (precompilationOptions.getDumpSignatureFile() == null);
      Precompilation precompilation = Precompile.precompile(logger,
          precompilationOptions, module, permId, onePerm,
          precompilationOptions.getGenDir(), compilerWorkDir, null);
      if (precompilation == null) {
        return false;
      }

      // Choose which permutations go with this precompilation
      Permutation[] subPerms = selectPermutationsForPrecompilation(
          new int[] {permId}, precompilation);
      assert subPerms.length == 1;

      PermutationResult permResult = compile(logger, subPerms[0],
          precompilation.getUnifiedAst());
      FileBackedObject<PermutationResult> resultFile = new FileBackedObject<PermutationResult>(
          PermutationResult.class, makePermFilename(compilerWorkDir, permId));
      permResult.addArtifacts(precompilation.getGeneratedArtifacts());
      resultFile.set(logger, permResult);
    }

    logger.log(TreeLogger.INFO, "Compile of permutations succeeded");
    return true;
  }
}
TOP

Related Classes of com.google.gwt.dev.CompilePerms

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.