Chromium Code Reviews| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 KernelNamedTypeBuilder, | 76 KernelNamedTypeBuilder, |
| 77 KernelProcedureBuilder, | 77 KernelProcedureBuilder, |
| 78 LibraryBuilder, | 78 LibraryBuilder, |
| 79 MemberBuilder, | 79 MemberBuilder, |
| 80 NamedTypeBuilder, | 80 NamedTypeBuilder, |
| 81 TypeBuilder, | 81 TypeBuilder, |
| 82 TypeDeclarationBuilder, | 82 TypeDeclarationBuilder, |
| 83 TypeVariableBuilder; | 83 TypeVariableBuilder; |
| 84 | 84 |
| 85 import 'verifier.dart' show verifyProgram; | 85 import 'verifier.dart' show verifyProgram; |
| 86 import 'kernel_outline_shaker.dart' | |
| 87 show trimProgram, RetainedDataBuilder, RootsMarker; | |
| 86 | 88 |
| 87 class KernelTarget extends TargetImplementation { | 89 class KernelTarget extends TargetImplementation { |
| 88 /// The [FileSystem] which should be used to access files. | 90 /// The [FileSystem] which should be used to access files. |
| 89 final FileSystem fileSystem; | 91 final FileSystem fileSystem; |
| 90 | 92 |
| 91 final bool strongMode; | 93 final bool strongMode; |
| 92 | 94 |
| 93 final DillTarget dillTarget; | 95 final DillTarget dillTarget; |
| 94 | 96 |
| 95 /// Shared with [CompilerContext]. | 97 /// Shared with [CompilerContext]. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 cls.implementedTypes.clear(); | 209 cls.implementedTypes.clear(); |
| 208 cls.supertype = null; | 210 cls.supertype = null; |
| 209 cls.mixedInType = null; | 211 cls.mixedInType = null; |
| 210 builder.supertype = new KernelNamedTypeBuilder("Object", null, | 212 builder.supertype = new KernelNamedTypeBuilder("Object", null, |
| 211 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri)) | 213 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri)) |
| 212 ..builder = objectClassBuilder; | 214 ..builder = objectClassBuilder; |
| 213 builder.interfaces = null; | 215 builder.interfaces = null; |
| 214 builder.mixedInType = null; | 216 builder.mixedInType = null; |
| 215 } | 217 } |
| 216 | 218 |
| 217 void handleInputError(InputError error, {bool isFullProgram}) { | 219 void handleInputError(InputError error, |
| 220 {bool isFullProgram, bool trimDependencies: false}) { | |
| 218 if (error != null) { | 221 if (error != null) { |
| 219 String message = error.format(); | 222 String message = error.format(); |
| 220 print(message); | 223 print(message); |
| 221 errors.add(message); | 224 errors.add(message); |
| 222 } | 225 } |
| 223 _program = erroneousProgram(isFullProgram); | 226 _program = erroneousProgram(isFullProgram); |
| 227 if (trimDependencies) { | |
| 228 trimDependenciesHelper(_program, dillTarget.loader.libraries); | |
| 229 } | |
| 224 } | 230 } |
| 225 | 231 |
| 226 @override | 232 @override |
| 227 Future<Program> buildOutlines({CanonicalName nameRoot}) async { | 233 Future<Program> buildOutlines({CanonicalName nameRoot}) async { |
| 228 if (loader.first == null) return null; | 234 if (loader.first == null) return null; |
| 229 try { | 235 try { |
| 230 loader.createTypeInferenceEngine(); | 236 loader.createTypeInferenceEngine(); |
| 231 await loader.buildOutlines(); | 237 await loader.buildOutlines(); |
| 232 loader.coreLibrary | 238 loader.coreLibrary |
| 233 .becomeCoreLibrary(const DynamicType(), const VoidType()); | 239 .becomeCoreLibrary(const DynamicType(), const VoidType()); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 249 loader.prepareInitializerInference(); | 255 loader.prepareInitializerInference(); |
| 250 loader.performInitializerInference(); | 256 loader.performInitializerInference(); |
| 251 } on InputError catch (e) { | 257 } on InputError catch (e) { |
| 252 handleInputError(e, isFullProgram: false); | 258 handleInputError(e, isFullProgram: false); |
| 253 } catch (e, s) { | 259 } catch (e, s) { |
| 254 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 260 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
| 255 } | 261 } |
| 256 return _program; | 262 return _program; |
| 257 } | 263 } |
| 258 | 264 |
| 265 /// Build the kernel representation of the program loaded by this target. The | |
| 266 /// program will contain full bodies for the code loaded from sources, and | |
| 267 /// only references to the code loaded by the [DillTarget], which may or may | |
| 268 /// not include method bodies (depending on what was loaded into that target, | |
| 269 /// an outline or a full kernel program). | |
| 270 /// | |
| 271 /// When [trimDependencies] is true, this also runs a tree-shaker that deletes | |
| 272 /// anything from the [DillTarget] that is not needed for the source program, | |
| 273 /// this includes function bodies and types that are not reachable. | |
| 274 /// | |
| 275 /// If [verify], run the default kernel verification on the resulting program. | |
| 259 @override | 276 @override |
| 260 Future<Program> buildProgram({bool verify: false}) async { | 277 Future<Program> buildProgram( |
| 278 {bool verify: false, bool trimDependencies: false}) async { | |
| 261 if (loader.first == null) return null; | 279 if (loader.first == null) return null; |
| 262 if (errors.isNotEmpty) { | 280 if (errors.isNotEmpty) { |
| 263 handleInputError(null, isFullProgram: true); | 281 handleInputError(null, |
| 282 isFullProgram: true, trimDependencies: trimDependencies); | |
| 264 return _program; | 283 return _program; |
| 265 } | 284 } |
| 266 try { | 285 try { |
| 267 await loader.buildBodies(); | 286 await loader.buildBodies(); |
| 287 _program = link(new List<Library>.from(loader.libraries), | |
| 288 trimDependencies: trimDependencies); | |
| 268 loader.finishStaticInvocations(); | 289 loader.finishStaticInvocations(); |
| 269 finishAllConstructors(); | 290 finishAllConstructors(); |
| 270 loader.finishNativeMethods(); | 291 loader.finishNativeMethods(); |
| 271 runBuildTransformations(); | 292 runBuildTransformations(); |
| 272 | 293 |
| 273 if (verify) this.verify(); | 294 if (verify) this.verify(); |
| 274 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); | 295 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); |
| 275 if (errors.isNotEmpty) { | 296 if (errors.isNotEmpty) { |
| 276 handleInputError(null, isFullProgram: true); | 297 handleInputError(null, |
| 298 isFullProgram: true, trimDependencies: trimDependencies); | |
| 277 } | 299 } |
| 278 } on InputError catch (e) { | 300 } on InputError catch (e) { |
| 279 handleInputError(e, isFullProgram: true); | 301 handleInputError(e, |
| 302 isFullProgram: true, trimDependencies: trimDependencies); | |
| 280 } catch (e, s) { | 303 } catch (e, s) { |
| 281 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 304 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
| 282 } | 305 } |
| 283 return _program; | 306 return _program; |
| 284 } | 307 } |
| 285 | 308 |
| 286 Future writeDepsFile(Uri output, Uri depsFile, | 309 Future writeDepsFile(Uri output, Uri depsFile, |
| 287 {Iterable<Uri> extraDependencies}) async { | 310 {Iterable<Uri> extraDependencies}) async { |
| 288 String toRelativeFilePath(Uri uri) { | 311 String toRelativeFilePath(Uri uri) { |
| 289 // Ninja expects to find file names relative to the current working | 312 // Ninja expects to find file names relative to the current working |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 library.addBuilder(mainBuilder.name, mainBuilder, -1); | 366 library.addBuilder(mainBuilder.name, mainBuilder, -1); |
| 344 mainBuilder.body = new ExpressionStatement( | 367 mainBuilder.body = new ExpressionStatement( |
| 345 new Throw(new StringLiteral("${errors.join('\n')}"))); | 368 new Throw(new StringLiteral("${errors.join('\n')}"))); |
| 346 } | 369 } |
| 347 library.build(loader.coreLibrary); | 370 library.build(loader.coreLibrary); |
| 348 return link(<Library>[library.library]); | 371 return link(<Library>[library.library]); |
| 349 } | 372 } |
| 350 | 373 |
| 351 /// Creates a program by combining [libraries] with the libraries of | 374 /// Creates a program by combining [libraries] with the libraries of |
| 352 /// `dillTarget.loader.program`. | 375 /// `dillTarget.loader.program`. |
| 353 Program link(List<Library> libraries, {CanonicalName nameRoot}) { | 376 Program link(List<Library> libraries, |
| 377 {CanonicalName nameRoot, bool trimDependencies: false}) { | |
| 354 Map<String, Source> uriToSource = | 378 Map<String, Source> uriToSource = |
| 355 new Map<String, Source>.from(this.uriToSource); | 379 new Map<String, Source>.from(this.uriToSource); |
| 356 | 380 |
| 357 libraries.addAll(dillTarget.loader.libraries); | 381 List<Library> extraLibraries = dillTarget.loader.libraries; |
| 382 libraries.addAll(extraLibraries); | |
| 358 // TODO(scheglov) Should we also somehow update `uriToSource`? | 383 // TODO(scheglov) Should we also somehow update `uriToSource`? |
| 359 // uriToSource.addAll(binary.uriToSource); | 384 // uriToSource.addAll(binary.uriToSource); |
| 360 | 385 |
| 361 // TODO(ahe): Remove this line. Kernel seems to generate a default line map | 386 // TODO(ahe): Remove this line. Kernel seems to generate a default line map |
| 362 // that used when there's no fileUri on an element. Instead, ensure all | 387 // that used when there's no fileUri on an element. Instead, ensure all |
| 363 // elements have a fileUri. | 388 // elements have a fileUri. |
| 364 uriToSource[""] = new Source(<int>[0], const <int>[]); | 389 uriToSource[""] = new Source(<int>[0], const <int>[]); |
| 365 Program program = new Program( | 390 Program program = new Program( |
| 366 nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource); | 391 nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource); |
| 367 if (loader.first != null) { | 392 if (loader.first != null) { |
| 393 // TODO(sigmund): do only for full program | |
| 368 Builder builder = loader.first.lookup("main", -1, null); | 394 Builder builder = loader.first.lookup("main", -1, null); |
| 369 if (builder is KernelProcedureBuilder) { | 395 if (builder is KernelProcedureBuilder) { |
| 370 program.mainMethod = builder.procedure; | 396 program.mainMethod = builder.procedure; |
| 371 } | 397 } |
| 372 } | 398 } |
| 373 if (errors.isEmpty || dillTarget.isLoaded) { | 399 if (trimDependencies) { |
| 374 runLinkTransformations(program); | 400 trimDependenciesHelper(program, extraLibraries); |
| 375 } | 401 } |
| 402 | |
| 376 ticker.logMs("Linked program"); | 403 ticker.logMs("Linked program"); |
| 377 return program; | 404 return program; |
| 378 } | 405 } |
| 379 | 406 |
| 380 void installDefaultSupertypes() { | 407 void installDefaultSupertypes() { |
| 381 Class objectClass = this.objectClass; | 408 Class objectClass = this.objectClass; |
| 382 loader.builders.forEach((Uri uri, LibraryBuilder library) { | 409 loader.builders.forEach((Uri uri, LibraryBuilder library) { |
| 383 library.forEach((String name, Builder builder) { | 410 library.forEach((String name, Builder builder) { |
| 384 if (builder is SourceClassBuilder) { | 411 if (builder is SourceClassBuilder) { |
| 385 Class cls = builder.target; | 412 Class cls = builder.target; |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 }); | 658 }); |
| 632 } | 659 } |
| 633 | 660 |
| 634 /// Run all transformations that are needed when building a program for the | 661 /// Run all transformations that are needed when building a program for the |
| 635 /// first time. | 662 /// first time. |
| 636 void runBuildTransformations() { | 663 void runBuildTransformations() { |
| 637 transformMixinApplications(); | 664 transformMixinApplications(); |
| 638 otherTransformations(); | 665 otherTransformations(); |
| 639 } | 666 } |
| 640 | 667 |
| 641 /// Run all transformations that are needed when linking a program. | |
| 642 void runLinkTransformations(Program program) {} | |
| 643 | |
| 644 void transformMixinApplications() { | 668 void transformMixinApplications() { |
| 645 new MixinFullResolution().transform(_program); | 669 new MixinFullResolution().transform(_program); |
| 646 ticker.logMs("Transformed mixin applications"); | 670 ticker.logMs("Transformed mixin applications"); |
| 647 } | 671 } |
| 648 | 672 |
| 649 void otherTransformations() { | 673 void otherTransformations() { |
| 650 // TODO(ahe): Don't generate type variables in the first place. | 674 // TODO(ahe): Don't generate type variables in the first place. |
| 651 if (!strongMode) { | 675 if (!strongMode) { |
| 652 _program.accept(new Erasure()); | 676 _program.accept(new Erasure()); |
| 653 ticker.logMs("Erased type variables in generic methods"); | 677 ticker.logMs("Erased type variables in generic methods"); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 674 } | 698 } |
| 675 for (Constructor constructor in superclass.constructors) { | 699 for (Constructor constructor in superclass.constructors) { |
| 676 if (constructor.name.name.isEmpty) { | 700 if (constructor.name.name.isEmpty) { |
| 677 return constructor.function.requiredParameterCount == 0 | 701 return constructor.function.requiredParameterCount == 0 |
| 678 ? constructor | 702 ? constructor |
| 679 : null; | 703 : null; |
| 680 } | 704 } |
| 681 } | 705 } |
| 682 return null; | 706 return null; |
| 683 } | 707 } |
| 708 | |
| 709 trimDependenciesHelper(Program program, List<Library> extraLibraries) { | |
|
scheglov
2017/05/19 17:19:05
1. Helper is usually an object, YMMV though.
2. Co
Siggi Cherem (dart-lang)
2017/05/19 19:43:30
indeed - I very commonly use "helper" for helper f
| |
| 710 var excluded = extraLibraries.map((lib) => lib.importUri).toSet(); | |
| 711 var isIncluded = (Uri uri) => !excluded.contains(uri); | |
| 712 var data = new RetainedDataBuilder(); | |
| 713 // TODO(sigmund): replace this step with data that is directly computed from | |
| 714 // the builders: we should know the tree-shaking roots without having to do a | |
| 715 // second visit over the tree. | |
| 716 new RootsMarker(data).run(program, isIncluded); | |
| 717 trimProgram(program, data, isIncluded); | |
| 718 } | |
| OLD | NEW |