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

Unified Diff: pkg/compiler/lib/src/js_emitter/code_emitter_task.dart

Issue 1227643003: dart2js: Move most of the code_emitter_task code into the program-builder. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Upload Created 5 years, 5 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 | « no previous file | pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index b8fa032d80e5530d90643eef59232bdb439b2655..7d77bf3ce5bd9ff388b8794f5325846f0884baa2 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -21,34 +21,19 @@ class CodeEmitterTask extends CompilerTask {
OldEmitter oldEmitter;
Emitter emitter;
- final Set<ClassElement> neededClasses = new Set<ClassElement>();
- Set<ClassElement> classesOnlyNeededForRti;
- final Map<OutputUnit, List<ClassElement>> outputClassLists =
- new Map<OutputUnit, List<ClassElement>>();
- final Map<OutputUnit, List<ConstantValue>> outputConstantLists =
- new Map<OutputUnit, List<ConstantValue>>();
- final Map<OutputUnit, List<Element>> outputStaticLists =
- new Map<OutputUnit, List<Element>>();
- final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists =
- new Map<OutputUnit, List<VariableElement>>();
- final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists =
- new Map<OutputUnit, Set<LibraryElement>>();
-
- /// True, if the output contains a constant list.
- ///
- /// This flag is updated in [computeNeededConstants].
- bool outputContainsConstantList = false;
-
- final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[];
-
/// Records if a type variable is read dynamically for type tests.
final Set<TypeVariableElement> readTypeVariables =
new Set<TypeVariableElement>();
- List<TypedefElement> typedefsNeededForReflection;
-
JavaScriptBackend get backend => compiler.backend;
+ @deprecated
+ // This field should be removed. It's currently only needed for dump-info and
+ // tests.
+ // The field is set after the program has been emitted.
+ /// Contains a list of all classes that are emitted.
+ Set<ClassElement> neededClasses;
+
CodeEmitterTask(Compiler compiler, Namer namer, bool generateSourceMap)
: super(compiler),
this.namer = namer,
@@ -134,277 +119,25 @@ class CodeEmitterTask extends CompilerTask {
readTypeVariables.add(element);
}
- Set<ClassElement> computeInterceptorsReferencedFromConstants() {
- Set<ClassElement> classes = new Set<ClassElement>();
- JavaScriptConstantCompiler handler = backend.constants;
- List<ConstantValue> constants = handler.getConstantsForEmission();
- for (ConstantValue constant in constants) {
- if (constant is InterceptorConstantValue) {
- InterceptorConstantValue interceptorConstant = constant;
- classes.add(interceptorConstant.dispatchedType.element);
- }
- }
- return classes;
- }
-
- /**
- * Return a function that returns true if its argument is a class
- * that needs to be emitted.
- */
- Function computeClassFilter() {
- if (backend.isTreeShakingDisabled) return (ClassElement cls) => true;
-
- Set<ClassElement> unneededClasses = new Set<ClassElement>();
- // The [Bool] class is not marked as abstract, but has a factory
- // constructor that always throws. We never need to emit it.
- unneededClasses.add(compiler.boolClass);
-
- // Go over specialized interceptors and then constants to know which
- // interceptors are needed.
- Set<ClassElement> needed = new Set<ClassElement>();
- backend.specializedGetInterceptors.forEach(
- (_, Iterable<ClassElement> elements) {
- needed.addAll(elements);
- }
- );
-
- // Add interceptors referenced by constants.
- needed.addAll(computeInterceptorsReferencedFromConstants());
-
- // Add unneeded interceptors to the [unneededClasses] set.
- for (ClassElement interceptor in backend.interceptedClasses) {
- if (!needed.contains(interceptor)
- && interceptor != compiler.objectClass) {
- unneededClasses.add(interceptor);
- }
- }
-
- // These classes are just helpers for the backend's type system.
- unneededClasses.add(backend.jsMutableArrayClass);
- unneededClasses.add(backend.jsFixedArrayClass);
- unneededClasses.add(backend.jsExtendableArrayClass);
- unneededClasses.add(backend.jsUInt32Class);
- unneededClasses.add(backend.jsUInt31Class);
- unneededClasses.add(backend.jsPositiveIntClass);
-
- return (ClassElement cls) => !unneededClasses.contains(cls);
- }
-
- /**
- * Compute all the constants that must be emitted.
- */
- void computeNeededConstants() {
- // Make sure we retain all metadata of all elements. This could add new
- // constants to the handler.
- if (backend.mustRetainMetadata) {
- // TODO(floitsch): verify that we don't run through the same elements
- // multiple times.
- for (Element element in backend.generatedCode.keys) {
- if (backend.isAccessibleByReflection(element)) {
- bool shouldRetainMetadata = backend.retainMetadataOf(element);
- if (shouldRetainMetadata &&
- (element.isFunction || element.isConstructor ||
- element.isSetter)) {
- FunctionElement function = element;
- function.functionSignature.forEachParameter(
- backend.retainMetadataOf);
- }
- }
- }
- for (ClassElement cls in neededClasses) {
- final onlyForRti = classesOnlyNeededForRti.contains(cls);
- if (!onlyForRti) {
- backend.retainMetadataOf(cls);
- oldEmitter.classEmitter.visitFields(cls, false,
- (Element member,
- jsAst.Name name,
- jsAst.Name accessorName,
- bool needsGetter,
- bool needsSetter,
- bool needsCheckedSetter) {
- bool needsAccessor = needsGetter || needsSetter;
- if (needsAccessor && backend.isAccessibleByReflection(member)) {
- backend.retainMetadataOf(member);
- }
- });
- }
- }
- typedefsNeededForReflection.forEach(backend.retainMetadataOf);
- }
-
- JavaScriptConstantCompiler handler = backend.constants;
- List<ConstantValue> constants = handler.getConstantsForEmission(
- compiler.hasIncrementalSupport ? null : emitter.compareConstants);
- for (ConstantValue constant in constants) {
- if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
-
- if (constant.isList) outputContainsConstantList = true;
-
- OutputUnit constantUnit =
- compiler.deferredLoadTask.outputUnitForConstant(constant);
- if (constantUnit == null) {
- // The back-end introduces some constants, like "InterceptorConstant" or
- // some list constants. They are emitted in the main output-unit.
- // TODO(sigurdm): We should track those constants.
- constantUnit = compiler.deferredLoadTask.mainOutputUnit;
- }
- outputConstantLists.putIfAbsent(
- constantUnit, () => new List<ConstantValue>()).add(constant);
- }
- }
-
- /// Compute all the classes and typedefs that must be emitted.
- void computeNeededDeclarations(Set<ClassElement> rtiNeededClasses) {
- // Compute needed typedefs.
- typedefsNeededForReflection = Elements.sortedByPosition(
- compiler.world.allTypedefs
- .where(backend.isAccessibleByReflection)
- .toList());
-
- // Compute needed classes.
- Set<ClassElement> instantiatedClasses =
- compiler.codegenWorld.directlyInstantiatedClasses
- .where(computeClassFilter()).toSet();
-
- void addClassWithSuperclasses(ClassElement cls) {
- neededClasses.add(cls);
- for (ClassElement superclass = cls.superclass;
- superclass != null;
- superclass = superclass.superclass) {
- neededClasses.add(superclass);
- }
- }
-
- void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
- for (ClassElement cls in classes) {
- addClassWithSuperclasses(cls);
- }
- }
-
- // 1. We need to generate all classes that are instantiated.
- addClassesWithSuperclasses(instantiatedClasses);
-
- // 2. Add all classes used as mixins.
- Set<ClassElement> mixinClasses = neededClasses
- .where((ClassElement element) => element.isMixinApplication)
- .map(computeMixinClass)
- .toSet();
- neededClasses.addAll(mixinClasses);
-
- // 3. Find all classes needed for rti.
- // It is important that this is the penultimate step, at this point,
- // neededClasses must only contain classes that have been resolved and
- // codegen'd. The rtiNeededClasses may contain additional classes, but
- // these are thought to not have been instantiated, so we neeed to be able
- // to identify them later and make sure we only emit "empty shells" without
- // fields, etc.
- classesOnlyNeededForRti = rtiNeededClasses.difference(neededClasses);
-
- neededClasses.addAll(classesOnlyNeededForRti);
-
- // TODO(18175, floitsch): remove once issue 18175 is fixed.
- if (neededClasses.contains(backend.jsIntClass)) {
- neededClasses.add(compiler.intClass);
- }
- if (neededClasses.contains(backend.jsDoubleClass)) {
- neededClasses.add(compiler.doubleClass);
- }
- if (neededClasses.contains(backend.jsNumberClass)) {
- neededClasses.add(compiler.numClass);
- }
- if (neededClasses.contains(backend.jsStringClass)) {
- neededClasses.add(compiler.stringClass);
- }
- if (neededClasses.contains(backend.jsBoolClass)) {
- neededClasses.add(compiler.boolClass);
- }
- if (neededClasses.contains(backend.jsArrayClass)) {
- neededClasses.add(compiler.listClass);
- }
-
- // 4. Finally, sort the classes.
- List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses);
-
- for (ClassElement element in sortedClasses) {
- if (Elements.isNativeOrExtendsNative(element) &&
- !classesOnlyNeededForRti.contains(element)) {
- // For now, native classes and related classes cannot be deferred.
- nativeClassesAndSubclasses.add(element);
- assert(invariant(element,
- !compiler.deferredLoadTask.isDeferred(element)));
- outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
- () => new List<ClassElement>()).add(element);
- } else {
- outputClassLists.putIfAbsent(
- compiler.deferredLoadTask.outputUnitForElement(element),
- () => new List<ClassElement>())
- .add(element);
- }
- }
- }
-
- void computeNeededStatics() {
- bool isStaticFunction(Element element) =>
- !element.isInstanceMember && !element.isField;
-
- Iterable<Element> elements =
- backend.generatedCode.keys.where(isStaticFunction);
-
- for (Element element in Elements.sortedByPosition(elements)) {
- List<Element> list = outputStaticLists.putIfAbsent(
- compiler.deferredLoadTask.outputUnitForElement(element),
- () => new List<Element>());
- list.add(element);
- }
- }
-
- void computeNeededStaticNonFinalFields() {
- JavaScriptConstantCompiler handler = backend.constants;
- Iterable<VariableElement> staticNonFinalFields = handler
- .getStaticNonFinalFieldsForEmission()
- .where(compiler.codegenWorld.allReferencedStaticFields.contains);
- for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
- List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent(
- compiler.deferredLoadTask.outputUnitForElement(element),
- () => new List<VariableElement>());
- list.add(element);
- }
- }
-
- void computeNeededLibraries() {
- void addSurroundingLibraryToSet(Element element) {
- OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element);
- LibraryElement library = element.library;
- outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>())
- .add(library);
- }
-
- backend.generatedCode.keys.forEach(addSurroundingLibraryToSet);
- neededClasses.forEach(addSurroundingLibraryToSet);
- }
-
- void computeAllNeededEntities() {
+ Set<ClassElement> _finalizeRti() {
// Compute the required type checks to know which classes need a
// 'is$' method.
typeTestRegistry.computeRequiredTypeChecks();
// Compute the classes needed by RTI.
- Set<ClassElement> rtiClasses = typeTestRegistry.computeRtiNeededClasses();
-
- computeNeededDeclarations(rtiClasses);
- computeNeededConstants();
- computeNeededStatics();
- computeNeededStaticNonFinalFields();
- computeNeededLibraries();
+ return typeTestRegistry.computeRtiNeededClasses();
}
int assembleProgram() {
return measure(() {
emitter.invalidateCaches();
- computeAllNeededEntities();
-
- ProgramBuilder programBuilder = new ProgramBuilder(compiler, namer, this);
- return emitter.emitProgram(programBuilder);
+ Set<ClassElement> rtiNeededClasses = _finalizeRti();
+ ProgramBuilder programBuilder = new ProgramBuilder(
+ compiler, namer, this, emitter, oldEmitter, rtiNeededClasses);
+ int size = emitter.emitProgram(programBuilder);
+ // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
+ neededClasses = programBuilder.collector.neededClasses;
+ return size;
});
}
}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698