@@ -7,23 +7,27 @@ library fasta.incremental_compiler;
7
7
import 'dart:async' show Future;
8
8
9
9
import 'package:kernel/kernel.dart'
10
- show Library, Program, Source, loadProgramFromBytes ;
10
+ show loadProgramFromBytes, Library, Procedure, Program, Source ;
11
11
12
12
import '../api_prototype/incremental_kernel_generator.dart'
13
13
show IncrementalKernelGenerator;
14
14
15
+ import '../api_prototype/file_system.dart' show FileSystemEntity;
16
+
15
17
import 'builder/builder.dart' show LibraryBuilder;
16
18
19
+ import 'builder_graph.dart' show BuilderGraph;
20
+
21
+ import 'compiler_context.dart' show CompilerContext;
22
+
23
+ import 'dill/dill_library_builder.dart' show DillLibraryBuilder;
24
+
17
25
import 'dill/dill_target.dart' show DillTarget;
18
26
19
27
import 'kernel/kernel_target.dart' show KernelTarget;
20
28
21
- import 'source/source_graph.dart' show SourceGraph;
22
-
23
29
import 'source/source_library_builder.dart' show SourceLibraryBuilder;
24
30
25
- import 'compiler_context.dart' show CompilerContext;
26
-
27
31
import 'ticker.dart' show Ticker;
28
32
29
33
import 'uri_translator.dart' show UriTranslator;
@@ -35,48 +39,112 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
35
39
36
40
List <Uri > invalidatedUris = < Uri > [];
37
41
38
- DillTarget platform;
42
+ DillTarget dillLoadedData;
43
+ List <LibraryBuilder > platformBuilders;
44
+ Map <Uri , LibraryBuilder > userBuilders;
45
+ final Uri bootstrapDill;
46
+ bool bootstrapSuccess = false ;
39
47
40
48
KernelTarget userCode;
41
49
42
- IncrementalCompiler (this .context) : ticker = context.options.ticker;
50
+ IncrementalCompiler (this .context, [this .bootstrapDill])
51
+ : ticker = context.options.ticker;
43
52
44
53
@override
45
54
Future <Program > computeDelta ({Uri entryPoint}) async {
46
55
ticker.reset ();
47
56
entryPoint ?? = context.options.inputs.single;
48
57
return context.runInContext <Future <Program >>((CompilerContext c) async {
49
- if (platform == null ) {
58
+ bool includeUserLoadedLibraries = false ;
59
+ Map <Uri , Source > uriToSource = {};
60
+ Map <Uri , int > importUriToOrder = {};
61
+ Procedure userLoadedUriMain;
62
+ bootstrapSuccess = false ;
63
+ if (dillLoadedData == null ) {
50
64
UriTranslator uriTranslator = await c.options.getUriTranslator ();
51
65
ticker.logMs ("Read packages file" );
52
66
53
- platform = new DillTarget (ticker, uriTranslator, c.options.target);
54
- List <int > bytes = await c.options.loadSdkSummaryBytes ();
55
- if (bytes != null ) {
67
+ dillLoadedData =
68
+ new DillTarget (ticker, uriTranslator, c.options.target);
69
+ List <int > summaryBytes = await c.options.loadSdkSummaryBytes ();
70
+ int bytesLength = 0 ;
71
+ Program program;
72
+ if (summaryBytes != null ) {
56
73
ticker.logMs ("Read ${c .options .sdkSummary }" );
57
- Program program = loadProgramFromBytes (bytes );
74
+ program = loadProgramFromBytes (summaryBytes );
58
75
ticker.logMs ("Deserialized ${c .options .sdkSummary }" );
59
- platform.loader.appendLibraries (program, byteCount: bytes.length);
60
- ticker.logMs ("Appended libraries" );
76
+ bytesLength += summaryBytes.length;
77
+ }
78
+
79
+ if (bootstrapDill != null ) {
80
+ FileSystemEntity entity =
81
+ c.options.fileSystem.entityForUri (bootstrapDill);
82
+ if (await entity.exists ()) {
83
+ List <int > bootstrapBytes = await entity.readAsBytes ();
84
+ if (bootstrapBytes != null ) {
85
+ Set <Uri > prevLibraryUris = new Set <Uri >.from (
86
+ program.libraries.map ((Library lib) => lib.importUri));
87
+ ticker.logMs ("Read $bootstrapDill " );
88
+ bool bootstrapFailed = false ;
89
+ try {
90
+ loadProgramFromBytes (bootstrapBytes, program);
91
+ } catch (e) {
92
+ bootstrapFailed = true ;
93
+ program = loadProgramFromBytes (summaryBytes);
94
+ }
95
+ if (! bootstrapFailed) {
96
+ bootstrapSuccess = true ;
97
+ bytesLength += bootstrapBytes.length;
98
+ for (Library lib in program.libraries) {
99
+ if (prevLibraryUris.contains (lib.importUri)) continue ;
100
+ importUriToOrder[lib.importUri] = importUriToOrder.length;
101
+ }
102
+ userLoadedUriMain = program.mainMethod;
103
+ includeUserLoadedLibraries = true ;
104
+ uriToSource.addAll (program.uriToSource);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ summaryBytes = null ;
110
+ if (program != null ) {
111
+ dillLoadedData.loader
112
+ .appendLibraries (program, byteCount: bytesLength);
61
113
}
62
- await platform.buildOutlines ();
114
+ ticker.logMs ("Appended libraries" );
115
+ await dillLoadedData.buildOutlines ();
116
+ userBuilders = < Uri , LibraryBuilder > {};
117
+ platformBuilders = < LibraryBuilder > [];
118
+ dillLoadedData.loader.builders.forEach ((uri, builder) {
119
+ if (builder.fileUri.scheme == "dart" ) {
120
+ platformBuilders.add (builder);
121
+ } else {
122
+ userBuilders[uri] = builder;
123
+ }
124
+ });
125
+ if (userBuilders.isEmpty) userBuilders = null ;
63
126
}
64
127
65
128
List <Uri > invalidatedUris = this .invalidatedUris.toList ();
66
129
this .invalidatedUris.clear ();
67
130
68
131
List <LibraryBuilder > reusedLibraries =
69
132
computeReusedLibraries (invalidatedUris);
133
+ Set <Uri > reusedLibraryUris =
134
+ new Set <Uri >.from (reusedLibraries.map ((b) => b.uri));
135
+ for (Uri uri in new Set <Uri >.from (dillLoadedData.loader.builders.keys)
136
+ ..removeAll (reusedLibraryUris)) {
137
+ dillLoadedData.loader.builders.remove (uri);
138
+ }
139
+
70
140
if (userCode != null ) {
71
141
ticker.logMs ("Decided to reuse ${reusedLibraries .length }"
72
142
" of ${userCode .loader .builders .length } libraries" );
73
143
}
74
144
75
- platform.loader.builders.forEach ((Uri uri, LibraryBuilder builder) {
76
- reusedLibraries.add (builder);
77
- });
145
+ reusedLibraries.addAll (platformBuilders);
78
146
userCode = new KernelTarget (
79
- c.fileSystem, false , platform, platform .uriTranslator,
147
+ c.fileSystem, false , dillLoadedData, dillLoadedData .uriTranslator,
80
148
uriToSource: c.uriToSource);
81
149
for (LibraryBuilder library in reusedLibraries) {
82
150
userCode.loader.builders[library.uri] = library;
@@ -94,16 +162,45 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
94
162
Program programWithDill =
95
163
await userCode.buildProgram (verify: c.options.verify);
96
164
165
+ List <Library > libraries =
166
+ new List <Library >.from (userCode.loader.libraries);
167
+ uriToSource.addAll (userCode.uriToSource);
168
+ if (includeUserLoadedLibraries) {
169
+ for (LibraryBuilder library in reusedLibraries) {
170
+ if (library.fileUri.scheme == "dart" ) continue ;
171
+ assert (library is DillLibraryBuilder );
172
+ libraries.add ((library as DillLibraryBuilder ).library);
173
+ }
174
+
175
+ // For now ensure original order of libraries to produce bit-perfect
176
+ // output.
177
+ List <Library > librariesOriginalOrder =
178
+ new List <Library >.filled (libraries.length, null , growable: true );
179
+ int lastOpen = libraries.length;
180
+ for (Library lib in libraries) {
181
+ int order = importUriToOrder[lib.importUri];
182
+ if (order != null ) {
183
+ librariesOriginalOrder[order] = lib;
184
+ } else {
185
+ librariesOriginalOrder[-- lastOpen] = lib;
186
+ }
187
+ }
188
+ libraries = librariesOriginalOrder;
189
+ }
190
+
97
191
// This is the incremental program.
98
- return new Program (
99
- libraries: new List <Library >.from (userCode.loader.libraries),
100
- uriToSource: new Map <Uri , Source >.from (userCode.uriToSource))
101
- ..mainMethod = programWithDill? .mainMethod;
192
+ Procedure mainMethod = programWithDill == null
193
+ ? userLoadedUriMain
194
+ : programWithDill.mainMethod;
195
+ return new Program (libraries: libraries, uriToSource: uriToSource)
196
+ ..mainMethod = mainMethod;
102
197
});
103
198
}
104
199
105
200
List <LibraryBuilder > computeReusedLibraries (Iterable <Uri > invalidatedUris) {
106
- if (userCode == null ) return < LibraryBuilder > [];
201
+ if (userCode == null && userBuilders == null ) {
202
+ return < LibraryBuilder > [];
203
+ }
107
204
108
205
// [invalidatedUris] converted to a set.
109
206
Set <Uri > invalidatedFileUris = invalidatedUris.toSet ();
@@ -116,25 +213,29 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
116
213
List <Uri > invalidatedImportUris = < Uri > [];
117
214
118
215
// Compute [builders] and [invalidatedImportUris].
119
- addBuilderAndInvalidateUris (Uri uri, LibraryBuilder libraryBuilder) {
120
- if (libraryBuilder.loader != platform.loader) {
121
- assert (libraryBuilder is SourceLibraryBuilder );
122
- SourceLibraryBuilder library = libraryBuilder;
123
- builders[uri] = library;
124
- if (invalidatedFileUris.contains (uri) ||
125
- (uri != library.fileUri &&
126
- invalidatedFileUris.contains (library.fileUri))) {
127
- invalidatedImportUris.add (uri);
128
- }
216
+ addBuilderAndInvalidateUris (Uri uri, LibraryBuilder library) {
217
+ builders[uri] = library;
218
+ if (invalidatedFileUris.contains (uri) ||
219
+ (uri != library.fileUri &&
220
+ invalidatedFileUris.contains (library.fileUri)) ||
221
+ (library is DillLibraryBuilder &&
222
+ uri != library.library.fileUri &&
223
+ invalidatedFileUris.contains (library.library.fileUri))) {
224
+ invalidatedImportUris.add (uri);
225
+ }
226
+ if (library is SourceLibraryBuilder ) {
129
227
for (var part in library.parts) {
130
228
addBuilderAndInvalidateUris (part.uri, part);
131
229
}
132
230
}
133
231
}
134
232
135
- userCode.loader.builders.forEach (addBuilderAndInvalidateUris);
233
+ userBuilders? .forEach (addBuilderAndInvalidateUris);
234
+ if (userCode != null ) {
235
+ userCode.loader.builders.forEach (addBuilderAndInvalidateUris);
236
+ }
136
237
137
- SourceGraph graph = new SourceGraph (builders);
238
+ BuilderGraph graph = new BuilderGraph (builders);
138
239
139
240
// Compute direct dependencies for each import URI (the reverse of the
140
241
// edges returned by `graph.neighborsOf`).
0 commit comments