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 library kernel.ast_from_binary; | 4 library kernel.ast_from_binary; |
5 | 5 |
| 6 import 'dart:convert'; |
| 7 |
6 import '../ast.dart'; | 8 import '../ast.dart'; |
| 9 import '../transformations/flags.dart'; |
7 import 'tag.dart'; | 10 import 'tag.dart'; |
8 import 'loader.dart'; | |
9 import 'dart:convert'; | |
10 import 'package:kernel/transformations/flags.dart'; | |
11 | 11 |
12 class ParseError { | 12 class ParseError { |
13 String filename; | 13 String filename; |
14 int byteIndex; | 14 int byteIndex; |
15 String message; | 15 String message; |
16 String path; | 16 String path; |
17 | 17 |
18 ParseError(this.message, {this.filename, this.byteIndex, this.path}); | 18 ParseError(this.message, {this.filename, this.byteIndex, this.path}); |
19 | 19 |
20 String toString() => '$filename:$byteIndex: $message at $path'; | 20 String toString() => '$filename:$byteIndex: $message at $path'; |
21 } | 21 } |
22 | 22 |
23 class BinaryBuilder { | 23 class BinaryBuilder { |
24 final BinaryReferenceLoader loader; | |
25 final List<Library> importTable = <Library>[]; | |
26 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; | 24 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; |
27 final List<LabeledStatement> labelStack = <LabeledStatement>[]; | 25 final List<LabeledStatement> labelStack = <LabeledStatement>[]; |
28 int labelStackBase = 0; | 26 int labelStackBase = 0; |
29 final List<SwitchCase> switchCaseStack = <SwitchCase>[]; | 27 final List<SwitchCase> switchCaseStack = <SwitchCase>[]; |
30 final List<TypeParameter> typeParameterStack = <TypeParameter>[]; | 28 final List<TypeParameter> typeParameterStack = <TypeParameter>[]; |
31 final String filename; | 29 final String filename; |
32 final List<int> _bytes; | 30 final List<int> _bytes; |
33 int _byteIndex = 0; | 31 int _byteIndex = 0; |
34 Library _currentLibrary; | |
35 List<String> _stringTable; | 32 List<String> _stringTable; |
36 List<String> _sourceUriTable; | 33 List<String> _sourceUriTable; |
| 34 List<CanonicalName> _linkTable; |
37 int _transformerFlags = 0; | 35 int _transformerFlags = 0; |
| 36 Library _currentLibrary; |
38 | 37 |
39 // If something goes wrong, this list should indicate what library, | 38 // If something goes wrong, this list should indicate what library, |
40 // class, and member was being built. | 39 // class, and member was being built. |
41 List<String> debugPath = <String>[]; | 40 List<String> debugPath = <String>[]; |
42 | 41 |
43 BinaryBuilder(this.loader, this._bytes, [this.filename]); | 42 bool _isReadingLibraryImplementation = false; |
| 43 |
| 44 BinaryBuilder(this._bytes, [this.filename]); |
44 | 45 |
45 fail(String message) { | 46 fail(String message) { |
46 throw new ParseError(message, | 47 throw new ParseError(message, |
47 byteIndex: _byteIndex, filename: filename, path: debugPath.join('::')); | 48 byteIndex: _byteIndex, filename: filename, path: debugPath.join('::')); |
48 } | 49 } |
49 | 50 |
50 int readByte() => _bytes[_byteIndex++]; | 51 int readByte() => _bytes[_byteIndex++]; |
51 | 52 |
52 int readUInt() { | 53 int readUInt() { |
53 var byte = readByte(); | 54 var byte = readByte(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 return _stringTable[readUInt()]; | 120 return _stringTable[readUInt()]; |
120 } | 121 } |
121 | 122 |
122 String readStringOrNullIfEmpty() { | 123 String readStringOrNullIfEmpty() { |
123 var string = readStringReference(); | 124 var string = readStringReference(); |
124 return string.isEmpty ? null : string; | 125 return string.isEmpty ? null : string; |
125 } | 126 } |
126 | 127 |
127 InferredValue readOptionalInferredValue() { | 128 InferredValue readOptionalInferredValue() { |
128 if (readAndCheckOptionTag()) { | 129 if (readAndCheckOptionTag()) { |
129 Class baseClass = readClassReference(allowNull: true); | 130 Reference baseClass = readClassReference(allowNull: true); |
130 BaseClassKind baseClassKind = BaseClassKind.values[readByte()]; | 131 BaseClassKind baseClassKind = BaseClassKind.values[readByte()]; |
131 int valueBits = readByte(); | 132 int valueBits = readByte(); |
132 return new InferredValue(baseClass, baseClassKind, valueBits); | 133 return new InferredValue.byReference(baseClass, baseClassKind, valueBits); |
133 } | 134 } |
134 return null; | 135 return null; |
135 } | 136 } |
136 | 137 |
137 bool readAndCheckOptionTag() { | 138 bool readAndCheckOptionTag() { |
138 int tag = readByte(); | 139 int tag = readByte(); |
139 if (tag == Tag.Nothing) { | 140 if (tag == Tag.Nothing) { |
140 return false; | 141 return false; |
141 } else if (tag == Tag.Something) { | 142 } else if (tag == Tag.Something) { |
142 return true; | 143 return true; |
(...skipping 20 matching lines...) Expand all Loading... |
163 } | 164 } |
164 } | 165 } |
165 | 166 |
166 void _fillNonTreeNodeList(List<Node> list, Node buildObject()) { | 167 void _fillNonTreeNodeList(List<Node> list, Node buildObject()) { |
167 list.length = readUInt(); | 168 list.length = readUInt(); |
168 for (int i = 0; i < list.length; ++i) { | 169 for (int i = 0; i < list.length; ++i) { |
169 list[i] = buildObject(); | 170 list[i] = buildObject(); |
170 } | 171 } |
171 } | 172 } |
172 | 173 |
173 Program readProgramFile() { | 174 /// Reads a list of named nodes, reusing any existing objects already in the |
| 175 /// linking tree. The nodes are merged into [list], and if reading the library |
| 176 /// implementation, the order is corrected. |
| 177 /// |
| 178 /// [readObject] should read the object definition and its canonical name. |
| 179 /// If an existing object is bound to the canonical name, the existing object |
| 180 /// must be reused and returned. |
| 181 void _mergeNamedNodeList( |
| 182 List<NamedNode> list, NamedNode readObject(), TreeNode parent) { |
| 183 if (_isReadingLibraryImplementation) { |
| 184 // When reading the library implementation, overwrite the whole list |
| 185 // with the new one. |
| 186 _fillTreeNodeList(list, readObject, parent); |
| 187 } else { |
| 188 // When reading an external library, the results should either be: |
| 189 // - merged with the existing external library definition (if any) |
| 190 // - ignored if the library implementation is already in memory |
| 191 int numberOfNodes = readUInt(); |
| 192 for (int i = 0; i < numberOfNodes; ++i) { |
| 193 var value = readObject(); |
| 194 // We use the parent pointer of a node to determine if it already is in |
| 195 // the AST and hence should not be added again. |
| 196 if (value.parent == null) { |
| 197 list.add(value..parent = parent); |
| 198 } |
| 199 } |
| 200 } |
| 201 } |
| 202 |
| 203 void readLinkTable(CanonicalName linkRoot) { |
| 204 int length = readUInt(); |
| 205 _linkTable = new List<CanonicalName>(length); |
| 206 for (int i = 0; i < length; ++i) { |
| 207 int biasedParentIndex = readUInt(); |
| 208 String name = readStringReference(); |
| 209 var parent = |
| 210 biasedParentIndex == 0 ? linkRoot : _linkTable[biasedParentIndex - 1]; |
| 211 _linkTable[i] = parent.getChild(name); |
| 212 } |
| 213 } |
| 214 |
| 215 /// Deserializes a kernel program and stores it in [program]. |
| 216 /// |
| 217 /// When linking with a non-empty program, canonical names must have been |
| 218 /// computed ahead of time. |
| 219 /// |
| 220 /// The input bytes may contain multiple files concatenated. |
| 221 void readProgram(Program program) { |
| 222 while (_byteIndex < _bytes.length) { |
| 223 _readOneProgram(program); |
| 224 } |
| 225 } |
| 226 |
| 227 /// Reads a single program file from the input and loads it into [program], |
| 228 /// overwriting and reusing any existing data in the program. |
| 229 /// |
| 230 /// When linking with a non-empty program, canonical names must have been |
| 231 /// computed ahead of time. |
| 232 /// |
| 233 /// This should *only* be used when there is a reason to not allow |
| 234 /// concatenated files. |
| 235 void readSingleFileProgram(Program program) { |
| 236 _readOneProgram(program); |
| 237 if (_byteIndex < _bytes.length) { |
| 238 if (_byteIndex + 3 < _bytes.length) { |
| 239 int magic = readMagicWord(); |
| 240 if (magic == Tag.ProgramFile) { |
| 241 throw 'Concatenated program file given when a single program ' |
| 242 'was expected.'; |
| 243 } |
| 244 } |
| 245 throw 'Unrecognized bytes following program data'; |
| 246 } |
| 247 } |
| 248 |
| 249 void _readOneProgram(Program program) { |
174 int magic = readMagicWord(); | 250 int magic = readMagicWord(); |
175 if (magic != Tag.ProgramFile) { | 251 if (magic != Tag.ProgramFile) { |
176 throw fail('This is not a binary dart file. ' | 252 throw fail('This is not a binary dart file. ' |
177 'Magic number was: ${magic.toRadixString(16)}'); | 253 'Magic number was: ${magic.toRadixString(16)}'); |
178 } | 254 } |
179 readStringTable(); | 255 readStringTable(); |
180 Map<String, Source> uriToSource = readUriToSource(); | 256 Map<String, Source> uriToSource = readUriToSource(); |
181 importTable.length = readUInt(); | 257 program.uriToSource.addAll(uriToSource); |
182 for (int i = 0; i < importTable.length; ++i) { | 258 readLinkTable(program.root); |
183 importTable[i] = new Library(null); | 259 int numberOfLibraries = readUInt(); |
184 } | 260 List<Library> libraries = new List<Library>(numberOfLibraries); |
185 for (int i = 0; i < importTable.length; ++i) { | 261 for (int i = 0; i < numberOfLibraries; ++i) { |
186 _currentLibrary = importTable[i]; | 262 libraries[i] = readLibrary(program); |
187 readLibrary(); | |
188 } | 263 } |
189 var mainMethod = readMemberReference(allowNull: true); | 264 var mainMethod = readMemberReference(allowNull: true); |
190 return new Program(importTable, uriToSource)..mainMethod = mainMethod; | 265 program.mainMethodName ??= mainMethod; |
191 } | 266 } |
192 | 267 |
193 Map<String, Source> readUriToSource() { | 268 Map<String, Source> readUriToSource() { |
194 readSourceUriTable(); | 269 readSourceUriTable(); |
195 int length = _sourceUriTable.length; | 270 int length = _sourceUriTable.length; |
196 Map<String, Source> uriToLineStarts = <String, Source>{}; | 271 Map<String, Source> uriToSource = <String, Source>{}; |
197 for (int i = 0; i < length; ++i) { | 272 for (int i = 0; i < length; ++i) { |
198 String uri = _sourceUriTable[i]; | 273 String uri = _sourceUriTable[i]; |
199 String sourceCode = readStringEntry(); | 274 String sourceCode = readStringEntry(); |
200 int lineCount = readUInt(); | 275 int lineCount = readUInt(); |
201 List<int> lineStarts = new List<int>(lineCount); | 276 List<int> lineStarts = new List<int>(lineCount); |
202 int previousLineStart = 0; | 277 int previousLineStart = 0; |
203 for (int j = 0; j < lineCount; ++j) { | 278 for (int j = 0; j < lineCount; ++j) { |
204 int lineStart = readUInt() + previousLineStart; | 279 int lineStart = readUInt() + previousLineStart; |
205 lineStarts[j] = lineStart; | 280 lineStarts[j] = lineStart; |
206 previousLineStart = lineStart; | 281 previousLineStart = lineStart; |
207 } | 282 } |
208 uriToLineStarts[uri] = new Source(lineStarts, sourceCode); | 283 uriToSource[uri] = new Source(lineStarts, sourceCode); |
209 } | 284 } |
210 return uriToLineStarts; | 285 return uriToSource; |
211 } | 286 } |
212 | 287 |
213 void _fillLazilyLoadedList( | 288 CanonicalName readCanonicalNameReference() { |
214 List<TreeNode> list, void buildObject(int tag, int index)) { | 289 var index = readUInt(); |
215 int length = readUInt(); | 290 if (index == 0) return null; |
216 list.length = length; | 291 return _linkTable[index - 1]; |
217 for (int i = 0; i < length; ++i) { | |
218 int tag = readByte(); | |
219 buildObject(tag, i); | |
220 } | |
221 } | 292 } |
222 | 293 |
223 Library readLibraryReference() { | 294 Reference readLibraryReference() { |
224 int index = readUInt(); | 295 return readCanonicalNameReference().getReference(); |
225 return importTable[index]; | |
226 } | 296 } |
227 | 297 |
228 DeferredImport readDeferredImportReference() { | 298 DeferredImport readDeferredImportReference() { |
229 int index = readUInt(); | 299 int index = readUInt(); |
230 return _currentLibrary.deferredImports[index]; | 300 return _currentLibrary.deferredImports[index]; |
231 } | 301 } |
232 | 302 |
233 Class readClassReference({bool allowNull: false}) { | 303 Reference readClassReference({bool allowNull: false}) { |
234 int tag = readByte(); | 304 var name = readCanonicalNameReference(); |
235 if (tag == Tag.NullReference) { | 305 if (name == null && !allowNull) { |
236 if (!allowNull) { | 306 throw 'Expected a class reference to be valid but was `null`.'; |
237 throw 'Expected a class reference to be valid but was `null`.'; | |
238 } | |
239 return null; | |
240 } else { | |
241 var library = readLibraryReference(); | |
242 int index = readUInt(); | |
243 return loader.getClassReference(library, tag, index); | |
244 } | 307 } |
| 308 return name?.getReference(); |
245 } | 309 } |
246 | 310 |
247 Member readMemberReference({bool allowNull: false}) { | 311 Reference readMemberReference({bool allowNull: false}) { |
248 int tag = readByte(); | 312 var name = readCanonicalNameReference(); |
249 switch (tag) { | 313 if (name == null && !allowNull) { |
250 case Tag.LibraryFieldReference: | 314 throw 'Expected a member reference to be valid but was `null`.'; |
251 case Tag.LibraryProcedureReference: | |
252 var library = readLibraryReference(); | |
253 var index = readUInt(); | |
254 return loader.getLibraryMemberReference(library, tag, index); | |
255 | |
256 case Tag.ClassFieldReference: | |
257 case Tag.ClassConstructorReference: | |
258 case Tag.ClassProcedureReference: | |
259 var classNode = readClassReference(); | |
260 var index = readUInt(); | |
261 return loader.getClassMemberReference(classNode, tag, index); | |
262 | |
263 case Tag.NullReference: | |
264 if (!allowNull) { | |
265 throw 'Expected a member reference to be valid but was `null`.'; | |
266 } | |
267 return null; | |
268 | |
269 default: | |
270 throw fail('Invalid member reference tag: $tag'); | |
271 } | 315 } |
| 316 return name?.getReference(); |
272 } | 317 } |
273 | 318 |
274 Name readName() { | 319 Name readName() { |
275 String text = readStringReference(); | 320 String text = readStringReference(); |
276 if (text.isNotEmpty && text[0] == '_') { | 321 if (text.isNotEmpty && text[0] == '_') { |
277 return new Name(text, readLibraryReference()); | 322 return new Name.byReference(text, readLibraryReference()); |
278 } else { | 323 } else { |
279 return new Name(text); | 324 return new Name(text); |
280 } | 325 } |
281 } | 326 } |
282 | 327 |
283 Uri readImportUri() { | 328 Library readLibrary(Program program) { |
284 return Uri.parse(readStringReference()); | 329 int flags = readByte(); |
285 } | 330 bool isExternal = (flags & 0x1) != 0; |
| 331 _isReadingLibraryImplementation = !isExternal; |
| 332 var canonicalName = readCanonicalNameReference(); |
| 333 Reference reference = canonicalName.getReference(); |
| 334 Library library = reference.node; |
| 335 bool shouldWriteData = library == null || _isReadingLibraryImplementation; |
| 336 if (library == null) { |
| 337 library = |
| 338 new Library(Uri.parse(canonicalName.name), reference: reference); |
| 339 program.libraries.add(library..parent = program); |
| 340 } |
| 341 _currentLibrary = library; |
| 342 String name = readStringOrNullIfEmpty(); |
| 343 // TODO(jensj): We currently save (almost the same) uri twice. |
| 344 String fileUri = readUriReference(); |
286 | 345 |
287 void readLibrary() { | 346 if (shouldWriteData) { |
288 int flags = readByte(); | 347 library.isExternal = isExternal; |
289 _currentLibrary.isExternal = (flags & 0x1) != 0; | 348 library.name = name; |
290 _currentLibrary.name = readStringOrNullIfEmpty(); | 349 library.fileUri = fileUri; |
291 _currentLibrary.importUri = readImportUri(); | 350 } |
292 debugPath.add(_currentLibrary.name ?? | |
293 _currentLibrary.importUri?.toString() ?? | |
294 'library'); | |
295 | 351 |
296 // TODO(jensj): We currently save (almost the same) uri twice. | 352 _readDeferredImports(library); |
297 _currentLibrary.fileUri = readUriReference(); | |
298 | 353 |
299 _readDeferredImports(_currentLibrary); | 354 debugPath.add(library.name ?? library.importUri?.toString() ?? 'library'); |
300 _fillLazilyLoadedList(_currentLibrary.classes, (int tag, int index) { | 355 |
301 readClass(loader.getClassReference(_currentLibrary, tag, index), tag); | 356 _mergeNamedNodeList(library.classes, readClass, library); |
302 }); | 357 _mergeNamedNodeList(library.fields, readField, library); |
303 _fillLazilyLoadedList(_currentLibrary.fields, (int tag, int index) { | 358 _mergeNamedNodeList(library.procedures, readProcedure, library); |
304 readField( | 359 |
305 loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); | |
306 }); | |
307 _fillLazilyLoadedList(_currentLibrary.procedures, (int tag, int index) { | |
308 readProcedure( | |
309 loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); | |
310 }); | |
311 debugPath.removeLast(); | 360 debugPath.removeLast(); |
| 361 _currentLibrary = null; |
| 362 return library; |
312 } | 363 } |
313 | 364 |
314 void _readDeferredImports(Library library) { | 365 void _readDeferredImports(Library library) { |
315 int count = readUInt(); | 366 int length = readUInt(); |
316 library.deferredImports.length = count; | 367 if (library.isExternal) { |
317 for (int i = 0; i < count; ++i) { | 368 assert(length == 0); |
318 var importNode = _readDeferredImport(); | 369 return; |
319 library.deferredImports.add(importNode..parent = library); | 370 } |
| 371 library.deferredImports.length = length; |
| 372 for (int i = 0; i < length; ++i) { |
| 373 library.deferredImports[i] = new DeferredImport.byReference( |
| 374 readLibraryReference(), readStringReference())..parent = library; |
320 } | 375 } |
321 } | 376 } |
322 | 377 |
323 DeferredImport _readDeferredImport() { | 378 Class readClass() { |
324 return new DeferredImport(readLibraryReference(), readStringReference()); | 379 int tag = readByte(); |
325 } | 380 assert(tag == Tag.Class); |
326 | 381 var canonicalName = readCanonicalNameReference(); |
327 void readClass(Class node, int tag) { | 382 var reference = canonicalName.getReference(); |
328 assert(node != null); | 383 Class node = reference.node; |
329 switch (tag) { | 384 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
330 case Tag.NormalClass: | 385 if (node == null) { |
331 readNormalClass(node); | 386 node = new Class(reference: reference)..level = ClassLevel.Temporary; |
332 break; | |
333 case Tag.MixinClass: | |
334 readMixinClass(node); | |
335 break; | |
336 default: | |
337 throw fail('Invalid class tag: $tag'); | |
338 } | 387 } |
339 } | |
340 | |
341 void readNormalClass(Class node) { | |
342 node.fileOffset = readOffset(); | 388 node.fileOffset = readOffset(); |
343 int flags = readByte(); | 389 int flags = readByte(); |
344 node.isAbstract = flags & 0x1 != 0; | 390 node.isAbstract = flags & 0x1 != 0; |
345 int levelIndex = (flags >> 1) & 0x3; | 391 int levelIndex = (flags >> 1) & 0x3; |
346 node.level = ClassLevel.values[levelIndex + 1]; | 392 var level = ClassLevel.values[levelIndex + 1]; |
347 node.name = readStringOrNullIfEmpty(); | 393 if (level.index >= node.level.index) { |
348 node.fileUri = readUriReference(); | 394 node.level = level; |
349 node.annotations = readAnnotationList(node); | 395 } |
| 396 var name = readStringOrNullIfEmpty(); |
| 397 var fileUri = readUriReference(); |
| 398 var annotations = readAnnotationList(node); |
350 debugPath.add(node.name ?? 'normal-class'); | 399 debugPath.add(node.name ?? 'normal-class'); |
351 readAndPushTypeParameterList(node.typeParameters, node); | 400 readAndPushTypeParameterList(node.typeParameters, node); |
352 node.supertype = readSupertypeOption(); | 401 var supertype = readSupertypeOption(); |
| 402 var mixedInType = readSupertypeOption(); |
353 _fillNonTreeNodeList(node.implementedTypes, readSupertype); | 403 _fillNonTreeNodeList(node.implementedTypes, readSupertype); |
354 _fillLazilyLoadedList(node.fields, (int tag, int index) { | 404 _mergeNamedNodeList(node.fields, readField, node); |
355 readField(loader.getClassMemberReference(node, tag, index), tag); | 405 _mergeNamedNodeList(node.constructors, readConstructor, node); |
356 }); | 406 _mergeNamedNodeList(node.procedures, readProcedure, node); |
357 _fillLazilyLoadedList(node.constructors, (int tag, int index) { | |
358 readConstructor(loader.getClassMemberReference(node, tag, index), tag); | |
359 }); | |
360 _fillLazilyLoadedList(node.procedures, (int tag, int index) { | |
361 readProcedure(loader.getClassMemberReference(node, tag, index), tag); | |
362 }); | |
363 typeParameterStack.length = 0; | 407 typeParameterStack.length = 0; |
364 debugPath.removeLast(); | 408 debugPath.removeLast(); |
365 } | 409 if (shouldWriteData) { |
366 | 410 node.name = name; |
367 void readMixinClass(Class node) { | 411 node.fileUri = fileUri; |
368 node.fileOffset = readOffset(); | 412 node.annotations = annotations; |
369 int flags = readByte(); | 413 node.supertype = supertype; |
370 node.isAbstract = flags & 0x1 != 0; | 414 node.mixedInType = mixedInType; |
371 int levelIndex = (flags >> 1) & 0x3; | 415 } |
372 node.level = ClassLevel.values[levelIndex]; | 416 return node; |
373 node.name = readStringOrNullIfEmpty(); | |
374 node.fileUri = readUriReference(); | |
375 node.annotations = readAnnotationList(node); | |
376 debugPath.add(node.name ?? 'mixin-class'); | |
377 readAndPushTypeParameterList(node.typeParameters, node); | |
378 node.supertype = readSupertype(); | |
379 node.mixedInType = readSupertype(); | |
380 _fillNonTreeNodeList(node.implementedTypes, readDartType); | |
381 _fillLazilyLoadedList(node.constructors, (int tag, int index) { | |
382 readConstructor(loader.getClassMemberReference(node, tag, index), tag); | |
383 }); | |
384 typeParameterStack.length = 0; | |
385 debugPath.removeLast(); | |
386 } | 417 } |
387 | 418 |
388 int getAndResetTransformerFlags() { | 419 int getAndResetTransformerFlags() { |
389 int flags = _transformerFlags; | 420 int flags = _transformerFlags; |
390 _transformerFlags = 0; | 421 _transformerFlags = 0; |
391 return flags; | 422 return flags; |
392 } | 423 } |
393 | 424 |
394 /// Adds the given flag to the current [Member.transformerFlags]. | 425 /// Adds the given flag to the current [Member.transformerFlags]. |
395 void addTransformerFlag(int flags) { | 426 void addTransformerFlag(int flags) { |
396 _transformerFlags |= flags; | 427 _transformerFlags |= flags; |
397 } | 428 } |
398 | 429 |
399 void readField(Field node, int tag) { | 430 Field readField() { |
400 // Note: as with readProcedure and readConstructor, the tag parameter | 431 int tag = readByte(); |
401 // is unused, but we pass it in to clarify that the tag has already been | |
402 // consumed from the input. | |
403 assert(tag == Tag.Field); | 432 assert(tag == Tag.Field); |
404 node.fileOffset = readOffset(); | 433 var canonicalName = readCanonicalNameReference(); |
405 node.fileEndOffset = readOffset(); | 434 var reference = canonicalName.getReference(); |
406 node.flags = readByte(); | 435 Field node = reference.node; |
407 node.name = readName(); | 436 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
408 node.fileUri = readUriReference(); | 437 if (node == null) { |
409 node.annotations = readAnnotationList(node); | 438 node = new Field(null, reference: reference); |
| 439 } |
| 440 int fileOffset = readOffset(); |
| 441 int fileEndOffset = readOffset(); |
| 442 int flags = readByte(); |
| 443 var name = readName(); |
| 444 var fileUri = readUriReference(); |
| 445 var annotations = readAnnotationList(node); |
410 debugPath.add(node.name?.name ?? 'field'); | 446 debugPath.add(node.name?.name ?? 'field'); |
411 node.type = readDartType(); | 447 var type = readDartType(); |
412 node.inferredValue = readOptionalInferredValue(); | 448 var inferredValue = readOptionalInferredValue(); |
413 node.initializer = readExpressionOption(); | 449 var initializer = readExpressionOption(); |
414 node.initializer?.parent = node; | 450 int transformerFlags = getAndResetTransformerFlags(); |
415 node.transformerFlags = getAndResetTransformerFlags(); | |
416 debugPath.removeLast(); | 451 debugPath.removeLast(); |
| 452 if (shouldWriteData) { |
| 453 node.fileOffset = fileOffset; |
| 454 node.fileEndOffset = fileEndOffset; |
| 455 node.flags = flags; |
| 456 node.name = name; |
| 457 node.fileUri = fileUri; |
| 458 node.annotations = annotations; |
| 459 node.type = type; |
| 460 node.inferredValue = inferredValue; |
| 461 node.initializer = initializer; |
| 462 node.initializer?.parent = node; |
| 463 node.transformerFlags = transformerFlags; |
| 464 } |
| 465 return node; |
417 } | 466 } |
418 | 467 |
419 void readConstructor(Constructor node, int tag) { | 468 Constructor readConstructor() { |
| 469 int tag = readByte(); |
420 assert(tag == Tag.Constructor); | 470 assert(tag == Tag.Constructor); |
421 node.fileOffset = readOffset(); | 471 var canonicalName = readCanonicalNameReference(); |
422 node.fileEndOffset = readOffset(); | 472 var reference = canonicalName.getReference(); |
423 node.flags = readByte(); | 473 Constructor node = reference.node; |
424 node.name = readName(); | 474 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
425 node.annotations = readAnnotationList(node); | 475 if (node == null) { |
| 476 node = new Constructor(null, reference: reference); |
| 477 } |
| 478 var fileOffset = readOffset(); |
| 479 var fileEndOffset = readOffset(); |
| 480 var flags = readByte(); |
| 481 var name = readName(); |
| 482 var annotations = readAnnotationList(node); |
426 debugPath.add(node.name?.name ?? 'constructor'); | 483 debugPath.add(node.name?.name ?? 'constructor'); |
427 node.function = readFunctionNode()..parent = node; | 484 var function = readFunctionNode(); |
428 pushVariableDeclarations(node.function.positionalParameters); | 485 pushVariableDeclarations(function.positionalParameters); |
429 pushVariableDeclarations(node.function.namedParameters); | 486 pushVariableDeclarations(function.namedParameters); |
430 _fillTreeNodeList(node.initializers, readInitializer, node); | 487 _fillTreeNodeList(node.initializers, readInitializer, node); |
431 variableStack.length = 0; | 488 variableStack.length = 0; |
432 node.transformerFlags = getAndResetTransformerFlags(); | 489 var transformerFlags = getAndResetTransformerFlags(); |
433 debugPath.removeLast(); | 490 debugPath.removeLast(); |
| 491 if (shouldWriteData) { |
| 492 node.fileOffset = fileOffset; |
| 493 node.fileEndOffset = fileEndOffset; |
| 494 node.flags = flags; |
| 495 node.name = name; |
| 496 node.annotations = annotations; |
| 497 node.function = function..parent = node; |
| 498 node.transformerFlags = transformerFlags; |
| 499 } |
| 500 return node; |
434 } | 501 } |
435 | 502 |
436 void readProcedure(Procedure node, int tag) { | 503 Procedure readProcedure() { |
| 504 int tag = readByte(); |
437 assert(tag == Tag.Procedure); | 505 assert(tag == Tag.Procedure); |
438 node.fileOffset = readOffset(); | 506 var canonicalName = readCanonicalNameReference(); |
439 node.fileEndOffset = readOffset(); | 507 var reference = canonicalName.getReference(); |
| 508 Procedure node = reference.node; |
| 509 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
| 510 if (node == null) { |
| 511 node = new Procedure(null, null, null, reference: reference); |
| 512 } |
| 513 var fileOffset = readOffset(); |
| 514 var fileEndOffset = readOffset(); |
440 int kindIndex = readByte(); | 515 int kindIndex = readByte(); |
441 node.kind = ProcedureKind.values[kindIndex]; | 516 var kind = ProcedureKind.values[kindIndex]; |
442 node.flags = readByte(); | 517 var flags = readByte(); |
443 node.name = readName(); | 518 var name = readName(); |
444 node.fileUri = readUriReference(); | 519 var fileUri = readUriReference(); |
445 node.annotations = readAnnotationList(node); | 520 var annotations = readAnnotationList(node); |
446 debugPath.add(node.name?.name ?? 'procedure'); | 521 debugPath.add(node.name?.name ?? 'procedure'); |
447 node.function = readFunctionNodeOption(); | 522 var function = readFunctionNodeOption(); |
448 node.function?.parent = node; | 523 var transformerFlags = getAndResetTransformerFlags(); |
449 node.transformerFlags = getAndResetTransformerFlags(); | |
450 debugPath.removeLast(); | 524 debugPath.removeLast(); |
| 525 if (shouldWriteData) { |
| 526 node.fileOffset = fileOffset; |
| 527 node.fileEndOffset = fileEndOffset; |
| 528 node.kind = kind; |
| 529 node.flags = flags; |
| 530 node.name = name; |
| 531 node.fileUri = fileUri; |
| 532 node.annotations = annotations; |
| 533 node.function = function; |
| 534 node.function?.parent = node; |
| 535 node.transformerFlags = transformerFlags; |
| 536 } |
| 537 return node; |
451 } | 538 } |
452 | 539 |
453 Initializer readInitializer() { | 540 Initializer readInitializer() { |
454 int tag = readByte(); | 541 int tag = readByte(); |
455 switch (tag) { | 542 switch (tag) { |
456 case Tag.InvalidInitializer: | 543 case Tag.InvalidInitializer: |
457 return new InvalidInitializer(); | 544 return new InvalidInitializer(); |
458 case Tag.FieldInitializer: | 545 case Tag.FieldInitializer: |
459 return new FieldInitializer(readMemberReference(), readExpression()); | 546 return new FieldInitializer.byReference( |
| 547 readMemberReference(), readExpression()); |
460 case Tag.SuperInitializer: | 548 case Tag.SuperInitializer: |
461 return new SuperInitializer(readMemberReference(), readArguments()); | 549 return new SuperInitializer.byReference( |
| 550 readMemberReference(), readArguments()); |
462 case Tag.RedirectingInitializer: | 551 case Tag.RedirectingInitializer: |
463 return new RedirectingInitializer( | 552 return new RedirectingInitializer.byReference( |
464 readMemberReference(), readArguments()); | 553 readMemberReference(), readArguments()); |
465 case Tag.LocalInitializer: | 554 case Tag.LocalInitializer: |
466 return new LocalInitializer(readAndPushVariableDeclaration()); | 555 return new LocalInitializer(readAndPushVariableDeclaration()); |
467 default: | 556 default: |
468 throw fail('Invalid initializer tag: $tag'); | 557 throw fail('Invalid initializer tag: $tag'); |
469 } | 558 } |
470 } | 559 } |
471 | 560 |
472 FunctionNode readFunctionNodeOption() { | 561 FunctionNode readFunctionNodeOption() { |
473 return readAndCheckOptionTag() ? readFunctionNode() : null; | 562 return readAndCheckOptionTag() ? readFunctionNode() : null; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 int offset = readOffset(); | 653 int offset = readOffset(); |
565 return new VariableSet(readVariableReference(), readExpression()) | 654 return new VariableSet(readVariableReference(), readExpression()) |
566 ..fileOffset = offset; | 655 ..fileOffset = offset; |
567 case Tag.SpecializedVariableSet: | 656 case Tag.SpecializedVariableSet: |
568 int index = tagByte & Tag.SpecializedPayloadMask; | 657 int index = tagByte & Tag.SpecializedPayloadMask; |
569 int offset = readOffset(); | 658 int offset = readOffset(); |
570 return new VariableSet(variableStack[index], readExpression()) | 659 return new VariableSet(variableStack[index], readExpression()) |
571 ..fileOffset = offset; | 660 ..fileOffset = offset; |
572 case Tag.PropertyGet: | 661 case Tag.PropertyGet: |
573 int offset = readOffset(); | 662 int offset = readOffset(); |
574 return new PropertyGet( | 663 return new PropertyGet.byReference( |
575 readExpression(), readName(), readMemberReference(allowNull: true)) | 664 readExpression(), readName(), readMemberReference(allowNull: true)) |
576 ..fileOffset = offset; | 665 ..fileOffset = offset; |
577 case Tag.PropertySet: | 666 case Tag.PropertySet: |
578 int offset = readOffset(); | 667 int offset = readOffset(); |
579 return new PropertySet(readExpression(), readName(), readExpression(), | 668 return new PropertySet.byReference( |
| 669 readExpression(), |
| 670 readName(), |
| 671 readExpression(), |
580 readMemberReference(allowNull: true))..fileOffset = offset; | 672 readMemberReference(allowNull: true))..fileOffset = offset; |
581 case Tag.SuperPropertyGet: | 673 case Tag.SuperPropertyGet: |
582 addTransformerFlag(TransformerFlag.superCalls); | 674 addTransformerFlag(TransformerFlag.superCalls); |
583 return new SuperPropertyGet( | 675 return new SuperPropertyGet.byReference( |
584 readName(), readMemberReference(allowNull: true)); | 676 readName(), readMemberReference(allowNull: true)); |
585 case Tag.SuperPropertySet: | 677 case Tag.SuperPropertySet: |
586 addTransformerFlag(TransformerFlag.superCalls); | 678 addTransformerFlag(TransformerFlag.superCalls); |
587 return new SuperPropertySet( | 679 return new SuperPropertySet.byReference( |
588 readName(), readExpression(), readMemberReference(allowNull: true)); | 680 readName(), readExpression(), readMemberReference(allowNull: true)); |
589 case Tag.DirectPropertyGet: | 681 case Tag.DirectPropertyGet: |
590 return new DirectPropertyGet(readExpression(), readMemberReference()); | 682 return new DirectPropertyGet.byReference( |
| 683 readExpression(), readMemberReference()); |
591 case Tag.DirectPropertySet: | 684 case Tag.DirectPropertySet: |
592 return new DirectPropertySet( | 685 return new DirectPropertySet.byReference( |
593 readExpression(), readMemberReference(), readExpression()); | 686 readExpression(), readMemberReference(), readExpression()); |
594 case Tag.StaticGet: | 687 case Tag.StaticGet: |
595 int offset = readOffset(); | 688 int offset = readOffset(); |
596 return new StaticGet(readMemberReference())..fileOffset = offset; | 689 return new StaticGet.byReference(readMemberReference()) |
| 690 ..fileOffset = offset; |
597 case Tag.StaticSet: | 691 case Tag.StaticSet: |
598 return new StaticSet(readMemberReference(), readExpression()); | 692 return new StaticSet.byReference( |
| 693 readMemberReference(), readExpression()); |
599 case Tag.MethodInvocation: | 694 case Tag.MethodInvocation: |
600 int offset = readOffset(); | 695 int offset = readOffset(); |
601 return new MethodInvocation( | 696 return new MethodInvocation.byReference( |
602 readExpression(), | 697 readExpression(), |
603 readName(), | 698 readName(), |
604 readArguments(), | 699 readArguments(), |
605 readMemberReference(allowNull: true))..fileOffset = offset; | 700 readMemberReference(allowNull: true))..fileOffset = offset; |
606 case Tag.SuperMethodInvocation: | 701 case Tag.SuperMethodInvocation: |
607 int offset = readOffset(); | 702 int offset = readOffset(); |
608 addTransformerFlag(TransformerFlag.superCalls); | 703 addTransformerFlag(TransformerFlag.superCalls); |
609 return new SuperMethodInvocation( | 704 return new SuperMethodInvocation.byReference( |
610 readName(), readArguments(), readMemberReference(allowNull: true)) | 705 readName(), readArguments(), readMemberReference(allowNull: true)) |
611 ..fileOffset = offset; | 706 ..fileOffset = offset; |
612 case Tag.DirectMethodInvocation: | 707 case Tag.DirectMethodInvocation: |
613 return new DirectMethodInvocation( | 708 return new DirectMethodInvocation.byReference( |
614 readExpression(), readMemberReference(), readArguments()); | 709 readExpression(), readMemberReference(), readArguments()); |
615 case Tag.StaticInvocation: | 710 case Tag.StaticInvocation: |
616 int offset = readOffset(); | 711 int offset = readOffset(); |
617 return new StaticInvocation(readMemberReference(), readArguments(), | 712 return new StaticInvocation.byReference( |
618 isConst: false)..fileOffset = offset; | 713 readMemberReference(), readArguments(), isConst: false) |
| 714 ..fileOffset = offset; |
619 case Tag.ConstStaticInvocation: | 715 case Tag.ConstStaticInvocation: |
620 int offset = readOffset(); | 716 int offset = readOffset(); |
621 return new StaticInvocation(readMemberReference(), readArguments(), | 717 return new StaticInvocation.byReference( |
622 isConst: true)..fileOffset = offset; | 718 readMemberReference(), readArguments(), isConst: true) |
| 719 ..fileOffset = offset; |
623 case Tag.ConstructorInvocation: | 720 case Tag.ConstructorInvocation: |
624 int offset = readOffset(); | 721 int offset = readOffset(); |
625 return new ConstructorInvocation(readMemberReference(), readArguments(), | 722 return new ConstructorInvocation.byReference( |
626 isConst: false)..fileOffset = offset; | 723 readMemberReference(), readArguments(), isConst: false) |
| 724 ..fileOffset = offset; |
627 case Tag.ConstConstructorInvocation: | 725 case Tag.ConstConstructorInvocation: |
628 int offset = readOffset(); | 726 int offset = readOffset(); |
629 return new ConstructorInvocation(readMemberReference(), readArguments(), | 727 return new ConstructorInvocation.byReference( |
630 isConst: true)..fileOffset = offset; | 728 readMemberReference(), readArguments(), isConst: true) |
| 729 ..fileOffset = offset; |
631 case Tag.Not: | 730 case Tag.Not: |
632 return new Not(readExpression()); | 731 return new Not(readExpression()); |
633 case Tag.LogicalExpression: | 732 case Tag.LogicalExpression: |
634 return new LogicalExpression(readExpression(), | 733 return new LogicalExpression(readExpression(), |
635 logicalOperatorToString(readByte()), readExpression()); | 734 logicalOperatorToString(readByte()), readExpression()); |
636 case Tag.ConditionalExpression: | 735 case Tag.ConditionalExpression: |
637 return new ConditionalExpression(readExpression(), readExpression(), | 736 return new ConditionalExpression(readExpression(), readExpression(), |
638 readExpression(), readDartTypeOption()); | 737 readExpression(), readDartTypeOption()); |
639 case Tag.StringConcatenation: | 738 case Tag.StringConcatenation: |
640 int offset = readOffset(); | 739 int offset = readOffset(); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 | 948 |
850 Block readBlock() { | 949 Block readBlock() { |
851 int stackHeight = variableStack.length; | 950 int stackHeight = variableStack.length; |
852 var body = readStatementList(); | 951 var body = readStatementList(); |
853 variableStack.length = stackHeight; | 952 variableStack.length = stackHeight; |
854 return new Block(body); | 953 return new Block(body); |
855 } | 954 } |
856 | 955 |
857 Supertype readSupertype() { | 956 Supertype readSupertype() { |
858 InterfaceType type = readDartType(); | 957 InterfaceType type = readDartType(); |
859 return new Supertype(type.classNode, type.typeArguments); | 958 return new Supertype.byReference(type.className, type.typeArguments); |
860 } | 959 } |
861 | 960 |
862 Supertype readSupertypeOption() { | 961 Supertype readSupertypeOption() { |
863 return readAndCheckOptionTag() ? readSupertype() : null; | 962 return readAndCheckOptionTag() ? readSupertype() : null; |
864 } | 963 } |
865 | 964 |
866 List<Supertype> readSupertypeList() { | 965 List<Supertype> readSupertypeList() { |
867 return new List<Supertype>.generate(readUInt(), (i) => readSupertype()); | 966 return new List<Supertype>.generate(readUInt(), (i) => readSupertype()); |
868 } | 967 } |
869 | 968 |
(...skipping 18 matching lines...) Expand all Loading... |
888 switch (tag) { | 987 switch (tag) { |
889 case Tag.BottomType: | 988 case Tag.BottomType: |
890 return const BottomType(); | 989 return const BottomType(); |
891 case Tag.InvalidType: | 990 case Tag.InvalidType: |
892 return const InvalidType(); | 991 return const InvalidType(); |
893 case Tag.DynamicType: | 992 case Tag.DynamicType: |
894 return const DynamicType(); | 993 return const DynamicType(); |
895 case Tag.VoidType: | 994 case Tag.VoidType: |
896 return const VoidType(); | 995 return const VoidType(); |
897 case Tag.InterfaceType: | 996 case Tag.InterfaceType: |
898 return new InterfaceType(readClassReference(), readDartTypeList()); | 997 return new InterfaceType.byReference( |
| 998 readClassReference(), readDartTypeList()); |
899 case Tag.SimpleInterfaceType: | 999 case Tag.SimpleInterfaceType: |
900 return new InterfaceType(readClassReference(), const <DartType>[]); | 1000 return new InterfaceType.byReference( |
| 1001 readClassReference(), const <DartType>[]); |
901 case Tag.FunctionType: | 1002 case Tag.FunctionType: |
902 int typeParameterStackHeight = typeParameterStack.length; | 1003 int typeParameterStackHeight = typeParameterStack.length; |
903 var typeParameters = readAndPushTypeParameterList(); | 1004 var typeParameters = readAndPushTypeParameterList(); |
904 var requiredParameterCount = readUInt(); | 1005 var requiredParameterCount = readUInt(); |
905 var positional = readDartTypeList(); | 1006 var positional = readDartTypeList(); |
906 var named = readNamedTypeList(); | 1007 var named = readNamedTypeList(); |
907 var returnType = readDartType(); | 1008 var returnType = readDartType(); |
908 typeParameterStack.length = typeParameterStackHeight; | 1009 typeParameterStack.length = typeParameterStackHeight; |
909 return new FunctionType(positional, returnType, | 1010 return new FunctionType(positional, returnType, |
910 typeParameters: typeParameters, | 1011 typeParameters: typeParameters, |
(...skipping 11 matching lines...) Expand all Loading... |
922 } | 1023 } |
923 } | 1024 } |
924 | 1025 |
925 List<TypeParameter> readAndPushTypeParameterList( | 1026 List<TypeParameter> readAndPushTypeParameterList( |
926 [List<TypeParameter> list, TreeNode parent]) { | 1027 [List<TypeParameter> list, TreeNode parent]) { |
927 int length = readUInt(); | 1028 int length = readUInt(); |
928 if (length == 0) return list ?? <TypeParameter>[]; | 1029 if (length == 0) return list ?? <TypeParameter>[]; |
929 if (list == null) { | 1030 if (list == null) { |
930 list = new List<TypeParameter>.generate( | 1031 list = new List<TypeParameter>.generate( |
931 length, (i) => new TypeParameter(null, null)..parent = parent); | 1032 length, (i) => new TypeParameter(null, null)..parent = parent); |
932 } else { | 1033 } else if (list.length != length) { |
933 list.length = length; | 1034 list.length = length; |
934 for (int i = 0; i < length; ++i) { | 1035 for (int i = 0; i < length; ++i) { |
935 list[i] = new TypeParameter(null, null)..parent = parent; | 1036 list[i] = new TypeParameter(null, null)..parent = parent; |
936 } | 1037 } |
937 } | 1038 } |
938 typeParameterStack.addAll(list); | 1039 typeParameterStack.addAll(list); |
939 for (int i = 0; i < list.length; ++i) { | 1040 for (int i = 0; i < list.length; ++i) { |
940 readTypeParameter(list[i]); | 1041 readTypeParameter(list[i]); |
941 } | 1042 } |
942 return list; | 1043 return list; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 isFinal: flags & 0x1 != 0, | 1089 isFinal: flags & 0x1 != 0, |
989 isConst: flags & 0x2 != 0)..fileOffset = offset; | 1090 isConst: flags & 0x2 != 0)..fileOffset = offset; |
990 } | 1091 } |
991 | 1092 |
992 int readOffset() { | 1093 int readOffset() { |
993 // Offset is saved as unsigned, | 1094 // Offset is saved as unsigned, |
994 // but actually ranges from -1 and up (thus the -1) | 1095 // but actually ranges from -1 and up (thus the -1) |
995 return readUInt() - 1; | 1096 return readUInt() - 1; |
996 } | 1097 } |
997 } | 1098 } |
OLD | NEW |