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, IOSink; | 9 import 'dart:io' show File, IOSink; |
10 | 10 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 KernelNamedTypeBuilder, | 79 KernelNamedTypeBuilder, |
80 KernelProcedureBuilder, | 80 KernelProcedureBuilder, |
81 LibraryBuilder, | 81 LibraryBuilder, |
82 MemberBuilder, | 82 MemberBuilder, |
83 NamedTypeBuilder, | 83 NamedTypeBuilder, |
84 TypeBuilder, | 84 TypeBuilder, |
85 TypeDeclarationBuilder, | 85 TypeDeclarationBuilder, |
86 TypeVariableBuilder; | 86 TypeVariableBuilder; |
87 | 87 |
88 import 'verifier.dart' show verifyProgram; | 88 import 'verifier.dart' show verifyProgram; |
| 89 import 'kernel_outline_shaker.dart' show trimProgram; |
89 | 90 |
90 class KernelTarget extends TargetImplementation { | 91 class KernelTarget extends TargetImplementation { |
91 /// The [FileSystem] which should be used to access files. | 92 /// The [FileSystem] which should be used to access files. |
92 final FileSystem fileSystem; | 93 final FileSystem fileSystem; |
93 | 94 |
94 final bool strongMode; | 95 final bool strongMode; |
95 | 96 |
96 final DillTarget dillTarget; | 97 final DillTarget dillTarget; |
97 | 98 |
98 /// Shared with [CompilerContext]. | 99 /// Shared with [CompilerContext]. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 cls.supertype = null; | 212 cls.supertype = null; |
212 cls.mixedInType = null; | 213 cls.mixedInType = null; |
213 builder.supertype = new KernelNamedTypeBuilder("Object", null, | 214 builder.supertype = new KernelNamedTypeBuilder("Object", null, |
214 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri)) | 215 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri)) |
215 ..builder = objectClassBuilder; | 216 ..builder = objectClassBuilder; |
216 builder.interfaces = null; | 217 builder.interfaces = null; |
217 builder.mixedInType = null; | 218 builder.mixedInType = null; |
218 } | 219 } |
219 | 220 |
220 Future<Program> handleInputError(Uri uri, InputError error, | 221 Future<Program> handleInputError(Uri uri, InputError error, |
221 {bool isFullProgram}) { | 222 {bool isFullProgram, bool trimDependencies: false}) { |
222 if (error != null) { | 223 if (error != null) { |
223 String message = error.format(); | 224 String message = error.format(); |
224 print(message); | 225 print(message); |
225 errors.add(message); | 226 errors.add(message); |
226 } | 227 } |
227 _program = erroneousProgram(isFullProgram); | 228 _program = erroneousProgram(isFullProgram); |
| 229 if (trimDependencies) { |
| 230 var excluded = |
| 231 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); |
| 232 trimProgram(_program, (uri) => !excluded.contains(uri)); |
| 233 } |
228 return uri == null | 234 return uri == null |
229 ? new Future<Program>.value(_program) | 235 ? new Future<Program>.value(_program) |
230 : writeLinkedProgram(uri, _program, isFullProgram: isFullProgram); | 236 : writeLinkedProgram(uri, _program, isFullProgram: isFullProgram); |
231 } | 237 } |
232 | 238 |
233 @override | 239 @override |
234 Future<Program> buildOutlines({CanonicalName nameRoot}) async { | 240 Future<Program> buildOutlines({CanonicalName nameRoot}) async { |
235 if (loader.first == null) return null; | 241 if (loader.first == null) return null; |
236 try { | 242 try { |
237 loader.createTypeInferenceEngine(); | 243 loader.createTypeInferenceEngine(); |
238 await loader.buildOutlines(); | 244 await loader.buildOutlines(); |
239 loader.coreLibrary | 245 loader.coreLibrary |
240 .becomeCoreLibrary(const DynamicType(), const VoidType()); | 246 .becomeCoreLibrary(const DynamicType(), const VoidType()); |
241 dynamicType.bind(loader.coreLibrary["dynamic"]); | 247 dynamicType.bind(loader.coreLibrary["dynamic"]); |
242 loader.resolveParts(); | 248 loader.resolveParts(); |
243 loader.computeLibraryScopes(); | 249 loader.computeLibraryScopes(); |
244 loader.resolveTypes(); | 250 loader.resolveTypes(); |
245 loader.checkSemantics(); | 251 loader.checkSemantics(); |
246 loader.buildProgram(); | 252 loader.buildProgram(); |
247 List<SourceClassBuilder> sourceClasses = collectAllSourceClasses(); | 253 List<SourceClassBuilder> sourceClasses = collectAllSourceClasses(); |
248 installDefaultSupertypes(); | 254 installDefaultSupertypes(); |
249 installDefaultConstructors(sourceClasses); | 255 installDefaultConstructors(sourceClasses); |
250 loader.resolveConstructors(); | 256 loader.resolveConstructors(); |
251 loader.finishTypeVariables(objectClassBuilder); | 257 loader.finishTypeVariables(objectClassBuilder); |
252 _program = | 258 var outline = |
253 link(new List<Library>.from(loader.libraries), nameRoot: nameRoot); | 259 link(new List<Library>.from(loader.libraries), nameRoot: nameRoot); |
254 loader.computeHierarchy(_program); | 260 loader.computeHierarchy(outline); |
255 loader.checkOverrides(sourceClasses); | 261 loader.checkOverrides(sourceClasses); |
256 loader.prepareInitializerInference(); | 262 loader.prepareInitializerInference(); |
257 loader.performInitializerInference(); | 263 loader.performInitializerInference(); |
258 return _program; | 264 return _program = outline; |
259 } on InputError catch (e) { | 265 } on InputError catch (e) { |
260 return handleInputError(null, e, isFullProgram: false); | 266 return handleInputError(null, e, isFullProgram: false); |
261 } catch (e, s) { | 267 } catch (e, s) { |
262 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 268 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
263 } | 269 } |
264 } | 270 } |
265 | 271 |
266 Future<Null> writeOutline(Uri uri) async { | 272 Future<Null> writeOutline(Uri uri) async { |
267 try { | 273 try { |
268 if (uri != null) { | 274 if (uri != null) { |
269 await writeLinkedProgram(uri, _program, isFullProgram: false); | 275 await writeLinkedProgram(uri, _program, isFullProgram: false); |
270 } | 276 } |
271 } on InputError catch (e) { | 277 } on InputError catch (e) { |
272 handleInputError(uri, e, isFullProgram: false); | 278 handleInputError(uri, e, isFullProgram: false, trimDependencies: false); |
273 } catch (e, s) { | 279 } catch (e, s) { |
274 reportCrash(e, s, loader?.currentUriForCrashReporting); | 280 reportCrash(e, s, loader?.currentUriForCrashReporting); |
275 } | 281 } |
276 } | 282 } |
277 | 283 |
278 @override | 284 @override |
279 Future<Program> buildProgram({bool verify: false}) async { | 285 Future<Program> buildProgram( |
| 286 {bool verify: false, bool trimDependencies: false}) async { |
280 if (loader.first == null) return null; | 287 if (loader.first == null) return null; |
281 if (errors.isNotEmpty) { | 288 if (errors.isNotEmpty) { |
282 return handleInputError(null, null, isFullProgram: true); | 289 return handleInputError(null, null, |
| 290 isFullProgram: true, trimDependencies: trimDependencies); |
283 } | 291 } |
284 try { | 292 try { |
285 await loader.buildBodies(); | 293 await loader.buildBodies(); |
| 294 _program = link(new List<Library>.from(loader.libraries), |
| 295 trimDependencies: trimDependencies); |
286 loader.finishStaticInvocations(); | 296 loader.finishStaticInvocations(); |
287 finishAllConstructors(); | 297 finishAllConstructors(); |
288 loader.finishNativeMethods(); | 298 loader.finishNativeMethods(); |
289 runBuildTransformations(); | 299 runBuildTransformations(); |
290 | 300 |
291 if (verify) this.verify(); | 301 if (verify) this.verify(); |
292 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); | 302 errors.addAll(loader.collectCompileTimeErrors().map((e) => e.format())); |
293 if (errors.isNotEmpty) { | 303 if (errors.isNotEmpty) { |
294 return handleInputError(null, null, isFullProgram: true); | 304 return handleInputError(null, null, |
| 305 isFullProgram: true, trimDependencies: trimDependencies); |
295 } | 306 } |
296 return _program; | 307 return _program; |
297 } on InputError catch (e) { | 308 } on InputError catch (e) { |
298 return handleInputError(null, e, isFullProgram: true); | 309 return handleInputError(null, e, |
| 310 isFullProgram: true, trimDependencies: trimDependencies); |
299 } catch (e, s) { | 311 } catch (e, s) { |
300 return reportCrash(e, s, loader?.currentUriForCrashReporting); | 312 return reportCrash(e, s, loader?.currentUriForCrashReporting); |
301 } | 313 } |
302 } | 314 } |
303 | 315 |
304 Future<Null> writeProgram(Uri uri) async { | 316 Future<Null> writeProgram(Uri uri) async { |
305 if (loader.first == null) return null; | 317 if (loader.first == null) return null; |
306 try { | 318 try { |
307 await writeLinkedProgram(uri, _program, isFullProgram: true); | 319 await writeLinkedProgram(uri, _program, isFullProgram: true); |
308 } on InputError catch (e) { | 320 } on InputError catch (e) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 library.addBuilder(mainBuilder.name, mainBuilder, -1); | 395 library.addBuilder(mainBuilder.name, mainBuilder, -1); |
384 mainBuilder.body = new ExpressionStatement( | 396 mainBuilder.body = new ExpressionStatement( |
385 new Throw(new StringLiteral("${errors.join('\n')}"))); | 397 new Throw(new StringLiteral("${errors.join('\n')}"))); |
386 } | 398 } |
387 library.build(loader.coreLibrary); | 399 library.build(loader.coreLibrary); |
388 return link(<Library>[library.library]); | 400 return link(<Library>[library.library]); |
389 } | 401 } |
390 | 402 |
391 /// Creates a program by combining [libraries] with the libraries of | 403 /// Creates a program by combining [libraries] with the libraries of |
392 /// `dillTarget.loader.program`. | 404 /// `dillTarget.loader.program`. |
393 Program link(List<Library> libraries, {CanonicalName nameRoot}) { | 405 Program link(List<Library> libraries, |
| 406 {CanonicalName nameRoot, trimDependencies: false}) { |
394 Map<String, Source> uriToSource = | 407 Map<String, Source> uriToSource = |
395 new Map<String, Source>.from(this.uriToSource); | 408 new Map<String, Source>.from(this.uriToSource); |
396 | 409 |
397 libraries.addAll(dillTarget.loader.libraries); | 410 List<Library> extraLibraries = dillTarget.loader.libraries; |
| 411 libraries.addAll(extraLibraries); |
398 // TODO(scheglov) Should we also somehow update `uriToSource`? | 412 // TODO(scheglov) Should we also somehow update `uriToSource`? |
399 // uriToSource.addAll(binary.uriToSource); | 413 // uriToSource.addAll(binary.uriToSource); |
400 | 414 |
401 // TODO(ahe): Remove this line. Kernel seems to generate a default line map | 415 // TODO(ahe): Remove this line. Kernel seems to generate a default line map |
402 // that used when there's no fileUri on an element. Instead, ensure all | 416 // that used when there's no fileUri on an element. Instead, ensure all |
403 // elements have a fileUri. | 417 // elements have a fileUri. |
404 uriToSource[""] = new Source(<int>[0], const <int>[]); | 418 uriToSource[""] = new Source(<int>[0], const <int>[]); |
405 Program program = new Program( | 419 Program program = new Program( |
406 nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource); | 420 nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource); |
407 if (loader.first != null) { | 421 if (loader.first != null) { |
| 422 // TODO(sigmund): do only for full program |
408 Builder builder = loader.first.lookup("main", -1, null); | 423 Builder builder = loader.first.lookup("main", -1, null); |
409 if (builder is KernelProcedureBuilder) { | 424 if (builder is KernelProcedureBuilder) { |
410 program.mainMethod = builder.procedure; | 425 program.mainMethod = builder.procedure; |
411 } | 426 } |
412 } | 427 } |
413 if (errors.isEmpty || dillTarget.isLoaded) { | 428 if (trimDependencies) { |
414 runLinkTransformations(program); | 429 var excluded = extraLibraries.map((lib) => lib.importUri).toSet(); |
| 430 trimProgram(program, (uri) => !excluded.contains(uri)); |
415 } | 431 } |
| 432 |
416 ticker.logMs("Linked program"); | 433 ticker.logMs("Linked program"); |
417 return program; | 434 return program; |
418 } | 435 } |
419 | 436 |
420 Future<Program> writeLinkedProgram(Uri uri, Program program, | 437 Future<Program> writeLinkedProgram(Uri uri, Program program, |
421 {bool isFullProgram}) async { | 438 {bool isFullProgram}) async { |
422 File output = new File.fromUri(uri); | 439 File output = new File.fromUri(uri); |
423 IOSink sink = output.openWrite(); | 440 IOSink sink = output.openWrite(); |
424 try { | 441 try { |
425 new BinaryPrinter(sink).writeProgramFile(program); | 442 new BinaryPrinter(sink).writeProgramFile(program); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 }); | 706 }); |
690 } | 707 } |
691 | 708 |
692 /// Run all transformations that are needed when building a program for the | 709 /// Run all transformations that are needed when building a program for the |
693 /// first time. | 710 /// first time. |
694 void runBuildTransformations() { | 711 void runBuildTransformations() { |
695 transformMixinApplications(); | 712 transformMixinApplications(); |
696 otherTransformations(); | 713 otherTransformations(); |
697 } | 714 } |
698 | 715 |
699 /// Run all transformations that are needed when linking a program. | |
700 void runLinkTransformations(Program program) {} | |
701 | |
702 void transformMixinApplications() { | 716 void transformMixinApplications() { |
703 new MixinFullResolution().transform(_program); | 717 new MixinFullResolution().transform(_program); |
704 ticker.logMs("Transformed mixin applications"); | 718 ticker.logMs("Transformed mixin applications"); |
705 } | 719 } |
706 | 720 |
707 void otherTransformations() { | 721 void otherTransformations() { |
708 // TODO(ahe): Don't generate type variables in the first place. | 722 // TODO(ahe): Don't generate type variables in the first place. |
709 if (!strongMode) { | 723 if (!strongMode) { |
710 _program.accept(new Erasure()); | 724 _program.accept(new Erasure()); |
711 ticker.logMs("Erased type variables in generic methods"); | 725 ticker.logMs("Erased type variables in generic methods"); |
(...skipping 20 matching lines...) Expand all Loading... |
732 } | 746 } |
733 for (Constructor constructor in superclass.constructors) { | 747 for (Constructor constructor in superclass.constructors) { |
734 if (constructor.name.name.isEmpty) { | 748 if (constructor.name.name.isEmpty) { |
735 return constructor.function.requiredParameterCount == 0 | 749 return constructor.function.requiredParameterCount == 0 |
736 ? constructor | 750 ? constructor |
737 : null; | 751 : null; |
738 } | 752 } |
739 } | 753 } |
740 return null; | 754 return null; |
741 } | 755 } |
OLD | NEW |