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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_emitter/program_builder.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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: sdk/lib/_internal/compiler/implementation/js_emitter/program_builder.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/program_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/program_builder.dart
deleted file mode 100644
index 3738340a2d96e84ee7983bc1ee65e63d613ea701..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/program_builder.dart
+++ /dev/null
@@ -1,405 +0,0 @@
-// Copyright (c) 2014, 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.
-
-library dart2js.js_emitter.program_builder;
-
-import 'model.dart';
-import '../common.dart';
-import '../js/js.dart' as js;
-
-import '../js_backend/js_backend.dart' show
- Namer,
- JavaScriptBackend,
- JavaScriptConstantCompiler;
-
-import '../closure.dart' show ClosureFieldElement;
-
-import 'js_emitter.dart' as emitterTask show
- CodeEmitterTask,
- Emitter,
- InterceptorStubGenerator;
-
-import '../universe/universe.dart' show Universe;
-import '../deferred_load.dart' show DeferredLoadTask, OutputUnit;
-
-part 'registry.dart';
-
-class ProgramBuilder {
- final Compiler _compiler;
- final Namer namer;
- final emitterTask.CodeEmitterTask _task;
-
- final Registry _registry;
-
- ProgramBuilder(Compiler compiler,
- this.namer,
- this._task)
- : this._compiler = compiler,
- this._registry = new Registry(compiler);
-
- JavaScriptBackend get backend => _compiler.backend;
- Universe get universe => _compiler.codegenWorld;
-
- /// Mapping from [ClassElement] to constructed [Class]. We need this to
- /// update the superclass in the [Class].
- final Map<ClassElement, Class> _classes = <ClassElement, Class>{};
-
- /// Mapping from [OutputUnit] to constructed [Output]. We need this to
- /// generate the deferredLoadingMap (to know which hunks to load).
- final Map<OutputUnit, Output> _outputs = <OutputUnit, Output>{};
-
- /// Mapping from [ConstantValue] to constructed [Constant]. We need this to
- /// update field-initializers to point to the ConstantModel.
- final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
-
- Program buildProgram() {
- _task.outputClassLists.forEach(_registry.registerElements);
- _task.outputStaticLists.forEach(_registry.registerElements);
- _task.outputConstantLists.forEach(_registerConstants);
-
- // TODO(kasperl): There's code that implicitly needs access to the special
- // $ holder so we have to register that. Can we track if we have to?
- _registry.registerHolder(r'$');
-
- MainOutput mainOutput = _buildMainOutput(_registry.mainFragment);
- Iterable<Output> deferredOutputs = _registry.deferredFragments
- .map((fragment) => _buildDeferredOutput(mainOutput, fragment));
-
- List<Output> outputs = new List<Output>(_registry.fragmentCount);
- outputs[0] = mainOutput;
- outputs.setAll(1, deferredOutputs);
-
- Program result =
- new Program(outputs, _task.outputContainsConstantList, _buildLoadMap());
-
- // Resolve the superclass references after we've processed all the classes.
- _classes.forEach((ClassElement element, Class c) {
- if (element.superclass != null) {
- c.setSuperclass(_classes[element.superclass]);
- }
- });
-
- _markEagerClasses();
-
- return result;
- }
-
- void _markEagerClasses() {
- _markEagerInterceptorClasses();
- }
-
- /// Builds a map from loadId to outputs-to-load.
- Map<String, List<Output>> _buildLoadMap() {
- List<OutputUnit> convertHunks(List<OutputUnit> hunks) {
- return hunks.map((OutputUnit unit) => _outputs[unit])
- .toList(growable: false);
- }
-
- Map<String, List<Output>> loadMap = <String, List<Output>>{};
- _compiler.deferredLoadTask.hunksToLoad
- .forEach((String loadId, List<OutputUnit> outputUnits) {
- loadMap[loadId] = outputUnits
- .map((OutputUnit unit) => _outputs[unit])
- .toList(growable: false);
- });
- return loadMap;
- }
-
- MainOutput _buildMainOutput(Fragment fragment) {
- // Construct the main output from the libraries and the registered holders.
- MainOutput result = new MainOutput(
- "", // The empty string is the name for the main output file.
- namer.elementAccess(_compiler.mainFunction),
- _buildLibraries(fragment),
- _buildStaticNonFinalFields(fragment),
- _buildStaticLazilyInitializedFields(fragment),
- _buildConstants(fragment),
- _registry.holders.toList(growable: false));
- _outputs[fragment.outputUnit] = result;
- return result;
- }
-
- /// Returns a name composed of the main output file name and [name].
- String _outputFileName(String name) {
- assert(name != "");
- String outPath = _compiler.outputUri != null
- ? _compiler.outputUri.path
- : "out";
- String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
- return "${outName}_$name";
- }
-
- DeferredOutput _buildDeferredOutput(MainOutput mainOutput,
- Fragment fragment) {
- DeferredOutput result = new DeferredOutput(
- _outputFileName(fragment.name), fragment.name,
- mainOutput,
- _buildLibraries(fragment),
- _buildStaticNonFinalFields(fragment),
- _buildStaticLazilyInitializedFields(fragment),
- _buildConstants(fragment));
- _outputs[fragment.outputUnit] = result;
- return result;
- }
-
- List<Constant> _buildConstants(Fragment fragment) {
- List<ConstantValue> constantValues =
- _task.outputConstantLists[fragment.outputUnit];
- if (constantValues == null) return const <Constant>[];
- return constantValues.map((ConstantValue value) => _constants[value])
- .toList(growable: false);
- }
-
- List<StaticField> _buildStaticNonFinalFields(Fragment fragment) {
- // TODO(floitsch): handle static non-final fields correctly with deferred
- // libraries.
- if (fragment != _registry.mainFragment) return const <StaticField>[];
- Iterable<VariableElement> staticNonFinalFields =
- backend.constants.getStaticNonFinalFieldsForEmission();
- return Elements.sortedByPosition(staticNonFinalFields)
- .map(_buildStaticField)
- .toList(growable: false);
- }
-
- StaticField _buildStaticField(Element element) {
- JavaScriptConstantCompiler handler = backend.constants;
- ConstantValue initialValue = handler.getInitialValueFor(element).value;
- js.Expression code = _task.emitter.constantReference(initialValue);
- String name = namer.getNameOfGlobalField(element);
- bool isFinal = false;
- bool isLazy = false;
- return new StaticField(name, _registry.registerHolder(r'$'), code,
- isFinal, isLazy);
- }
-
- List<StaticField> _buildStaticLazilyInitializedFields(Fragment fragment) {
- // TODO(floitsch): lazy fields should just be in their respective
- // libraries.
- if (fragment != _registry.mainFragment) return const <StaticField>[];
-
- JavaScriptConstantCompiler handler = backend.constants;
- List<VariableElement> lazyFields =
- handler.getLazilyInitializedFieldsForEmission();
- return Elements.sortedByPosition(lazyFields)
- .map(_buildLazyField)
- .where((field) => field != null) // Happens when the field was unused.
- .toList(growable: false);
- }
-
- StaticField _buildLazyField(Element element) {
- JavaScriptConstantCompiler handler = backend.constants;
- js.Expression code = backend.generatedCode[element];
- // The code is null if we ended up not needing the lazily
- // initialized field after all because of constant folding
- // before code generation.
- if (code == null) return null;
-
- String name = namer.getNameOfGlobalField(element);
- bool isFinal = element.isFinal;
- bool isLazy = true;
- return new StaticField(name, _registry.registerHolder(r'$'), code,
- isFinal, isLazy);
- }
-
- List<Library> _buildLibraries(Fragment fragment) {
- List<Library> libraries = new List<Library>(fragment.length);
- int count = 0;
- fragment.forEach((LibraryElement library, List<Element> elements) {
- libraries[count++] = _buildLibrary(library, elements);
- });
- return libraries;
- }
-
- // Note that a library-element may have multiple [Library]s, if it is split
- // into multiple output units.
- Library _buildLibrary(LibraryElement library, List<Element> elements) {
- String uri = library.canonicalUri.toString();
-
- List<StaticMethod> statics = elements
- .where((e) => e is FunctionElement).map(_buildStaticMethod).toList();
-
- statics.addAll(elements
- .where((e) => e is FunctionElement)
- .where((e) => universe.staticFunctionsNeedingGetter.contains(e))
- .map(_buildStaticMethodTearOff));
-
- if (library == backend.interceptorsLibrary) {
- statics.addAll(_generateGetInterceptorMethods());
- statics.addAll(_generateOneShotInterceptors());
- }
-
- List<Class> classes = elements
- .where((e) => e is ClassElement)
- .map(_buildClass)
- .toList(growable: false);
-
- return new Library(uri, statics, classes);
- }
-
- Class _buildClass(ClassElement element) {
- bool isInstantiated =
- _compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
-
- List<Method> methods = [];
- List<InstanceField> fields = [];
-
- void visitMember(ClassElement enclosing, Element member) {
- assert(invariant(element, member.isDeclaration));
- assert(invariant(element, element == enclosing));
-
- if (Elements.isNonAbstractInstanceMember(member)) {
- js.Expression code = backend.generatedCode[member];
- // TODO(kasperl): Figure out under which conditions code is null.
- if (code != null) methods.add(_buildMethod(member, code));
- } else if (member.isField && !member.isStatic) {
- fields.add(_buildInstanceField(member, enclosing));
- }
- }
-
- ClassElement implementation = element.implementation;
- if (isInstantiated) {
- implementation.forEachMember(visitMember, includeBackendMembers: true);
- }
- String name = namer.getNameOfClass(element);
- String holderName = namer.globalObjectFor(element);
- Holder holder = _registry.registerHolder(holderName);
- Class result = new Class(name, holder, methods, fields);
- _classes[element] = result;
- return result;
- }
-
- Method _buildMethod(FunctionElement element, js.Expression code) {
- String name = namer.getNameOfInstanceMember(element);
- return new Method(name, code);
- }
-
- // The getInterceptor methods directly access the prototype of classes.
- // We must evaluate these classes eagerly so that the prototype is
- // accessible.
- void _markEagerInterceptorClasses() {
- Map<String, Set<ClassElement>> specializedGetInterceptors =
- backend.specializedGetInterceptors;
- for (Set<ClassElement> classes in specializedGetInterceptors.values) {
- for (ClassElement element in classes) {
- Class cls = _classes[element];
- if (cls != null) cls.isEager = true;
- }
- }
- }
-
- Iterable<StaticMethod> _generateGetInterceptorMethods() {
- emitterTask.InterceptorStubGenerator stubGenerator =
- new emitterTask.InterceptorStubGenerator(_compiler, namer, backend);
-
- String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
- Holder holder = _registry.registerHolder(holderName);
-
- Map<String, Set<ClassElement>> specializedGetInterceptors =
- backend.specializedGetInterceptors;
- List<String> names = specializedGetInterceptors.keys.toList()..sort();
- return names.map((String name) {
- Set<ClassElement> classes = specializedGetInterceptors[name];
- js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
- return new StaticMethod(name, holder, code);
- });
- }
-
- bool _fieldNeedsGetter(VariableElement field) {
- assert(field.isField);
- if (_fieldAccessNeverThrows(field)) return false;
- return backend.shouldRetainGetter(field)
- || _compiler.codegenWorld.hasInvokedGetter(field, _compiler.world);
- }
-
- bool _fieldNeedsSetter(VariableElement field) {
- assert(field.isField);
- if (_fieldAccessNeverThrows(field)) return false;
- return (!field.isFinal && !field.isConst)
- && (backend.shouldRetainSetter(field)
- || _compiler.codegenWorld.hasInvokedSetter(field, _compiler.world));
- }
-
- // We never access a field in a closure (a captured variable) without knowing
- // that it is there. Therefore we don't need to use a getter (that will throw
- // if the getter method is missing), but can always access the field directly.
- bool _fieldAccessNeverThrows(VariableElement field) {
- return field is ClosureFieldElement;
- }
-
- InstanceField _buildInstanceField(VariableElement field,
- ClassElement holder) {
- assert(invariant(field, field.isDeclaration));
- String name = namer.fieldPropertyName(field);
-
- int getterFlags = 0;
- if (_fieldNeedsGetter(field)) {
- bool isIntercepted = backend.fieldHasInterceptedGetter(field);
- if (isIntercepted) {
- getterFlags += 2;
- if (backend.isInterceptorClass(holder)) {
- getterFlags += 1;
- }
- } else {
- getterFlags = 1;
- }
- }
-
- int setterFlags = 0;
- if (_fieldNeedsSetter(field)) {
- bool isIntercepted = backend.fieldHasInterceptedSetter(field);
- if (isIntercepted) {
- setterFlags += 2;
- if (backend.isInterceptorClass(holder)) {
- setterFlags += 1;
- }
- } else {
- setterFlags = 1;
- }
- }
-
- return new InstanceField(name, getterFlags, setterFlags);
- }
-
- Iterable<StaticMethod> _generateOneShotInterceptors() {
- emitterTask.InterceptorStubGenerator stubGenerator =
- new emitterTask.InterceptorStubGenerator(_compiler, namer, backend);
-
- String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
- Holder holder = _registry.registerHolder(holderName);
-
- List<String> names = backend.oneShotInterceptors.keys.toList()..sort();
- return names.map((String name) {
- js.Expression code = stubGenerator.generateOneShotInterceptor(name);
- return new StaticMethod(name, holder, code);
- });
- }
-
- StaticMethod _buildStaticMethod(FunctionElement element) {
- String name = namer.getNameOfMember(element);
- String holder = namer.globalObjectFor(element);
- js.Expression code = backend.generatedCode[element];
- return new StaticMethod(name, _registry.registerHolder(holder), code);
- }
-
- StaticMethod _buildStaticMethodTearOff(FunctionElement element) {
- String name = namer.getStaticClosureName(element);
- String holder = namer.globalObjectFor(element);
- // TODO(kasperl): This clearly doesn't work yet.
- js.Expression code = js.string("<<unimplemented>>");
- return new StaticMethod(name, _registry.registerHolder(holder), code);
- }
-
- void _registerConstants(OutputUnit outputUnit,
- List<ConstantValue> constantValues) {
- if (constantValues == null) return;
- for (ConstantValue constantValue in constantValues) {
- assert(!_constants.containsKey(constantValue));
- String name = namer.constantName(constantValue);
- String constantObject = namer.globalObjectForConstant(constantValue);
- Holder holder = _registry.registerHolder(constantObject);
- Constant constant = new Constant(name, holder, constantValue);
- _constants[constantValue] = constant;
- };
- }
-}

Powered by Google App Engine
This is Rietveld 408576698