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

Unified Diff: lib/src/codegen/js_module_item_order.dart

Issue 1879373004: Implement modular compilation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « lib/src/codegen/js_metalet.dart ('k') | lib/src/codegen/js_names.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/codegen/js_module_item_order.dart
diff --git a/lib/src/codegen/js_module_item_order.dart b/lib/src/codegen/js_module_item_order.dart
deleted file mode 100644
index bbb9c6ce0cc12d2c2040911aebcbc99a993acb38..0000000000000000000000000000000000000000
--- a/lib/src/codegen/js_module_item_order.dart
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) 2015, 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.
-
-import 'dart:collection' show HashMap;
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-
-import '../compiler.dart' show corelibOrder;
-
-typedef void ModuleItemEmitter(AstNode item);
-
-/// Helper that tracks order of elements visited by the compiler, detecting
-/// if the top level item can be loaded eagerly or not.
-class ModuleItemLoadOrder {
- /// The order that elements should be emitted in, with a bit indicating if
- /// the element should be generated lazily. The value will be `false` if
- /// the item could not be loaded, and needs to be made lazy.
- ///
- /// The order will match the original source order, unless something needed to
- /// be moved sooner to satisfy dependencies.
- ///
- /// Sometimes it's impossible to ensure an ordering when confronting library
- /// cycles. In that case, we mark the definition as lazy.
- final _loaded = new Map<Element, bool>();
-
- final _declarationNodes = new HashMap<Element, AstNode>();
-
- /// The stack of currently emitting elements, if generating top-level code
- /// for them. This is not used when inside method bodies, because order does
- /// not matter for those.
- final _topLevelElements = new List<Element>();
-
- /// The current element being loaded.
- /// We can use this to determine if we're loading top-level code or not:
- ///
- /// _currentElements.last == _topLevelElements.last
- final _currentElements = new List<Element>();
-
- /// Memoized results of [_inLibraryCycle].
- final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
-
- bool _checkReferences;
-
- final ModuleItemEmitter _emitModuleItem;
-
- LibraryElement _currentLibrary;
-
- ModuleItemLoadOrder(this._emitModuleItem);
-
- bool isLoaded(Element e) => (e.library == _currentLibrary)
- ? _loaded[e] == true
- : libraryIsLoaded(e.library);
-
- /// True if the element is currently being loaded.
- bool _isLoading(Element e) => _currentElements.contains(e);
-
- /// Collect top-level elements and nodes we need to emit.
- void collectElements(
- LibraryElement library, Iterable<CompilationUnit> partsThenLibrary) {
- assert(_currentLibrary == null);
- _currentLibrary = library;
-
- for (var unit in partsThenLibrary) {
- for (var decl in unit.declarations) {
- _declarationNodes[decl.element] = decl;
-
- if (decl is TopLevelVariableDeclaration) {
- _collectElementsForVariable(decl.variables);
- }
- }
- }
- }
-
- void _collectElementsForVariable(VariableDeclarationList fields) {
- for (var field in fields.variables) {
- _declarationNodes[field.element] = field;
- }
- }
-
- /// Start generating top-level code for the element [e].
- /// Subsequent [loadElement] calls will cause those elements to be generated
- /// before this one, until [finishElement] is called.
- void startTopLevel(Element e) {
- assert(isCurrentElement(e));
- _topLevelElements.add(e);
- }
-
- /// Finishes the top-level code for the element [e].
- void finishTopLevel(Element e) {
- var last = _topLevelElements.removeLast();
- assert(identical(e, last));
- }
-
- /// Starts recording calls to [declareBeforeUse], until
- /// [finishCheckingReferences] is called.
- void startCheckingReferences() {
- // This function should not be reentrant, and we should not current be
- // emitting top-level code.
- assert(_checkReferences == null);
- assert(
- _topLevelElements.isEmpty || !isCurrentElement(_topLevelElements.last));
- // Assume true until proven otherwise
- _checkReferences = true;
- }
-
- /// Finishes recording references, and returns `true` if all referenced
- /// items were loaded (or if no items were referenced).
- bool finishCheckingReferences() {
- var result = _checkReferences;
- _checkReferences = null;
- return result;
- }
-
- // Starts generating code for the declaration element [e].
- //
- // Normally this is called implicitly by [loadDeclaration] and/or
- // [loadElement]. However, for synthetic elements (like temporary variables)
- // it must be called explicitly, and paired with a call to [finishElement].
- void startDeclaration(Element e) {
- // Assume load will succeed until proven otherwise.
- _loaded[e] = true;
- _currentElements.add(e);
- }
-
- /// Returns true if all dependencies were loaded successfully.
- bool finishDeclaration(Element e) {
- var last = _currentElements.removeLast();
- assert(identical(e, last));
- return _loaded[e];
- }
-
- /// Loads a top-level declaration. This is similar to [loadElement], but it
- /// ensures we always visit the node if it has not been emitted yet. In other
- /// words, it handles nodes that do not need dependency resolution like
- /// top-level functions.
- bool loadDeclaration(AstNode node, Element e) {
- assert(e.library == _currentLibrary);
-
- // If we already tried to load it, see if we succeeded or not.
- // Otherwise try and load now.
- var loaded = _loaded[e];
- if (loaded != null) return loaded;
-
- // Otherwise, try to load it.
- startDeclaration(e);
- _emitModuleItem(node);
- return finishDeclaration(e);
- }
-
- bool isCurrentElement(Element e) =>
- _currentElements.isNotEmpty && identical(e, _currentElements.last);
-
- /// To emit top-level module items, we sometimes need to reorder them.
- ///
- /// This function takes care of that, and also detects cases where reordering
- /// failed, and we need to resort to lazy loading, by marking the element as
- /// lazy. All elements need to be aware of this possibility and generate code
- /// accordingly.
- ///
- /// If we are not emitting top-level code, this does nothing, because all
- /// declarations are assumed to be available before we start execution.
- /// See [startTopLevel].
- void declareBeforeUse(Element e) {
- if (e == null) return;
-
- if (_checkReferences != null) {
- _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
- return;
- }
-
- if (_topLevelElements.isEmpty ||
- !isCurrentElement(_topLevelElements.last)) {
- return;
- }
-
- // If the item is from our library, try to emit it now.
- bool loaded;
- if (e.library == _currentLibrary) {
- // Type parameters are not in scope when generating hoisted fields.
- if (e is TypeParameterElement &&
- _currentElements.last is VariableElement) {
- loaded = false;
- } else {
- var node = _declarationNodes[e];
- loaded = node == null || loadDeclaration(node, e);
- }
- } else {
- // We can't force things from other libraries to be emitted in a different
- // order. Instead, we see if the library itself can be loaded before the
- // current library. Generally that is possible, unless we have cyclic
- // imports.
- loaded = libraryIsLoaded(e.library);
- }
-
- if (loaded) return;
-
- // If we failed to emit it, then we need to make sure all currently emitting
- // elements are generated in a lazy way.
- for (var current in _topLevelElements) {
- // TODO(jmesserly): if we want to log what triggered laziness, this is
- // the place to do so.
- _loaded[current] = false;
- }
- }
-
- bool libraryIsLoaded(LibraryElement library) {
- assert(library != _currentLibrary);
-
- // DynamicElementImpl has no library.
- if (library == null) return true;
-
- // The SDK is a special case: we optimize the order to prevent laziness.
- if (library.source.isInSystemLibrary) {
- // SDK is loaded before non-SDK libraries
- if (!_currentLibrary.source.isInSystemLibrary) return true;
-
- // Compute the order of both SDK libraries. If unknown, assume it's after.
- var order = corelibOrder.indexOf(library.source.uri);
- if (order == -1) order = corelibOrder.length;
-
- var currentOrder = corelibOrder.indexOf(_currentLibrary.source.uri);
- if (currentOrder == -1) currentOrder = corelibOrder.length;
-
- // If the dart:* library we are currently compiling is loaded after the
- // class's library, then we know the class is available.
- if (order != currentOrder) return currentOrder > order;
-
- // If we don't know the order of the class's library or the current
- // library, do the normal cycle check. (Not all SDK libs are cycles.)
- }
-
- return !_inLibraryCycle(library);
- }
-
- /// Returns true if [library] depends on the [currentLibrary] via some
- /// transitive import.
- bool _inLibraryCycle(LibraryElement library) {
- // SDK libs don't depend on things outside the SDK.
- // (We can reach this via the recursive call below.)
- if (library.source.isInSystemLibrary &&
- !_currentLibrary.source.isInSystemLibrary) return false;
-
- var result = _libraryCycleMemo[library];
- if (result != null) return result;
-
- result = library == _currentLibrary;
- _libraryCycleMemo[library] = result;
- for (var e in library.imports) {
- if (result) break;
- result = _inLibraryCycle(e.importedLibrary);
- }
- for (var e in library.exports) {
- if (result) break;
- result = _inLibraryCycle(e.exportedLibrary);
- }
- return _libraryCycleMemo[library] = result;
- }
-}
« no previous file with comments | « lib/src/codegen/js_metalet.dart ('k') | lib/src/codegen/js_names.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698