Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(439)

Unified Diff: dart/compiler/java/com/google/dart/compiler/backend/js/ClosureJsBackend.java

Issue 9353015: Remove dartc optimizing backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix minor test issues Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: dart/compiler/java/com/google/dart/compiler/backend/js/ClosureJsBackend.java
diff --git a/dart/compiler/java/com/google/dart/compiler/backend/js/ClosureJsBackend.java b/dart/compiler/java/com/google/dart/compiler/backend/js/ClosureJsBackend.java
deleted file mode 100644
index c72c7f991872fbb21e179881667ee1cdefbb15c1..0000000000000000000000000000000000000000
--- a/dart/compiler/java/com/google/dart/compiler/backend/js/ClosureJsBackend.java
+++ /dev/null
@@ -1,664 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.google.dart.compiler.backend.js;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.io.CharStreams;
-import com.google.common.io.Closeables;
-import com.google.common.io.LimitInputStream;
-import com.google.dart.compiler.DartCompilationError;
-import com.google.dart.compiler.DartCompilerContext;
-import com.google.dart.compiler.DartSource;
-import com.google.dart.compiler.LibrarySource;
-import com.google.dart.compiler.Source;
-import com.google.dart.compiler.ast.DartUnit;
-import com.google.dart.compiler.ast.LibraryNode;
-import com.google.dart.compiler.ast.LibraryUnit;
-import com.google.dart.compiler.backend.js.ast.JsProgram;
-import com.google.dart.compiler.common.SourceInfo;
-import com.google.dart.compiler.metrics.CompilerMetrics;
-import com.google.dart.compiler.resolver.CoreTypeProvider;
-import com.google.javascript.jscomp.CheckLevel;
-import com.google.javascript.jscomp.CompilationLevel;
-import com.google.javascript.jscomp.Compiler;
-import com.google.javascript.jscomp.CompilerInput;
-import com.google.javascript.jscomp.CompilerOptions;
-import com.google.javascript.jscomp.DiagnosticGroups;
-import com.google.javascript.jscomp.JSError;
-import com.google.javascript.jscomp.JSModule;
-import com.google.javascript.jscomp.JSSourceFile;
-import com.google.javascript.jscomp.PropertyRenamingPolicy;
-import com.google.javascript.jscomp.Result;
-import com.google.javascript.jscomp.SourceAst;
-import com.google.javascript.jscomp.SourceMap.DetailLevel;
-import com.google.javascript.jscomp.SourceMap.Format;
-import com.google.javascript.jscomp.VariableRenamingPolicy;
-import com.google.javascript.jscomp.WarningLevel;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URI;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-/**
- * A compiler backend that produces raw Javascript.
- * @author johnlenz@google.com (John Lenz)
- */
-public class ClosureJsBackend extends AbstractJsBackend {
- private static final String EXTENSION_OPT_JS = "opt.js";
- private static final String EXTENSION_OPT_JS_SRC_MAP = "opt.js.map";
-
- // A map of possible input sources to use when building the optimized output.
- private Map<String, DartUnit> dartSrcToUnitMap = Maps.newHashMap();
- private long totalJsOutputCharCount;
-
- // Generate "readable" output for debugging
- private final boolean generateHumanReadableOutput;
- // Generate "good" instead of "best" output.
- private final boolean fastOutput;
- // TODO(johnlenz): Currently we can only support incremential builds
- // if we aren't building source maps.
- private final boolean incremental;
-
- // Validate the generated JavaScript
- private final boolean validate;
-
- // Whether the generated code is "checked".
- private final boolean checkedMode;
-
- public ClosureJsBackend() {
- this(false, false);
- }
-
- /**
- * @param generateHumanReadableOutput - generates human readable javascript output.
- */
- public ClosureJsBackend(boolean checkedMode, boolean generateHumanReadableOutput) {
- // Current default settings
- this(false, false, true, checkedMode, generateHumanReadableOutput);
- }
-
- public ClosureJsBackend(boolean fastOutput,
- boolean incremental,
- boolean validate,
- boolean checkedMode,
- boolean generateHumanReadableOutput) {
- this.fastOutput = fastOutput;
- // can't currently produce a valid source map incrementally
- this.incremental = incremental;
- this.validate = validate;
- this.checkedMode = checkedMode;
- this.generateHumanReadableOutput = generateHumanReadableOutput;
- }
-
- @Override
- public boolean isOutOfDate(DartSource src, DartCompilerContext context) {
- if (!incremental) {
- return true;
- } else {
- return super.isOutOfDate(src, context);
- }
- }
-
- @Override
- public void compileUnit(DartUnit unit, DartSource src,
- DartCompilerContext context, CoreTypeProvider typeProvider) throws IOException {
- if (!incremental) {
- dartSrcToUnitMap.put(src.getName(), unit);
- } else {
- super.compileUnit(unit, src, context, typeProvider);
- }
- }
-
- private Map<String, CompilerInput> createClosureJsAst(Map<String,JsProgram> parts, Source source) {
- String name = source.getName();
- Preconditions.checkState(name != null && !name.isEmpty(), "A source name is required");
-
- Map<String, CompilerInput> translatedParts = new HashMap<String, CompilerInput>();
- for (Map.Entry<String,JsProgram> part : parts.entrySet()) {
- String partName = part.getKey();
- String inputName = name + ':' + partName;
- SourceAst sourceAst = new ClosureJsAst(part.getValue(), inputName, source, validate);
- CompilerInput input = new CompilerInput(sourceAst, false);
- translatedParts.put(part.getKey(), input);
- }
- return translatedParts;
- }
-
- private class DepsWritingCallback implements DepsCallback {
- private final DartCompilerContext context;
- private final CoreTypeProvider typeProvider;
- private final List<CompilerInput> inputs;
- private final Map<String, Source> sourcesByName;
- private final Map<DartUnit, Map<String, CompilerInput>> translatedUnits = Maps.newHashMap();
-
- DepsWritingCallback(
- DartCompilerContext context,
- CoreTypeProvider typeProvider,
- List<CompilerInput> inputs,
- Map<String, Source> sourcesByName) {
- this.context = context;
- this.typeProvider = typeProvider;
- this.inputs = inputs;
- this.sourcesByName = sourcesByName;
- }
-
- @Override
- public void visitNative(LibraryUnit libUnit, LibraryNode node)
- throws IOException {
- String name = node.getText();
- DartSource nativeSrc = libUnit.getSource().getSourceFor(name);
- StringWriter w = new StringWriter();
- Reader r = nativeSrc.getSourceReader();
- CharStreams.copy(r, w);
- inputs.add(new CompilerInput(createSource(name, w), false));
- }
-
- @Override
- public void visitPart(Part part) throws IOException {
- DartSource src = part.unit.getSource();
- if (!incremental) {
- Map<String, CompilerInput> translatedParts = translatedUnits.get(part.unit);
- if (translatedParts == null) {
- assert !sourcesByName.containsKey(src.getName());
- sourcesByName.put(src.getName(), src);
- Preconditions.checkNotNull(part.unit, "src: " + src.getName());
- translatedParts = translateUnit(part.unit, src, context, typeProvider);
- Preconditions.checkState(!translatedUnits.containsKey(part.unit));
- translatedUnits.put(part.unit, translatedParts);
- }
- inputs.add(translatedParts.get(part.part));
- return;
- }
-
- Reader r = context.getArtifactReader(src, part.part, EXTENSION_JS);
- if (r == null) {
- return;
- }
- StringWriter w = new StringWriter();
- CharStreams.copy(r, w);
- String inputName = src.getName() + ':' + part.part;
- inputs.add(new CompilerInput(createSource(inputName, w), false));
- }
-
- private JSSourceFile createSource(String name, Writer w) {
- return JSSourceFile.fromCode(name, w.toString());
- }
- }
-
- private void packageAppOptimized(LibrarySource app,
- Collection<LibraryUnit> libraries,
- DartCompilerContext context,
- CoreTypeProvider typeProvider)
- throws IOException {
-
- List<CompilerInput> inputs = Lists.newLinkedList();
- Map<String, Source> sourcesByName = Maps.newHashMap();
- DepsWritingCallback callback = new DepsWritingCallback(
- context, typeProvider, inputs, sourcesByName);
- DependencyBuilder.build(context.getAppLibraryUnit(), callback);
-
- // Lastly, add the entry point.
- inputs.add(getCompilerInputForEntry(context));
-
- // Currently, there is only a single module, add all the sources to it.
- JSModule mainModule = new JSModule("main");
- for (CompilerInput input : inputs) {
- if (input != null) {
- mainModule.add(input);
- }
- }
-
- Writer out = context.getArtifactWriter(app, "", getAppExtension());
- boolean failed = true;
- try {
- compileModule(app, context, mainModule, sourcesByName, out);
- failed = false;
- } finally {
- Closeables.close(out, failed);
- }
- }
-
- private Map<String, CompilerInput> translateUnit(
- DartUnit unit, DartSource src, DartCompilerContext context, CoreTypeProvider typeProvider) {
- Map<String, JsProgram> parts = translateToJS(unit, context, typeProvider);
-
- // Translate the AST and cache it for later use.
- return createClosureJsAst(parts, src);
- }
-
- private CompilerInput getCompilerInputForEntry(DartCompilerContext context)
- throws IOException {
- StringWriter entry = new StringWriter();
- writeEntryPointCall(getMangledEntryPoint(context), entry);
- return new CompilerInput(
- JSSourceFile.fromCode("entry", entry.toString()), false);
- }
-
- class MockSource implements Source {
- private String sourceName;
-
- MockSource(String sourceName) {
- this.sourceName = sourceName;
- }
-
- @Override
- public boolean exists() {
- return true;
- }
-
- @Override
- public long getLastModified() {
- return 0;
- }
-
- @Override
- public String getName() {
- return sourceName;
- }
-
- @Override
- public Reader getSourceReader() {
- return new StringReader("");
- }
-
- @Override
- public URI getUri() {
- return null;
- }
- }
-
- // Stub source info object for reporting errors coming from the Closure Compiler
- static class JSErrorSourceInfo implements SourceInfo {
- final JSError error;
- final Source source;
-
- JSErrorSourceInfo(JSError error, Source source) {
- this.error = error;
- this.source = source;
- }
-
- @Override
- public Source getSource() {
- return source;
- }
-
- @Override
- public int getSourceColumn() {
- return error.getCharno();
- }
-
- @Override
- public int getSourceLength() {
- return -1;
- }
-
- @Override
- public int getSourceLine() {
- return error.lineNumber;
- }
-
- @Override
- public int getSourceStart() {
- return -1;
- }
- }
-
- private void compileModule(
- LibrarySource src, DartCompilerContext context,
- JSModule module,
- Map<String, Source> sourcesByName,
- Writer out) throws IOException {
- // Turn off Closure Compiler logging
- CompilerOptions options = getClosureCompilerOptions(context);
- Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
-
- Compiler compiler = new Compiler();
-
- List<JSSourceFile> externs = getDefaultExterns();
- List<JSModule> modules = Lists.newLinkedList();
- modules.add(module);
- compiler.disableThreads();
- Result result = compiler.compileModules(externs, modules, options);
-
- if (processResults(src, context, compiler, result, module, out) != 0) {
- for (JSError error : result.errors) {
- // Use the real dart source object when we can.
- Source source = sourcesByName.get(error.sourceName);
- if (source == null) {
- // This might be a compiler generate source, whatever it is
- // report it.
- source = new MockSource(error.sourceName);
- }
- System.err.println("error optimizing:" + error.toString());
- DartCompilationError dartError =
- new DartCompilationError(new JSErrorSourceInfo(error, source),
- ClosureJsErrorCode.INTERNAL_ERROR,
- error.description);
- context.onError(dartError);
- }
- }
-
- out.close();
- }
-
- /**
- * Processes the results of the compile job, and returns an error code.
- */
- private int processResults(LibrarySource src, DartCompilerContext context, Compiler compiler,
- Result result, JSModule module, Writer out)
- throws IOException {
- if (result.success) {
- // TODO(johnlenz): Append directly to the writer.
- String output = compiler.toSource(module);
- out.append(output);
- out.append('\n');
-
- if (generateSourceMap(context)) {
- Writer srcMapOut = context.getArtifactWriter(src, "", getSourceMapExtension());
- boolean failed = true;
- try {
- compiler.getSourceMap().appendTo(srcMapOut, module.getName());
- failed = false;
- } finally {
- Closeables.close(srcMapOut, failed);
- }
- }
- totalJsOutputCharCount = output.length();
- }
-
- // return 0 if no errors, the error count otherwise
- return Math.min(result.errors.length, 0x7f);
- }
-
- private CompilerOptions getClosureCompilerOptions(DartCompilerContext context) {
- CompilerOptions options = new CompilerOptions();
- options.setCodingConvention(new ClosureJsCodingConvention());
-
- // Set the optimization passes that we want.
- if (fastOutput) {
- options.smartNameRemoval = true;
- options.collapseProperties = true;
- options.removeUnusedPrototypeProperties = true;
- options.removeUnusedVars = true;
- options.setRenamingPolicy(VariableRenamingPolicy.ALL, PropertyRenamingPolicy.ALL_UNQUOTED);
- // On by default
- options.setReplaceIdGenerators(false);
- } else {
- CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
- options.setAssumeStrictThis(true);
- // TODO(johnlenz): try out experimential inlining
- // options.setAssumeClosuresOnlyCaptureReferences(true);
-
- // TODO(johnlenz): rewriteFunctionExpressions kills the Richards benchmark,
- // it needs some better heuristics.
- options.rewriteFunctionExpressions = false;
-
- // AliasKeywords has a runtime performance hit, disable it.
- options.aliasKeywords = false;
-
- // slow for little value
- options.setPropertyAffinity(false);
-
- // TODO(johnlenz): These passes use SimpleDefinitionFinder or equivalent, and operate
- // based on property name, not object type. DisambiguateProperties helps but is not
- // a complete fix even with complete type information.
- // See http://code.google.com/p/closure-compiler/issues/detail?id=437.
- // We need to develop a plan for how to deal with them.
-
- options.computeFunctionSideEffects = false;
- options.devirtualizePrototypeMethods = true;
- options.inlineGetters = true;
-
- // TODO(johnlenz): Some DOM definitions look like unused prototype property
- // definitions because they are only referenced using dynamically generated
- // names.
- options.removeUnusedPrototypePropertiesInExterns = false;
- }
-
- if (generateSourceMap(context)) {
- options.sourceMapOutputPath = "placeholder"; // anything will do
- options.sourceMapDetailLevel = DetailLevel.SYMBOLS;
- options.sourceMapFormat = Format.V3;
- }
-
- // Turn off the default checks.
-
- // Dart doesn't currently need the Closure Library checks
- // or optimizations.
- options.closurePass = false;
-
- // Disable type warnings as we don't provide any type information.
- options.setInferTypes(false);
- options.checkTypes = false;
- options.setWarningLevel(DiagnosticGroups.CHECK_TYPES, CheckLevel.OFF);
-
- // Disable other checks, that don't make sense for generated code
- options.setWarningLevel(DiagnosticGroups.GLOBAL_THIS, CheckLevel.OFF);
- options.checkSuspiciousCode = false;
- options.checkGlobalThisLevel = CheckLevel.OFF;
- options.checkMissingReturn = CheckLevel.OFF;
- options.checkGlobalNamesLevel = CheckLevel.OFF;
- options.aggressiveVarCheck = CheckLevel.OFF;
- options.setWarningLevel(DiagnosticGroups.DEPRECATED, CheckLevel.OFF);
-
- // Optionally turn on the checks that are useful to Dart
- if (validate) {
- options.checkSymbols = true;
- options.setWarningLevel(DiagnosticGroups.ES5_STRICT, CheckLevel.ERROR);
- // options.setAggressiveVarCheck(CheckLevel.ERROR);
- } else {
- // A lot of warnings don't make sense for generated code, or require type
- // information. Turn them all off by default and make the ones we care
- // about errors.
- WarningLevel.QUIET.setOptionsForWarningLevel(options);
-
- options.checkSymbols = false;
- options.setWarningLevel(DiagnosticGroups.ES5_STRICT, CheckLevel.OFF);
- }
-
- // To ease debugging, try enabling these options:
- if (generateHumanReadableOutput) {
- options.prettyPrint = true;
- options.generatePseudoNames = true;
- options.printInputDelimiter = true;
- options.inputDelimiter = "// Input %name%";
- }
- // If those aren't enough, try disabling these:
- // options.setRenamingPolicy(VariableRenamingPolicy.OFF, PropertyRenamingPolicy.OFF);
- // options.coalesceVariableNames = false;
- // options.setShadowVariables(false);
- // options.inlineFunctions = false;
-
- /*
- * NOTE: We turn this off because TypeErrors or anything that relies on a type name will fail
- * due to the class renaming.
- */
- if (checkedMode) {
- options.setReplaceIdGenerators(false);
- }
-
- return options;
- }
-
- // The externs expected in externs.zip, in sorted order.
- private static final List<String> DEFAULT_EXTERNS_NAMES = ImmutableList.of(
- // JS externs
- "es3.js",
- "es5.js",
- // "json.js", // TODO(johnlenz): add this.
-
- // Event APIs
- "w3c_event.js",
- "w3c_event3.js",
- "gecko_event.js",
- "ie_event.js",
- "webkit_event.js",
-
- // DOM apis
- "w3c_dom1.js",
- "w3c_dom2.js",
- "w3c_dom3.js",
- "gecko_dom.js",
- "ie_dom.js",
- "webkit_dom.js",
-
- // CSS apis
- "w3c_css.js",
- "gecko_css.js",
- "ie_css.js",
- "webkit_css.js",
-
- // Top-level namespaces
- "google.js",
-
- "deprecated.js",
- "fileapi.js",
- "flash.js",
- "gears_symbols.js",
- "gears_types.js",
- "gecko_xml.js",
- "html5.js",
- "ie_vml.js",
- "iphone.js",
- "webstorage.js",
- "w3c_anim_timing.js",
- "w3c_css3d.js",
- "w3c_elementtraversal.js",
- "w3c_geolocation.js",
- "w3c_indexeddb.js",
- "w3c_navigation_timing.js",
- "w3c_range.js",
- "w3c_selectors.js",
- "w3c_xml.js",
- "window.js",
- "webkit_notifications.js",
- "webgl.js");
-
- // Add a declarations for the V8 logging function.
- private static final String UNIT_TEST_EXTERN_STUBS = "var write;";
-
- private static final String CLOSURE_PRIMITIVES = "function JSCompiler_renameProperty() {};";
-
- // TODO(johnlenz): include json.js in the default set of externs.
- private static final String MISSING_EXTERNS =
- "var JSON = {};\n" +
- "/**\n" +
- " * @param {string} jsonStr The string to parse.\n" +
- " * @param {(function(string, *) : *)=} opt_reviver\n" +
- " * @return {*} The JSON object.\n" +
- " */\n" +
- "JSON.parse = function(jsonStr, opt_reviver) {};\n" +
- "\n" +
- "/**\n" +
- " * @param {*} jsonObj Input object.\n" +
- " * @param {(Array.<string>|(function(string, *) : *)|null)=} opt_replacer\n" +
- " * @param {(number|string)=} opt_space\n" +
- " * @return {string} json string which represents jsonObj.\n" +
- " */\n" +
- "JSON.stringify = function(jsonObj, opt_replacer, opt_space) {};" +
- "\n";
-
- /**
- * @return a mutable list
- * @throws IOException
- */
- private static List<JSSourceFile> getDefaultExterns() throws IOException {
- Class<ClosureJsBackend> clazz = ClosureJsBackend.class;
- InputStream input = clazz.getResourceAsStream(
- "/com/google/javascript/jscomp/externs.zip");
- if (input == null) {
- /*
- * HACK - the open source version of the closure compiler maps the
- * resource into a different location.
- */
- input = clazz.getResourceAsStream("/externs.zip");
- }
- ZipInputStream zip = new ZipInputStream(input);
- Map<String, JSSourceFile> externsMap = Maps.newHashMap();
- for (ZipEntry entry = null; (entry = zip.getNextEntry()) != null; ) {
- InputStream entryStream = new BufferedInputStream(
- new LimitInputStream(zip, entry.getSize()));
- externsMap.put(entry.getName(),
- JSSourceFile.fromInputStream(
- // Give the files an odd prefix, so that they do not conflict
- // with the user's files.
- "externs.zip//" + entry.getName(),
- entryStream));
- }
-
- Preconditions.checkState(
- externsMap.keySet().equals(Sets.newHashSet(DEFAULT_EXTERNS_NAMES)),
- "Externs zip must match our hard-coded list of externs.");
-
- // Order matters, so the resources must be added to the result list
- // in the expected order.
- List<JSSourceFile> externs = Lists.newArrayList();
- for (String key : DEFAULT_EXTERNS_NAMES) {
- externs.add(externsMap.get(key));
- }
-
- // Add methods used when running the unit tests.
- externs.add(JSSourceFile.fromCode("missingExterns", MISSING_EXTERNS));
-
- // Add methods used when running the unit tests.
- externs.add(JSSourceFile.fromCode("unitTestStubs", UNIT_TEST_EXTERN_STUBS));
-
- // Add methods used by Closure Compiler itself.
- externs.add(JSSourceFile.fromCode("closureCompilerPrimitives", CLOSURE_PRIMITIVES));
-
- return externs;
- }
-
- @Override
- public void packageApp(LibrarySource app,
- Collection<LibraryUnit> libraries,
- DartCompilerContext context,
- CoreTypeProvider typeProvider)
- throws IOException {
- totalJsOutputCharCount = 0;
- packageAppOptimized(app, libraries, context, typeProvider);
- CompilerMetrics compilerMetrics = context.getCompilerMetrics();
- if (compilerMetrics != null) {
- compilerMetrics.packagedJsApplication(totalJsOutputCharCount, -1);
- }
- }
-
- @Override
- public String getAppExtension() {
- return (incremental) ? EXTENSION_APP_JS : EXTENSION_OPT_JS;
- }
-
- @Override
- public String getSourceMapExtension() {
- return (incremental) ? EXTENSION_APP_JS_SRC_MAP : EXTENSION_OPT_JS_SRC_MAP;
- }
-
- @Override
- protected boolean shouldOptimize() {
- return (fastOutput) ? false : true;
- }
-
- @Override
- protected boolean generateClosureCompatibleCode() {
- return true;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698