| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 fasta.kernel_target; | 5 library fasta.kernel_target; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import 'dart:io' show File; | 9 import 'dart:io' show File; |
| 10 | 10 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 final FileSystem fileSystem; | 90 final FileSystem fileSystem; |
| 91 | 91 |
| 92 final bool strongMode; | 92 final bool strongMode; |
| 93 | 93 |
| 94 final DillTarget dillTarget; | 94 final DillTarget dillTarget; |
| 95 | 95 |
| 96 /// Shared with [CompilerContext]. | 96 /// Shared with [CompilerContext]. |
| 97 final Map<String, Source> uriToSource; | 97 final Map<String, Source> uriToSource; |
| 98 | 98 |
| 99 SourceLoader<Library> loader; | 99 SourceLoader<Library> loader; |
| 100 Program _program; | 100 |
| 101 Program program; |
| 101 | 102 |
| 102 final List<String> errors = <String>[]; | 103 final List<String> errors = <String>[]; |
| 103 | 104 |
| 104 final TypeBuilder dynamicType = | 105 final TypeBuilder dynamicType = |
| 105 new KernelNamedTypeBuilder("dynamic", null, -1, null); | 106 new KernelNamedTypeBuilder("dynamic", null, -1, null); |
| 106 | 107 |
| 107 KernelTarget(this.fileSystem, DillTarget dillTarget, | 108 KernelTarget(this.fileSystem, DillTarget dillTarget, |
| 108 TranslateUri uriTranslator, this.strongMode, | 109 TranslateUri uriTranslator, this.strongMode, |
| 109 [Map<String, Source> uriToSource]) | 110 [Map<String, Source> uriToSource]) |
| 110 : dillTarget = dillTarget, | 111 : dillTarget = dillTarget, |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 builder.mixedInType = null; | 216 builder.mixedInType = null; |
| 216 } | 217 } |
| 217 | 218 |
| 218 void handleInputError(InputError error, | 219 void handleInputError(InputError error, |
| 219 {bool isFullProgram, bool trimDependencies: false}) { | 220 {bool isFullProgram, bool trimDependencies: false}) { |
| 220 if (error != null) { | 221 if (error != null) { |
| 221 String message = error.format(); | 222 String message = error.format(); |
| 222 print(message); | 223 print(message); |
| 223 errors.add(message); | 224 errors.add(message); |
| 224 } | 225 } |
| 225 _program = erroneousProgram(isFullProgram); | 226 program = erroneousProgram(isFullProgram); |
| 226 } | 227 } |
| 227 | 228 |
| 228 @override | 229 @override |
| 229 Future<Program> buildOutlines({CanonicalName nameRoot}) async { | 230 Future<Program> buildOutlines({CanonicalName nameRoot}) async { |
| 230 if (loader.first == null) return null; | 231 if (loader.first == null) return null; |
| 231 try { | 232 try { |
| 232 loader.createTypeInferenceEngine(); | 233 loader.createTypeInferenceEngine(); |
| 233 await loader.buildOutlines(); | 234 await loader.buildOutlines(); |
| 234 loader.coreLibrary | 235 loader.coreLibrary |
| 235 .becomeCoreLibrary(const DynamicType(), const VoidType()); | 236 .becomeCoreLibrary(const DynamicType(), const VoidType()); |
| 236 dynamicType.bind(loader.coreLibrary["dynamic"]); | 237 dynamicType.bind(loader.coreLibrary["dynamic"]); |
| 237 loader.resolveParts(); | 238 loader.resolveParts(); |
| 238 loader.computeLibraryScopes(); | 239 loader.computeLibraryScopes(); |
| 239 loader.resolveTypes(); | 240 loader.resolveTypes(); |
| 240 loader.checkSemantics(); | 241 loader.checkSemantics(); |
| 241 loader.buildProgram(); | 242 loader.buildProgram(); |
| 242 List<SourceClassBuilder> sourceClasses = collectAllSourceClasses(); | 243 List<SourceClassBuilder> sourceClasses = collectAllSourceClasses(); |
| 243 installDefaultSupertypes(); | 244 installDefaultSupertypes(); |
| 244 installDefaultConstructors(sourceClasses); | 245 installDefaultConstructors(sourceClasses); |
| 245 loader.resolveConstructors(); | 246 loader.resolveConstructors(); |
| 246 loader.finishTypeVariables(objectClassBuilder); | 247 loader.finishTypeVariables(objectClassBuilder); |
| 247 _program = | 248 program = |
| 248 link(new List<Library>.from(loader.libraries), nameRoot: nameRoot); | 249 link(new List<Library>.from(loader.libraries), nameRoot: nameRoot); |
| 249 loader.computeHierarchy(_program); | 250 loader.computeHierarchy(program); |
| 250 loader.checkOverrides(sourceClasses); | 251 loader.checkOverrides(sourceClasses); |
| 251 loader.prepareInitializerInference(); | 252 loader.prepareInitializerInference(); |
| 252 loader.performInitializerInference(); | 253 loader.performInitializerInference(); |
| 253 } on InputError catch (e) { | 254 } on InputError catch (e) { |
| 254 handleInputError(e, isFullProgram: false); | 255 handleInputError(e, isFullProgram: false); |
| 255 } catch (e, s) { | 256 } catch (e, s) { |
| 256 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 257 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
| 257 } | 258 } |
| 258 return _program; | 259 return program; |
| 259 } | 260 } |
| 260 | 261 |
| 261 /// Build the kernel representation of the program loaded by this target. The | 262 /// Build the kernel representation of the program loaded by this target. The |
| 262 /// program will contain full bodies for the code loaded from sources, and | 263 /// program will contain full bodies for the code loaded from sources, and |
| 263 /// only references to the code loaded by the [DillTarget], which may or may | 264 /// only references to the code loaded by the [DillTarget], which may or may |
| 264 /// not include method bodies (depending on what was loaded into that target, | 265 /// not include method bodies (depending on what was loaded into that target, |
| 265 /// an outline or a full kernel program). | 266 /// an outline or a full kernel program). |
| 266 /// | 267 /// |
| 267 /// When [trimDependencies] is true, this also runs a tree-shaker that deletes | 268 /// When [trimDependencies] is true, this also runs a tree-shaker that deletes |
| 268 /// anything from the [DillTarget] that is not needed for the source program, | 269 /// anything from the [DillTarget] that is not needed for the source program, |
| 269 /// this includes function bodies and types that are not reachable. This | 270 /// this includes function bodies and types that are not reachable. This |
| 270 /// option is currently in flux and the internal implementation might change. | 271 /// option is currently in flux and the internal implementation might change. |
| 271 /// See [trimDependenciesInProgram] for more details. | 272 /// See [trimDependenciesInProgram] for more details. |
| 272 /// | 273 /// |
| 273 /// If [verify], run the default kernel verification on the resulting program. | 274 /// If [verify], run the default kernel verification on the resulting program. |
| 274 @override | 275 @override |
| 275 Future<Program> buildProgram( | 276 Future<Program> buildProgram( |
| 276 {bool verify: false, bool trimDependencies: false}) async { | 277 {bool verify: false, bool trimDependencies: false}) async { |
| 277 if (loader.first == null) return null; | 278 if (loader.first == null) return null; |
| 278 if (errors.isNotEmpty) { | 279 if (errors.isNotEmpty) { |
| 279 handleInputError(null, | 280 handleInputError(null, |
| 280 isFullProgram: true, trimDependencies: trimDependencies); | 281 isFullProgram: true, trimDependencies: trimDependencies); |
| 281 return _program; | 282 return program; |
| 282 } | 283 } |
| 283 | 284 |
| 284 try { | 285 try { |
| 285 await loader.buildBodies(); | 286 await loader.buildBodies(); |
| 286 loader.finishStaticInvocations(); | 287 loader.finishStaticInvocations(); |
| 287 finishAllConstructors(); | 288 finishAllConstructors(); |
| 288 loader.finishNativeMethods(); | 289 loader.finishNativeMethods(); |
| 289 runBuildTransformations(); | 290 runBuildTransformations(); |
| 290 | 291 |
| 291 if (verify) this.verify(); | 292 if (verify) this.verify(); |
| 292 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); | 293 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); |
| 293 if (errors.isNotEmpty) { | 294 if (errors.isNotEmpty) { |
| 294 handleInputError(null, | 295 handleInputError(null, |
| 295 isFullProgram: true, trimDependencies: trimDependencies); | 296 isFullProgram: true, trimDependencies: trimDependencies); |
| 296 } | 297 } |
| 297 } on InputError catch (e) { | 298 } on InputError catch (e) { |
| 298 handleInputError(e, | 299 handleInputError(e, |
| 299 isFullProgram: true, trimDependencies: trimDependencies); | 300 isFullProgram: true, trimDependencies: trimDependencies); |
| 300 } catch (e, s) { | 301 } catch (e, s) { |
| 301 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 302 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
| 302 } | 303 } |
| 303 if (trimDependencies) trimDependenciesInProgram(); | 304 if (trimDependencies) trimDependenciesInProgram(); |
| 304 return _program; | 305 return program; |
| 305 } | 306 } |
| 306 | 307 |
| 307 Future writeDepsFile(Uri output, Uri depsFile, | 308 Future writeDepsFile(Uri output, Uri depsFile, |
| 308 {Iterable<Uri> extraDependencies}) async { | 309 {Iterable<Uri> extraDependencies}) async { |
| 309 String toRelativeFilePath(Uri uri) { | 310 String toRelativeFilePath(Uri uri) { |
| 310 // Ninja expects to find file names relative to the current working | 311 // Ninja expects to find file names relative to the current working |
| 311 // directory. We've tried making them relative to the deps file, but that | 312 // directory. We've tried making them relative to the deps file, but that |
| 312 // doesn't work for downstream projects. Making them absolute also | 313 // doesn't work for downstream projects. Making them absolute also |
| 313 // doesn't work. | 314 // doesn't work. |
| 314 // | 315 // |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 transformMixinApplications(); | 658 transformMixinApplications(); |
| 658 otherTransformations(); | 659 otherTransformations(); |
| 659 } | 660 } |
| 660 | 661 |
| 661 void transformMixinApplications() { | 662 void transformMixinApplications() { |
| 662 mix.transformLibraries(backendTarget, loader.coreTypes, loader.libraries); | 663 mix.transformLibraries(backendTarget, loader.coreTypes, loader.libraries); |
| 663 ticker.logMs("Transformed mixin applications"); | 664 ticker.logMs("Transformed mixin applications"); |
| 664 } | 665 } |
| 665 | 666 |
| 666 void otherTransformations() { | 667 void otherTransformations() { |
| 667 // TODO(ahe): Don't generate type variables in the first place. | |
| 668 if (!strongMode) { | 668 if (!strongMode) { |
| 669 _program.accept(new Erasure()); | 669 // TODO(ahe): Don't generate type variables in the first place. |
| 670 program.accept(new Erasure()); |
| 670 ticker.logMs("Erased type variables in generic methods"); | 671 ticker.logMs("Erased type variables in generic methods"); |
| 671 } | 672 } |
| 672 // TODO(kmillikin): Make this run on a per-method basis. | 673 if (errors.isEmpty && loader.collectCompileTimeErrors().isEmpty) { |
| 673 transformAsync.transformLibraries(loader.coreTypes, loader.libraries); | 674 // TODO(kmillikin): Make this run on a per-method basis. |
| 675 transformAsync.transformLibraries(loader.coreTypes, loader.libraries); |
| 676 } |
| 674 ticker.logMs("Transformed async methods"); | 677 ticker.logMs("Transformed async methods"); |
| 675 } | 678 } |
| 676 | 679 |
| 677 void verify() { | 680 void verify() { |
| 678 var verifyErrors = verifyProgram(_program); | 681 var verifyErrors = verifyProgram(program); |
| 679 errors.addAll(verifyErrors.map((error) => '$error')); | 682 errors.addAll(verifyErrors.map((error) => '$error')); |
| 680 ticker.logMs("Verified program"); | 683 ticker.logMs("Verified program"); |
| 681 } | 684 } |
| 682 | 685 |
| 683 /// Tree-shakes most code from the [dillTarget] by visiting all other | 686 /// Tree-shakes most code from the [dillTarget] by visiting all other |
| 684 /// libraries in [_program] and marking the APIs from the [dillTarget] | 687 /// libraries in [program] and marking the APIs from the [dillTarget] |
| 685 /// libraries that are in use. | 688 /// libraries that are in use. |
| 686 /// | 689 /// |
| 687 /// Note: while it's likely we'll do some trimming of programs for modular | 690 /// Note: while it's likely we'll do some trimming of programs for modular |
| 688 /// compilation, it is unclear at this time when and how that trimming should | 691 /// compilation, it is unclear at this time when and how that trimming should |
| 689 /// happen. We are likely going to remove the extra visitor my either marking | 692 /// happen. We are likely going to remove the extra visitor my either marking |
| 690 /// things while code is built, or by handling tree-shaking after the fact | 693 /// things while code is built, or by handling tree-shaking after the fact |
| 691 /// (e.g. during serialization). | 694 /// (e.g. during serialization). |
| 692 trimDependenciesInProgram() { | 695 trimDependenciesInProgram() { |
| 693 var toShake = | 696 var toShake = |
| 694 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); | 697 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); |
| 695 var isIncluded = (Uri uri) => !toShake.contains(uri); | 698 var isIncluded = (Uri uri) => !toShake.contains(uri); |
| 696 var data = new RetainedDataBuilder(); | 699 var data = new RetainedDataBuilder(); |
| 697 // TODO(sigmund): replace this step with data that is directly computed from | 700 // TODO(sigmund): replace this step with data that is directly computed from |
| 698 // the builders: we should know the tree-shaking roots without having to do | 701 // the builders: we should know the tree-shaking roots without having to do |
| 699 // a second visit over the tree. | 702 // a second visit over the tree. |
| 700 new RootsMarker(loader.coreTypes, data).run(_program, isIncluded); | 703 new RootsMarker(loader.coreTypes, data).run(program, isIncluded); |
| 701 trimProgram(_program, data, isIncluded); | 704 trimProgram(program, data, isIncluded); |
| 702 } | 705 } |
| 703 | 706 |
| 704 /// Return `true` if the given [library] was built by this [KernelTarget] | 707 /// Return `true` if the given [library] was built by this [KernelTarget] |
| 705 /// from sources, and not loaded from a [DillTarget]. | 708 /// from sources, and not loaded from a [DillTarget]. |
| 706 bool isSourceLibrary(Library library) { | 709 bool isSourceLibrary(Library library) { |
| 707 return loader.libraries.contains(library); | 710 return loader.libraries.contains(library); |
| 708 } | 711 } |
| 709 } | 712 } |
| 710 | 713 |
| 711 /// Looks for a constructor call that matches `super()` from a constructor in | 714 /// Looks for a constructor call that matches `super()` from a constructor in |
| 712 /// [cls]. Such a constructor may have optional arguments, but no required | 715 /// [cls]. Such a constructor may have optional arguments, but no required |
| 713 /// arguments. | 716 /// arguments. |
| 714 Constructor defaultSuperConstructor(Class cls) { | 717 Constructor defaultSuperConstructor(Class cls) { |
| 715 Class superclass = cls.superclass; | 718 Class superclass = cls.superclass; |
| 716 while (superclass != null && superclass.isMixinApplication) { | 719 while (superclass != null && superclass.isMixinApplication) { |
| 717 superclass = superclass.superclass; | 720 superclass = superclass.superclass; |
| 718 } | 721 } |
| 719 for (Constructor constructor in superclass.constructors) { | 722 for (Constructor constructor in superclass.constructors) { |
| 720 if (constructor.name.name.isEmpty) { | 723 if (constructor.name.name.isEmpty) { |
| 721 return constructor.function.requiredParameterCount == 0 | 724 return constructor.function.requiredParameterCount == 0 |
| 722 ? constructor | 725 ? constructor |
| 723 : null; | 726 : null; |
| 724 } | 727 } |
| 725 } | 728 } |
| 726 return null; | 729 return null; |
| 727 } | 730 } |
| OLD | NEW |