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

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_target.dart

Issue 2976543002: Reapply "Tweak public APIs and use them in patch_sdk, dart2js, and kernel-service."" (Closed)
Patch Set: fix Created 3 years, 5 months 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 unified diff | Download patch
OLDNEW
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;
10
11 import 'package:front_end/file_system.dart'; 9 import 'package:front_end/file_system.dart';
12 10
13 import 'package:kernel/ast.dart' 11 import 'package:kernel/ast.dart'
14 show 12 show
15 Arguments, 13 Arguments,
16 CanonicalName, 14 CanonicalName,
17 Class, 15 Class,
18 Constructor, 16 Constructor,
19 DartType, 17 DartType,
20 DynamicType, 18 DynamicType,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 KernelNamedTypeBuilder, 69 KernelNamedTypeBuilder,
72 KernelProcedureBuilder, 70 KernelProcedureBuilder,
73 LibraryBuilder, 71 LibraryBuilder,
74 MemberBuilder, 72 MemberBuilder,
75 NamedTypeBuilder, 73 NamedTypeBuilder,
76 TypeBuilder, 74 TypeBuilder,
77 TypeDeclarationBuilder, 75 TypeDeclarationBuilder,
78 TypeVariableBuilder; 76 TypeVariableBuilder;
79 77
80 import 'verifier.dart' show verifyProgram; 78 import 'verifier.dart' show verifyProgram;
81 import 'kernel_outline_shaker.dart'
82 show trimProgram, RetainedDataBuilder, RootsMarker;
83 79
84 class KernelTarget extends TargetImplementation { 80 class KernelTarget extends TargetImplementation {
85 /// The [FileSystem] which should be used to access files. 81 /// The [FileSystem] which should be used to access files.
86 final FileSystem fileSystem; 82 final FileSystem fileSystem;
87 83
88 final DillTarget dillTarget; 84 final DillTarget dillTarget;
89 85
90 /// Shared with [CompilerContext]. 86 /// Shared with [CompilerContext].
91 final Map<String, Source> uriToSource; 87 final Map<String, Source> uriToSource;
92 88
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 cls.implementedTypes.clear(); 203 cls.implementedTypes.clear();
208 cls.supertype = null; 204 cls.supertype = null;
209 cls.mixedInType = null; 205 cls.mixedInType = null;
210 builder.supertype = new KernelNamedTypeBuilder("Object", null, 206 builder.supertype = new KernelNamedTypeBuilder("Object", null,
211 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri)) 207 builder.charOffset, builder.fileUri ?? Uri.parse(cls.fileUri))
212 ..builder = objectClassBuilder; 208 ..builder = objectClassBuilder;
213 builder.interfaces = null; 209 builder.interfaces = null;
214 builder.mixedInType = null; 210 builder.mixedInType = null;
215 } 211 }
216 212
217 void handleInputError(InputError error, 213 void handleInputError(InputError error, {bool isFullProgram}) {
218 {bool isFullProgram, bool trimDependencies: false}) {
219 if (error != null) { 214 if (error != null) {
220 String message = error.format(); 215 String message = error.format();
221 print(message); 216 print(message);
222 errors.add(message); 217 errors.add(message);
223 } 218 }
224 program = erroneousProgram(isFullProgram); 219 program = erroneousProgram(isFullProgram);
225 } 220 }
226 221
227 @override 222 @override
228 Future<Program> buildOutlines({CanonicalName nameRoot}) async { 223 Future<Program> buildOutlines({CanonicalName nameRoot}) async {
(...skipping 27 matching lines...) Expand all
256 } 251 }
257 return program; 252 return program;
258 } 253 }
259 254
260 /// Build the kernel representation of the program loaded by this target. The 255 /// Build the kernel representation of the program loaded by this target. The
261 /// program will contain full bodies for the code loaded from sources, and 256 /// program will contain full bodies for the code loaded from sources, and
262 /// only references to the code loaded by the [DillTarget], which may or may 257 /// only references to the code loaded by the [DillTarget], which may or may
263 /// not include method bodies (depending on what was loaded into that target, 258 /// not include method bodies (depending on what was loaded into that target,
264 /// an outline or a full kernel program). 259 /// an outline or a full kernel program).
265 /// 260 ///
266 /// When [trimDependencies] is true, this also runs a tree-shaker that deletes
267 /// anything from the [DillTarget] that is not needed for the source program,
268 /// this includes function bodies and types that are not reachable. This
269 /// option is currently in flux and the internal implementation might change.
270 /// See [trimDependenciesInProgram] for more details.
271 ///
272 /// If [verify], run the default kernel verification on the resulting program. 261 /// If [verify], run the default kernel verification on the resulting program.
273 @override 262 @override
274 Future<Program> buildProgram( 263 Future<Program> buildProgram({bool verify: false}) async {
275 {bool verify: false, bool trimDependencies: false}) async {
276 if (loader.first == null) return null; 264 if (loader.first == null) return null;
277 if (errors.isNotEmpty) { 265 if (errors.isNotEmpty) {
278 handleInputError(null, 266 handleInputError(null, isFullProgram: true);
279 isFullProgram: true, trimDependencies: trimDependencies);
280 return program; 267 return program;
281 } 268 }
282 269
283 try { 270 try {
284 await loader.buildBodies(); 271 await loader.buildBodies();
285 loader.finishStaticInvocations(); 272 loader.finishStaticInvocations();
286 finishAllConstructors(); 273 finishAllConstructors();
287 loader.finishNativeMethods(); 274 loader.finishNativeMethods();
288 runBuildTransformations(); 275 runBuildTransformations();
289 276
290 if (verify) this.verify(); 277 if (verify) this.verify();
291 if (errors.isNotEmpty) { 278 if (errors.isNotEmpty) {
292 handleInputError(null, 279 handleInputError(null, isFullProgram: true);
293 isFullProgram: true, trimDependencies: trimDependencies);
294 } 280 }
295 handleRecoverableErrors(loader.unhandledErrors); 281 handleRecoverableErrors(loader.unhandledErrors);
296 } on InputError catch (e) { 282 } on InputError catch (e) {
297 handleInputError(e, 283 handleInputError(e, isFullProgram: true);
298 isFullProgram: true, trimDependencies: trimDependencies);
299 } catch (e, s) { 284 } catch (e, s) {
300 return reportCrash(e, s, loader?.currentUriForCrashReporting); 285 return reportCrash(e, s, loader?.currentUriForCrashReporting);
301 } 286 }
302 if (trimDependencies) trimDependenciesInProgram();
303 return program; 287 return program;
304 } 288 }
305 289
306 Future writeDepsFile(Uri output, Uri depsFile,
307 {Iterable<Uri> extraDependencies}) async {
308 String toRelativeFilePath(Uri uri) {
309 // Ninja expects to find file names relative to the current working
310 // directory. We've tried making them relative to the deps file, but that
311 // doesn't work for downstream projects. Making them absolute also
312 // doesn't work.
313 //
314 // We can test if it works by running ninja twice, for example:
315 //
316 // ninja -C xcodebuild/ReleaseX64 runtime_kernel -d explain
317 // ninja -C xcodebuild/ReleaseX64 runtime_kernel -d explain
318 //
319 // The second time, ninja should say:
320 //
321 // ninja: Entering directory `xcodebuild/ReleaseX64'
322 // ninja: no work to do.
323 //
324 // It's broken if it says something like this:
325 //
326 // ninja explain: expected depfile 'patched_sdk.d' to mention
327 // 'patched_sdk/platform.dill', got
328 // '/.../xcodebuild/ReleaseX64/patched_sdk/platform.dill'
329 return Uri.parse(relativizeUri(uri, base: Uri.base)).toFilePath();
330 }
331
332 if (loader.first == null) return null;
333 StringBuffer sb = new StringBuffer();
334 sb.write(toRelativeFilePath(output));
335 sb.write(":");
336 Set<String> allDependencies = new Set<String>();
337 allDependencies.addAll(loader.getDependencies().map(toRelativeFilePath));
338 if (extraDependencies != null) {
339 allDependencies.addAll(extraDependencies.map(toRelativeFilePath));
340 }
341 for (String path in allDependencies) {
342 sb.write(" ");
343 sb.write(path);
344 }
345 sb.writeln();
346 await new File.fromUri(depsFile).writeAsString("$sb");
347 ticker.logMs("Wrote deps file");
348 }
349
350 /// Adds a synthetic field named `#errors` to the main library that contains 290 /// Adds a synthetic field named `#errors` to the main library that contains
351 /// [recoverableErrors] formatted. 291 /// [recoverableErrors] formatted.
352 /// 292 ///
353 /// If [recoverableErrors] is empty, this method does nothing. 293 /// If [recoverableErrors] is empty, this method does nothing.
354 /// 294 ///
355 /// If there's no main library, this method uses [erroneousProgram] to 295 /// If there's no main library, this method uses [erroneousProgram] to
356 /// replace [program]. 296 /// replace [program].
357 void handleRecoverableErrors(List<InputError> recoverableErrors) { 297 void handleRecoverableErrors(List<InputError> recoverableErrors) {
358 if (recoverableErrors.isEmpty) return; 298 if (recoverableErrors.isEmpty) return;
359 KernelLibraryBuilder mainLibrary = loader.first; 299 KernelLibraryBuilder mainLibrary = loader.first;
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 backendTarget.performGlobalTransformations(loader.coreTypes, program, 623 backendTarget.performGlobalTransformations(loader.coreTypes, program,
684 logger: (String msg) => ticker.logMs(msg)); 624 logger: (String msg) => ticker.logMs(msg));
685 } 625 }
686 626
687 void verify() { 627 void verify() {
688 var verifyErrors = verifyProgram(program); 628 var verifyErrors = verifyProgram(program);
689 errors.addAll(verifyErrors.map((error) => '$error')); 629 errors.addAll(verifyErrors.map((error) => '$error'));
690 ticker.logMs("Verified program"); 630 ticker.logMs("Verified program");
691 } 631 }
692 632
693 /// Tree-shakes most code from the [dillTarget] by visiting all other
694 /// libraries in [program] and marking the APIs from the [dillTarget]
695 /// libraries that are in use.
696 ///
697 /// Note: while it's likely we'll do some trimming of programs for modular
698 /// compilation, it is unclear at this time when and how that trimming should
699 /// happen. We are likely going to remove the extra visitor my either marking
700 /// things while code is built, or by handling tree-shaking after the fact
701 /// (e.g. during serialization).
702 trimDependenciesInProgram() {
703 var toShake =
704 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet();
705 var isIncluded = (Uri uri) => !toShake.contains(uri);
706 var data = new RetainedDataBuilder();
707 // TODO(sigmund): replace this step with data that is directly computed from
708 // the builders: we should know the tree-shaking roots without having to do
709 // a second visit over the tree.
710 new RootsMarker(loader.coreTypes, data).run(program, isIncluded);
711 trimProgram(program, data, isIncluded);
712 }
713
714 /// Return `true` if the given [library] was built by this [KernelTarget] 633 /// Return `true` if the given [library] was built by this [KernelTarget]
715 /// from sources, and not loaded from a [DillTarget]. 634 /// from sources, and not loaded from a [DillTarget].
716 bool isSourceLibrary(Library library) { 635 bool isSourceLibrary(Library library) {
717 return loader.libraries.contains(library); 636 return loader.libraries.contains(library);
718 } 637 }
719 } 638 }
720 639
721 /// Looks for a constructor call that matches `super()` from a constructor in 640 /// Looks for a constructor call that matches `super()` from a constructor in
722 /// [cls]. Such a constructor may have optional arguments, but no required 641 /// [cls]. Such a constructor may have optional arguments, but no required
723 /// arguments. 642 /// arguments.
724 Constructor defaultSuperConstructor(Class cls) { 643 Constructor defaultSuperConstructor(Class cls) {
725 Class superclass = cls.superclass; 644 Class superclass = cls.superclass;
726 while (superclass != null && superclass.isMixinApplication) { 645 while (superclass != null && superclass.isMixinApplication) {
727 superclass = superclass.superclass; 646 superclass = superclass.superclass;
728 } 647 }
729 for (Constructor constructor in superclass.constructors) { 648 for (Constructor constructor in superclass.constructors) {
730 if (constructor.name.name.isEmpty) { 649 if (constructor.name.name.isEmpty) {
731 return constructor.function.requiredParameterCount == 0 650 return constructor.function.requiredParameterCount == 0
732 ? constructor 651 ? constructor
733 : null; 652 : null;
734 } 653 }
735 } 654 }
736 return null; 655 return null;
737 } 656 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698