| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.js_emitter.full_emitter; | 5 library dart2js.js_emitter.full_emitter; |
| 6 | 6 |
| 7 import 'dart:collection' show HashMap; | 7 import 'dart:collection' show HashMap; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 import '../../elements/elements.dart' | 21 import '../../elements/elements.dart' |
| 22 show | 22 show |
| 23 ClassElement, | 23 ClassElement, |
| 24 Element, | 24 Element, |
| 25 Elements, | 25 Elements, |
| 26 FieldElement, | 26 FieldElement, |
| 27 FunctionElement, | 27 FunctionElement, |
| 28 FunctionSignature, | 28 FunctionSignature, |
| 29 LibraryElement, | 29 LibraryElement, |
| 30 MethodElement, | 30 MethodElement, |
| 31 TypedefElement, | 31 TypedefElement; |
| 32 VariableElement; | |
| 33 import '../../elements/entities.dart'; | 32 import '../../elements/entities.dart'; |
| 34 import '../../hash/sha1.dart' show Hasher; | 33 import '../../hash/sha1.dart' show Hasher; |
| 35 import '../../io/code_output.dart'; | 34 import '../../io/code_output.dart'; |
| 36 import '../../io/location_provider.dart' show LocationCollector; | 35 import '../../io/location_provider.dart' show LocationCollector; |
| 37 import '../../io/source_map_builder.dart' show SourceMapBuilder; | 36 import '../../io/source_map_builder.dart' show SourceMapBuilder; |
| 38 import '../../js/js.dart' as jsAst; | 37 import '../../js/js.dart' as jsAst; |
| 39 import '../../js/js.dart' show js; | 38 import '../../js/js.dart' show js; |
| 40 import '../../js_backend/js_backend.dart' | 39 import '../../js_backend/js_backend.dart' |
| 41 show | 40 show |
| 42 ConstantEmitter, | 41 ConstantEmitter, |
| 43 JavaScriptBackend, | 42 JavaScriptBackend, |
| 44 JavaScriptConstantCompiler, | 43 JavaScriptConstantCompiler, |
| 45 Namer, | 44 Namer, |
| 46 SetterName, | 45 SetterName, |
| 47 TypeVariableCodegenAnalysis; | 46 TypeVariableCodegenAnalysis; |
| 48 import '../../universe/call_structure.dart' show CallStructure; | 47 import '../../universe/call_structure.dart' show CallStructure; |
| 49 import '../../universe/selector.dart' show Selector; | 48 import '../../universe/selector.dart' show Selector; |
| 50 import '../../universe/world_builder.dart' show CodegenWorldBuilder; | 49 import '../../universe/world_builder.dart' show CodegenWorldBuilder; |
| 51 import '../../util/uri_extras.dart' show relativize; | 50 import '../../util/uri_extras.dart' show relativize; |
| 52 import '../../world.dart' show ClosedWorld; | 51 import '../../world.dart' show ClosedWorld; |
| 53 import '../constant_ordering.dart' show deepCompareConstants; | 52 import '../constant_ordering.dart' show deepCompareConstants; |
| 54 import '../headers.dart'; | 53 import '../headers.dart'; |
| 55 import '../js_emitter.dart' hide Emitter, EmitterFactory; | 54 import '../js_emitter.dart' hide Emitter, EmitterFactory; |
| 56 import '../js_emitter.dart' as js_emitter show Emitter, EmitterFactory; | 55 import '../js_emitter.dart' as js_emitter show Emitter, EmitterFactory; |
| 57 import '../model.dart'; | 56 import '../model.dart'; |
| 58 import '../program_builder/program_builder.dart'; | 57 import '../program_builder/program_builder.dart'; |
| 58 import '../sorter.dart'; |
| 59 | 59 |
| 60 import 'class_builder.dart'; | 60 import 'class_builder.dart'; |
| 61 import 'class_emitter.dart'; | 61 import 'class_emitter.dart'; |
| 62 import 'container_builder.dart'; | 62 import 'container_builder.dart'; |
| 63 import 'interceptor_emitter.dart'; | 63 import 'interceptor_emitter.dart'; |
| 64 import 'nsm_emitter.dart'; | 64 import 'nsm_emitter.dart'; |
| 65 | 65 |
| 66 export 'class_builder.dart'; | 66 export 'class_builder.dart'; |
| 67 export 'class_emitter.dart'; | 67 export 'class_emitter.dart'; |
| 68 export 'container_builder.dart'; | 68 export 'container_builder.dart'; |
| 69 export 'interceptor_emitter.dart'; | 69 export 'interceptor_emitter.dart'; |
| 70 export 'nsm_emitter.dart'; | 70 export 'nsm_emitter.dart'; |
| 71 | 71 |
| 72 part 'code_emitter_helper.dart'; | 72 part 'code_emitter_helper.dart'; |
| 73 part 'declarations.dart'; | 73 part 'declarations.dart'; |
| 74 part 'deferred_output_unit_hash.dart'; | 74 part 'deferred_output_unit_hash.dart'; |
| 75 part 'setup_program_builder.dart'; | 75 part 'setup_program_builder.dart'; |
| 76 | 76 |
| 77 class EmitterFactory implements js_emitter.EmitterFactory { | 77 class EmitterFactory implements js_emitter.EmitterFactory { |
| 78 final bool generateSourceMap; | 78 final bool generateSourceMap; |
| 79 | 79 |
| 80 EmitterFactory({this.generateSourceMap}); | 80 EmitterFactory({this.generateSourceMap}); |
| 81 | 81 |
| 82 @override | 82 @override |
| 83 bool get supportsReflection => true; | 83 bool get supportsReflection => true; |
| 84 | 84 |
| 85 @override | 85 @override |
| 86 Emitter createEmitter( | 86 Emitter createEmitter( |
| 87 CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) { | 87 CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) { |
| 88 return new Emitter( | 88 return new Emitter(task.compiler, namer, closedWorld, generateSourceMap, |
| 89 task.compiler, namer, closedWorld, generateSourceMap, task); | 89 task, task.sorter); |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 class Emitter implements js_emitter.Emitter { | 93 class Emitter implements js_emitter.Emitter { |
| 94 final Compiler compiler; | 94 final Compiler compiler; |
| 95 final CodeEmitterTask task; | 95 final CodeEmitterTask task; |
| 96 | 96 |
| 97 // The following fields will be set to copies of the program-builder's | 97 // The following fields will be set to copies of the program-builder's |
| 98 // collector. | 98 // collector. |
| 99 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists; | 99 Map<OutputUnit, List<FieldEntity>> outputStaticNonFinalFieldLists; |
| 100 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists; | 100 Map<OutputUnit, Set<LibraryEntity>> outputLibraryLists; |
| 101 List<TypedefElement> typedefsNeededForReflection; | 101 List<TypedefElement> typedefsNeededForReflection; |
| 102 | 102 |
| 103 final ContainerBuilder containerBuilder = new ContainerBuilder(); | 103 final ContainerBuilder containerBuilder = new ContainerBuilder(); |
| 104 final ClassEmitter classEmitter; | 104 final ClassEmitter classEmitter; |
| 105 final NsmEmitter nsmEmitter; | 105 final NsmEmitter nsmEmitter; |
| 106 final InterceptorEmitter interceptorEmitter; | 106 final InterceptorEmitter interceptorEmitter; |
| 107 final Sorter _sorter; |
| 107 | 108 |
| 108 // TODO(johnniwinther): Wrap these fields in a caching strategy. | 109 // TODO(johnniwinther): Wrap these fields in a caching strategy. |
| 109 final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[]; | 110 final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[]; |
| 110 | 111 |
| 111 bool needsClassSupport = false; | 112 bool needsClassSupport = false; |
| 112 bool needsMixinSupport = false; | 113 bool needsMixinSupport = false; |
| 113 bool needsLazyInitializer = false; | 114 bool needsLazyInitializer = false; |
| 114 | 115 |
| 115 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info", | 116 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info", |
| 116 /// that is, some function was needed for reflection, had stubs, or had a | 117 /// that is, some function was needed for reflection, had stubs, or had a |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 * See [getElementDescriptor]. | 165 * See [getElementDescriptor]. |
| 165 */ | 166 */ |
| 166 // TODO(ahe): Generate statics with their class, and store only libraries in | 167 // TODO(ahe): Generate statics with their class, and store only libraries in |
| 167 // this map. | 168 // this map. |
| 168 final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors = | 169 final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors = |
| 169 new Map<Fragment, Map<Element, ClassBuilder>>(); | 170 new Map<Fragment, Map<Element, ClassBuilder>>(); |
| 170 | 171 |
| 171 final bool generateSourceMap; | 172 final bool generateSourceMap; |
| 172 | 173 |
| 173 Emitter(Compiler compiler, Namer namer, ClosedWorld closedWorld, | 174 Emitter(Compiler compiler, Namer namer, ClosedWorld closedWorld, |
| 174 this.generateSourceMap, this.task) | 175 this.generateSourceMap, this.task, this._sorter) |
| 175 : this.compiler = compiler, | 176 : this.compiler = compiler, |
| 176 this.namer = namer, | 177 this.namer = namer, |
| 177 classEmitter = new ClassEmitter(closedWorld), | 178 classEmitter = new ClassEmitter(closedWorld), |
| 178 interceptorEmitter = new InterceptorEmitter(closedWorld), | 179 interceptorEmitter = new InterceptorEmitter(closedWorld), |
| 179 nsmEmitter = new NsmEmitter(closedWorld) { | 180 nsmEmitter = new NsmEmitter(closedWorld) { |
| 180 constantEmitter = new ConstantEmitter( | 181 constantEmitter = new ConstantEmitter( |
| 181 compiler, namer, this.constantReference, constantListGenerator); | 182 compiler, namer, this.constantReference, constantListGenerator); |
| 182 containerBuilder.emitter = this; | 183 containerBuilder.emitter = this; |
| 183 classEmitter.emitter = this; | 184 classEmitter.emitter = this; |
| 184 nsmEmitter.emitter = this; | 185 nsmEmitter.emitter = this; |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 containerBuilder.addMemberMethod(method, builder); | 591 containerBuilder.addMemberMethod(method, builder); |
| 591 getStaticMethodDescriptor(element, fragment) | 592 getStaticMethodDescriptor(element, fragment) |
| 592 .properties | 593 .properties |
| 593 .addAll(builder.properties); | 594 .addAll(builder.properties); |
| 594 } | 595 } |
| 595 } | 596 } |
| 596 | 597 |
| 597 jsAst.Statement buildStaticNonFinalFieldInitializations( | 598 jsAst.Statement buildStaticNonFinalFieldInitializations( |
| 598 OutputUnit outputUnit) { | 599 OutputUnit outputUnit) { |
| 599 jsAst.Statement buildInitialization( | 600 jsAst.Statement buildInitialization( |
| 600 Element element, jsAst.Expression initialValue) { | 601 FieldElement element, jsAst.Expression initialValue) { |
| 601 return js.statement('${namer.staticStateHolder}.# = #', | 602 return js.statement('${namer.staticStateHolder}.# = #', |
| 602 [namer.globalPropertyName(element), initialValue]); | 603 [namer.globalPropertyName(element), initialValue]); |
| 603 } | 604 } |
| 604 | 605 |
| 605 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 606 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
| 606 JavaScriptConstantCompiler handler = backend.constants; | 607 JavaScriptConstantCompiler handler = backend.constants; |
| 607 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 608 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
| 608 | 609 |
| 609 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; | 610 Iterable<FieldEntity> fields = outputStaticNonFinalFieldLists[outputUnit]; |
| 610 // If the outputUnit does not contain any static non-final fields, then | 611 // If the outputUnit does not contain any static non-final fields, then |
| 611 // [fields] is `null`. | 612 // [fields] is `null`. |
| 612 if (fields != null) { | 613 if (fields != null) { |
| 613 for (FieldElement element in fields) { | 614 for (FieldElement element in fields) { |
| 614 reporter.withCurrentElement(element, () { | 615 reporter.withCurrentElement(element, () { |
| 615 ConstantValue constant = handler.getConstantValue(element.constant); | 616 ConstantValue constant = handler.getConstantValue(element.constant); |
| 616 parts.add(buildInitialization(element, constantReference(constant))); | 617 parts.add(buildInitialization(element, constantReference(constant))); |
| 617 }); | 618 }); |
| 618 } | 619 } |
| 619 } | 620 } |
| 620 | 621 |
| 621 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { | 622 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { |
| 622 // In the main output-unit we output a stub initializer for deferred | 623 // In the main output-unit we output a stub initializer for deferred |
| 623 // variables, so that `isolateProperties` stays a fast object. | 624 // variables, so that `isolateProperties` stays a fast object. |
| 624 outputStaticNonFinalFieldLists.forEach( | 625 outputStaticNonFinalFieldLists |
| 625 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 626 .forEach((OutputUnit fieldsOutputUnit, Iterable<FieldEntity> fields) { |
| 626 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 627 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
| 627 for (Element element in fields) { | 628 for (FieldEntity element in fields) { |
| 628 reporter.withCurrentElement(element, () { | 629 reporter.withCurrentElement(element, () { |
| 629 parts.add(buildInitialization(element, jsAst.number(0))); | 630 parts.add(buildInitialization(element, jsAst.number(0))); |
| 630 }); | 631 }); |
| 631 } | 632 } |
| 632 }); | 633 }); |
| 633 } | 634 } |
| 634 | 635 |
| 635 return new jsAst.Block(parts); | 636 return new jsAst.Block(parts); |
| 636 } | 637 } |
| 637 | 638 |
| (...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 if (isProgramSplit) { | 1341 if (isProgramSplit) { |
| 1341 statements.add(buildDeferredHeader()); | 1342 statements.add(buildDeferredHeader()); |
| 1342 } | 1343 } |
| 1343 | 1344 |
| 1344 // Collect the AST for the decriptors | 1345 // Collect the AST for the decriptors |
| 1345 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; | 1346 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; |
| 1346 if (descriptors == null) descriptors = const {}; | 1347 if (descriptors == null) descriptors = const {}; |
| 1347 | 1348 |
| 1348 checkEverythingEmitted(descriptors.keys); | 1349 checkEverythingEmitted(descriptors.keys); |
| 1349 | 1350 |
| 1350 Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit]; | 1351 Iterable<LibraryEntity> libraries = outputLibraryLists[mainOutputUnit]; |
| 1351 if (libraries == null) libraries = <LibraryElement>[]; | 1352 if (libraries == null) libraries = <LibraryElement>[]; |
| 1352 | 1353 |
| 1353 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1354 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
| 1354 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1355 for (LibraryEntity library in _sorter.sortLibraries(libraries)) { |
| 1355 parts.add(generateLibraryDescriptor(library, mainFragment)); | 1356 parts.add(generateLibraryDescriptor(library, mainFragment)); |
| 1356 descriptors.remove(library); | 1357 descriptors.remove(library); |
| 1357 } | 1358 } |
| 1358 | 1359 |
| 1359 if (descriptors.isNotEmpty) { | 1360 if (descriptors.isNotEmpty) { |
| 1360 List<Element> remainingLibraries = | 1361 List<Element> remainingLibraries = |
| 1361 descriptors.keys.where((Element e) => e is LibraryElement).toList(); | 1362 descriptors.keys.where((Element e) => e is LibraryElement).toList(); |
| 1362 | 1363 |
| 1363 // The remaining descriptors are only accessible through reflection. | 1364 // The remaining descriptors are only accessible through reflection. |
| 1364 // The program builder does not collect libraries that only | 1365 // The program builder does not collect libraries that only |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1561 Program program) { | 1562 Program program) { |
| 1562 Map<OutputUnit, jsAst.Expression> outputs = | 1563 Map<OutputUnit, jsAst.Expression> outputs = |
| 1563 new Map<OutputUnit, jsAst.Expression>(); | 1564 new Map<OutputUnit, jsAst.Expression>(); |
| 1564 | 1565 |
| 1565 for (Fragment fragment in program.deferredFragments) { | 1566 for (Fragment fragment in program.deferredFragments) { |
| 1566 OutputUnit outputUnit = fragment.outputUnit; | 1567 OutputUnit outputUnit = fragment.outputUnit; |
| 1567 | 1568 |
| 1568 Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment]; | 1569 Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment]; |
| 1569 | 1570 |
| 1570 if (descriptors != null && descriptors.isNotEmpty) { | 1571 if (descriptors != null && descriptors.isNotEmpty) { |
| 1571 Iterable<LibraryElement> libraries = outputLibraryLists[outputUnit]; | 1572 Iterable<LibraryEntity> libraries = outputLibraryLists[outputUnit]; |
| 1572 if (libraries == null) libraries = []; | 1573 if (libraries == null) libraries = []; |
| 1573 | 1574 |
| 1574 // TODO(johnniwinther): Avoid creating [CodeBuffer]s. | 1575 // TODO(johnniwinther): Avoid creating [CodeBuffer]s. |
| 1575 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1576 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
| 1576 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1577 for (LibraryEntity library in _sorter.sortLibraries(libraries)) { |
| 1577 parts.add(generateLibraryDescriptor(library, fragment)); | 1578 parts.add(generateLibraryDescriptor(library, fragment)); |
| 1578 descriptors.remove(library); | 1579 descriptors.remove(library); |
| 1579 } | 1580 } |
| 1580 | 1581 |
| 1581 outputs[outputUnit] = new jsAst.ArrayInitializer(parts); | 1582 outputs[outputUnit] = new jsAst.ArrayInitializer(parts); |
| 1582 } | 1583 } |
| 1583 } | 1584 } |
| 1584 | 1585 |
| 1585 return outputs; | 1586 return outputs; |
| 1586 } | 1587 } |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1927 // data. | 1928 // data. |
| 1928 mapping["_comment"] = "This mapping shows which compiled `.js` files are " | 1929 mapping["_comment"] = "This mapping shows which compiled `.js` files are " |
| 1929 "needed for a given deferred library import."; | 1930 "needed for a given deferred library import."; |
| 1930 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); | 1931 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); |
| 1931 compiler.outputProvider( | 1932 compiler.outputProvider( |
| 1932 compiler.options.deferredMapUri.path, '', OutputType.info) | 1933 compiler.options.deferredMapUri.path, '', OutputType.info) |
| 1933 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) | 1934 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) |
| 1934 ..close(); | 1935 ..close(); |
| 1935 } | 1936 } |
| 1936 } | 1937 } |
| OLD | NEW |