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_to_binary; | 4 library kernel.ast_to_binary; |
5 | 5 |
6 import '../ast.dart'; | 6 import '../ast.dart'; |
7 import '../import_table.dart'; | 7 import '../import_table.dart'; |
8 import 'tag.dart'; | 8 import 'tag.dart'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:typed_data'; | 10 import 'dart:typed_data'; |
11 import 'dart:collection'; | 11 import 'dart:collection'; |
12 | 12 |
13 /// Writes to a binary file. | 13 /// Writes to a binary file. |
14 /// | 14 /// |
15 /// A [BinaryPrinter] can be used to write one file and must then be | 15 /// A [BinaryPrinter] can be used to write one file and must then be |
16 /// discarded. | 16 /// discarded. |
17 class BinaryPrinter extends Visitor { | 17 class BinaryPrinter extends Visitor { |
18 ImportTable _importTable; | |
19 | |
20 VariableIndexer _variableIndexer; | 18 VariableIndexer _variableIndexer; |
21 LabelIndexer _labelIndexer; | 19 LabelIndexer _labelIndexer; |
22 SwitchCaseIndexer _switchCaseIndexer; | 20 SwitchCaseIndexer _switchCaseIndexer; |
23 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); | 21 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); |
24 final GlobalIndexer _globalIndexer; | |
25 final StringIndexer _stringIndexer = new StringIndexer(); | 22 final StringIndexer _stringIndexer = new StringIndexer(); |
26 final StringIndexer _sourceUriIndexer = new StringIndexer(); | 23 final StringIndexer _sourceUriIndexer = new StringIndexer(); |
27 Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{}; | 24 Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{}; |
28 | 25 |
29 final BufferedSink _sink; | 26 final BufferedSink _sink; |
30 | 27 |
31 /// Create a printer that writes to the given [sink]. | 28 /// Create a printer that writes to the given [sink]. |
32 /// | 29 /// |
33 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 30 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
34 /// one. | 31 /// one. |
35 /// | 32 /// |
36 /// If multiple binaries are to be written based on the same IR, a shared | 33 /// If multiple binaries are to be written based on the same IR, a shared |
37 /// [globalIndexer] may be passed in to avoid rebuilding the same indices | 34 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
38 /// in every printer. | 35 /// in every printer. |
39 BinaryPrinter(Sink<List<int>> sink, {GlobalIndexer globalIndexer}) | 36 BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink); |
40 : _sink = new BufferedSink(sink), | |
41 _globalIndexer = globalIndexer ?? new GlobalIndexer(); | |
42 | 37 |
43 void _flush() { | 38 void _flush() { |
44 _sink.flushAndDestroy(); | 39 _sink.flushAndDestroy(); |
45 } | 40 } |
46 | 41 |
47 void writeByte(int byte) { | 42 void writeByte(int byte) { |
48 _sink.addByte(byte); | 43 _sink.addByte(byte); |
49 } | 44 } |
50 | 45 |
51 void writeBytes(List<int> bytes) { | 46 void writeBytes(List<int> bytes) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 if (node == null) { | 121 if (node == null) { |
127 writeByte(Tag.Nothing); | 122 writeByte(Tag.Nothing); |
128 } else { | 123 } else { |
129 writeByte(Tag.Something); | 124 writeByte(Tag.Something); |
130 writeClassReference(node.baseClass, allowNull: true); | 125 writeClassReference(node.baseClass, allowNull: true); |
131 writeByte(node.baseClassKind.index); | 126 writeByte(node.baseClassKind.index); |
132 writeByte(node.valueBits); | 127 writeByte(node.valueBits); |
133 } | 128 } |
134 } | 129 } |
135 | 130 |
| 131 void writeLinkTable(Program program) { |
| 132 List<CanonicalName> list = <CanonicalName>[]; |
| 133 void visitCanonicalName(CanonicalName node) { |
| 134 node.index = list.length; |
| 135 list.add(node); |
| 136 node.children.forEach(visitCanonicalName); |
| 137 } |
| 138 |
| 139 for (var library in program.libraries) { |
| 140 visitCanonicalName(library.canonicalName); |
| 141 } |
| 142 writeList(list, writeCanonicalNameEntry); |
| 143 } |
| 144 |
| 145 void writeCanonicalNameEntry(CanonicalName node) { |
| 146 var parent = node.parent; |
| 147 if (parent.isRoot) { |
| 148 writeByte(0); |
| 149 } else { |
| 150 writeUInt30(parent.index + 1); |
| 151 } |
| 152 writeStringReference(node.name); |
| 153 } |
| 154 |
136 void writeProgramFile(Program program) { | 155 void writeProgramFile(Program program) { |
| 156 program.computeCanonicalNames(); |
137 writeMagicWord(Tag.ProgramFile); | 157 writeMagicWord(Tag.ProgramFile); |
138 _importTable = new ProgramImportTable(program); | 158 _stringIndexer.scanProgram(program); |
139 _stringIndexer.build(program); | |
140 writeStringTable(_stringIndexer); | 159 writeStringTable(_stringIndexer); |
141 writeUriToSource(program); | 160 writeUriToSource(program); |
| 161 writeLinkTable(program); |
142 writeList(program.libraries, writeNode); | 162 writeList(program.libraries, writeNode); |
143 writeMemberReference(program.mainMethod, allowNull: true); | 163 writeMemberReference(program.mainMethod, allowNull: true); |
144 _flush(); | 164 _flush(); |
145 } | 165 } |
146 | 166 |
147 void writeUriToSource(Program program) { | 167 void writeUriToSource(Program program) { |
148 program.uriToSource.keys.forEach((uri) { | 168 program.uriToSource.keys.forEach((uri) { |
149 _sourceUriIndexer.put(uri); | 169 _sourceUriIndexer.put(uri); |
150 }); | 170 }); |
151 writeStringTable(_sourceUriIndexer); | 171 writeStringTable(_sourceUriIndexer); |
152 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 172 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
153 String uri = _sourceUriIndexer.entries[i].value; | 173 String uri = _sourceUriIndexer.entries[i].value; |
154 Source source = program.uriToSource[uri] ?? new Source([], ''); | 174 Source source = program.uriToSource[uri] ?? new Source([], ''); |
155 String sourceCode = source.source; | 175 String sourceCode = source.source; |
156 writeStringTableEntry(sourceCode); | 176 writeStringTableEntry(sourceCode); |
157 List<int> lineStarts = source.lineStarts; | 177 List<int> lineStarts = source.lineStarts; |
158 writeUInt30(lineStarts.length); | 178 writeUInt30(lineStarts.length); |
159 int previousLineStart = 0; | 179 int previousLineStart = 0; |
160 lineStarts.forEach((lineStart) { | 180 lineStarts.forEach((lineStart) { |
161 writeUInt30(lineStart - previousLineStart); | 181 writeUInt30(lineStart - previousLineStart); |
162 previousLineStart = lineStart; | 182 previousLineStart = lineStart; |
163 }); | 183 }); |
164 } | 184 } |
165 } | 185 } |
166 | 186 |
167 void writeLibraryImportTable(LibraryImportTable imports) { | |
168 writeList(imports.importPaths, writeStringReference); | |
169 } | |
170 | |
171 void writeLibraryReference(Library node) { | |
172 int index = _importTable.getImportIndex(node); | |
173 if (index == -1) { | |
174 throw 'Missing import for library: ${node.importUri}'; | |
175 } | |
176 writeUInt30(index); | |
177 } | |
178 | |
179 void writeDeferredImportReference(DeferredImport node) { | 187 void writeDeferredImportReference(DeferredImport node) { |
180 int index = _deferredImportIndexer[node]; | 188 int index = _deferredImportIndexer[node]; |
181 if (index == null) { | 189 if (index == null) { |
182 throw 'Reference to deferred import $node out of scope'; | 190 throw 'Reference to deferred import $node out of scope'; |
183 } | 191 } |
184 writeUInt30(index); | 192 writeUInt30(index); |
185 } | 193 } |
186 | 194 |
187 void writeClassIndex(Class node) { | 195 void writeReference(Reference reference) { |
188 writeUInt30(_globalIndexer[node]); | 196 if (reference == null) { |
189 } | 197 writeByte(0); |
190 | 198 } else { |
191 void writeClassReference(Class node, {bool allowNull: false}) { | 199 CanonicalName name = reference.canonicalName; |
192 if (node == null) { | 200 if (name == null) { |
193 if (allowNull) { | 201 throw 'Missing canonical name for $reference'; |
194 writeByte(Tag.NullReference); | |
195 } else { | |
196 throw 'Expected a class reference to be valid but was `null`.'; | |
197 } | 202 } |
198 } else { | 203 writeUInt30(name.index + 1); |
199 node.acceptReference(this); | |
200 } | 204 } |
201 } | 205 } |
202 | 206 |
203 void writeMemberReference(Member node, {bool allowNull: false}) { | 207 void writeCanonicalNameReference(CanonicalName name) { |
204 if (node == null) { | 208 if (name == null) { |
205 if (allowNull) { | 209 writeByte(0); |
206 writeByte(Tag.NullReference); | |
207 } else { | |
208 throw 'Expected a member reference to be valid but was `null`.'; | |
209 } | |
210 } else { | 210 } else { |
211 node.acceptReference(this); | 211 writeUInt30(name.index + 1); |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
| 215 void writeLibraryReference(Library node) { |
| 216 writeCanonicalNameReference(node.canonicalName); |
| 217 } |
| 218 |
215 writeOffset(TreeNode node, int offset) { | 219 writeOffset(TreeNode node, int offset) { |
216 // TODO(jensj): Delta-encoding. | 220 // TODO(jensj): Delta-encoding. |
217 // File offset ranges from -1 and up, | 221 // File offset ranges from -1 and up, |
218 // but is here saved as unsigned (thus the +1) | 222 // but is here saved as unsigned (thus the +1) |
219 writeUInt30(offset + 1); | 223 writeUInt30(offset + 1); |
220 } | 224 } |
221 | 225 |
222 void visitClassReference(Class node) { | 226 void writeClassReference(Class class_, {bool allowNull: false}) { |
223 var library = node.enclosingLibrary; | 227 if (class_ == null && !allowNull) { |
224 writeByte(node.isMixinApplication | 228 throw 'Expected a class reference to be valid but was `null`.'; |
225 ? Tag.MixinClassReference | 229 } |
226 : Tag.NormalClassReference); | 230 writeCanonicalNameReference(getCanonicalNameOfClass(class_)); |
227 writeLibraryReference(library); | |
228 writeClassIndex(node); | |
229 } | 231 } |
230 | 232 |
231 void visitFieldReference(Field node) { | 233 void writeMemberReference(Member member, {bool allowNull: false}) { |
232 if (node.enclosingClass != null) { | 234 if (member == null && !allowNull) { |
233 writeByte(Tag.ClassFieldReference); | 235 throw 'Expected a member reference to be valid but was `null`.'; |
234 Class classNode = node.enclosingClass; | |
235 writeClassReference(classNode); | |
236 writeUInt30(_globalIndexer[node]); | |
237 } else { | |
238 writeByte(Tag.LibraryFieldReference); | |
239 writeLibraryReference(node.enclosingLibrary); | |
240 writeUInt30(_globalIndexer[node]); | |
241 } | 236 } |
242 } | 237 writeCanonicalNameReference(getCanonicalNameOfMember(member)); |
243 | |
244 void visitConstructorReference(Constructor node) { | |
245 writeByte(Tag.ClassConstructorReference); | |
246 writeClassReference(node.enclosingClass); | |
247 writeUInt30(_globalIndexer[node]); | |
248 } | |
249 | |
250 void visitProcedureReference(Procedure node) { | |
251 if (node.enclosingClass != null) { | |
252 writeByte(Tag.ClassProcedureReference); | |
253 Class classNode = node.enclosingClass; | |
254 writeClassReference(classNode); | |
255 writeUInt30(_globalIndexer[node]); | |
256 } else { | |
257 writeByte(Tag.LibraryProcedureReference); | |
258 writeLibraryReference(node.enclosingLibrary); | |
259 writeUInt30(_globalIndexer[node]); | |
260 } | |
261 } | 238 } |
262 | 239 |
263 void writeName(Name node) { | 240 void writeName(Name node) { |
264 writeStringReference(node.name); | 241 writeStringReference(node.name); |
265 // TODO: Consider a more compressed format for private names within the | 242 // TODO: Consider a more compressed format for private names within the |
266 // enclosing library. | 243 // enclosing library. |
267 if (node.isPrivate) { | 244 if (node.isPrivate) { |
268 writeLibraryReference(node.library); | 245 writeLibraryReference(node.library); |
269 } | 246 } |
270 } | 247 } |
271 | 248 |
272 bool insideExternalLibrary = false; | 249 bool insideExternalLibrary = false; |
273 | 250 |
274 visitLibrary(Library node) { | 251 visitLibrary(Library node) { |
275 insideExternalLibrary = node.isExternal; | 252 insideExternalLibrary = node.isExternal; |
276 writeByte(insideExternalLibrary ? 1 : 0); | 253 writeByte(insideExternalLibrary ? 1 : 0); |
| 254 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); |
277 writeStringReference(node.name ?? ''); | 255 writeStringReference(node.name ?? ''); |
278 writeStringReference('${node.importUri}'); | |
279 // TODO(jensj): We save (almost) the same URI twice. | 256 // TODO(jensj): We save (almost) the same URI twice. |
280 writeUriReference(node.fileUri ?? ''); | 257 writeUriReference(node.fileUri ?? ''); |
281 writeDeferredImports(node); | 258 writeDeferredImports(node); |
282 writeNodeList(node.classes); | 259 writeNodeList(node.classes); |
283 writeNodeList(node.fields); | 260 writeNodeList(node.fields); |
284 writeNodeList(node.procedures); | 261 writeNodeList(node.procedures); |
285 } | 262 } |
286 | 263 |
287 void writeDeferredImports(Library library) { | 264 void writeDeferredImports(Library library) { |
288 _deferredImportIndexer = library.deferredImports.isEmpty | 265 _deferredImportIndexer = library.deferredImports.isEmpty |
(...skipping 22 matching lines...) Expand all Loading... |
311 } | 288 } |
312 | 289 |
313 int _encodeClassFlags(bool isAbstract, ClassLevel level) { | 290 int _encodeClassFlags(bool isAbstract, ClassLevel level) { |
314 int abstactFlag = isAbstract ? 1 : 0; | 291 int abstactFlag = isAbstract ? 1 : 0; |
315 int levelFlags = (level.index - 1) << 1; | 292 int levelFlags = (level.index - 1) << 1; |
316 return abstactFlag | levelFlags; | 293 return abstactFlag | levelFlags; |
317 } | 294 } |
318 | 295 |
319 visitClass(Class node) { | 296 visitClass(Class node) { |
320 int flags = _encodeClassFlags(node.isAbstract, node.level); | 297 int flags = _encodeClassFlags(node.isAbstract, node.level); |
321 if (node.isMixinApplication) { | 298 if (node.canonicalName == null) { |
322 writeByte(Tag.MixinClass); | 299 throw 'Missing canonical name for $node'; |
323 writeOffset(node, node.fileOffset); | |
324 writeByte(flags); | |
325 writeStringReference(node.name ?? ''); | |
326 writeUriReference(node.fileUri ?? ''); | |
327 writeAnnotationList(node.annotations); | |
328 _typeParameterIndexer.enter(node.typeParameters); | |
329 writeNodeList(node.typeParameters); | |
330 writeNode(node.supertype); | |
331 writeNode(node.mixedInType); | |
332 writeNodeList(node.implementedTypes); | |
333 writeNodeList(node.constructors); | |
334 _typeParameterIndexer.exit(node.typeParameters); | |
335 } else { | |
336 writeByte(Tag.NormalClass); | |
337 writeOffset(node, node.fileOffset); | |
338 writeByte(flags); | |
339 writeStringReference(node.name ?? ''); | |
340 writeUriReference(node.fileUri ?? ''); | |
341 writeAnnotationList(node.annotations); | |
342 _typeParameterIndexer.enter(node.typeParameters); | |
343 writeNodeList(node.typeParameters); | |
344 writeOptionalNode(node.supertype); | |
345 writeNodeList(node.implementedTypes); | |
346 writeNodeList(node.fields); | |
347 writeNodeList(node.constructors); | |
348 writeNodeList(node.procedures); | |
349 _typeParameterIndexer.exit(node.typeParameters); | |
350 } | 300 } |
| 301 writeByte(Tag.Class); |
| 302 writeCanonicalNameReference(getCanonicalNameOfClass(node)); |
| 303 writeOffset(node, node.fileOffset); |
| 304 writeByte(flags); |
| 305 writeStringReference(node.name ?? ''); |
| 306 writeUriReference(node.fileUri ?? ''); |
| 307 writeAnnotationList(node.annotations); |
| 308 _typeParameterIndexer.enter(node.typeParameters); |
| 309 writeNodeList(node.typeParameters); |
| 310 writeOptionalNode(node.supertype); |
| 311 writeOptionalNode(node.mixedInType); |
| 312 writeNodeList(node.implementedTypes); |
| 313 writeNodeList(node.fields); |
| 314 writeNodeList(node.constructors); |
| 315 writeNodeList(node.procedures); |
| 316 _typeParameterIndexer.exit(node.typeParameters); |
351 } | 317 } |
352 | 318 |
353 static final Name _emptyName = new Name(''); | 319 static final Name _emptyName = new Name(''); |
354 | 320 |
355 visitConstructor(Constructor node) { | 321 visitConstructor(Constructor node) { |
| 322 if (node.canonicalName == null) { |
| 323 throw 'Missing canonical name for $node'; |
| 324 } |
356 _variableIndexer = new VariableIndexer(); | 325 _variableIndexer = new VariableIndexer(); |
357 writeByte(Tag.Constructor); | 326 writeByte(Tag.Constructor); |
| 327 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
358 writeOffset(node, node.fileOffset); | 328 writeOffset(node, node.fileOffset); |
359 writeOffset(node, node.fileEndOffset); | 329 writeOffset(node, node.fileEndOffset); |
360 writeByte(node.flags); | 330 writeByte(node.flags); |
361 writeName(node.name ?? _emptyName); | 331 writeName(node.name ?? _emptyName); |
362 writeAnnotationList(node.annotations); | 332 writeAnnotationList(node.annotations); |
363 assert(node.function.typeParameters.isEmpty); | 333 assert(node.function.typeParameters.isEmpty); |
364 writeNode(node.function); | 334 writeNode(node.function); |
365 // Parameters are in scope in the initializers. | 335 // Parameters are in scope in the initializers. |
366 _variableIndexer.restoreScope(node.function.positionalParameters.length + | 336 _variableIndexer.restoreScope(node.function.positionalParameters.length + |
367 node.function.namedParameters.length); | 337 node.function.namedParameters.length); |
368 writeNodeList(node.initializers); | 338 writeNodeList(node.initializers); |
369 _variableIndexer = null; | 339 _variableIndexer = null; |
370 } | 340 } |
371 | 341 |
372 visitProcedure(Procedure node) { | 342 visitProcedure(Procedure node) { |
| 343 if (node.canonicalName == null) { |
| 344 throw 'Missing canonical name for $node'; |
| 345 } |
373 _variableIndexer = new VariableIndexer(); | 346 _variableIndexer = new VariableIndexer(); |
374 writeByte(Tag.Procedure); | 347 writeByte(Tag.Procedure); |
| 348 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
375 writeOffset(node, node.fileOffset); | 349 writeOffset(node, node.fileOffset); |
376 writeOffset(node, node.fileEndOffset); | 350 writeOffset(node, node.fileEndOffset); |
377 writeByte(node.kind.index); | 351 writeByte(node.kind.index); |
378 writeByte(node.flags); | 352 writeByte(node.flags); |
379 writeName(node.name ?? ''); | 353 writeName(node.name ?? ''); |
380 writeUriReference(node.fileUri ?? ''); | 354 writeUriReference(node.fileUri ?? ''); |
381 writeAnnotationList(node.annotations); | 355 writeAnnotationList(node.annotations); |
382 writeOptionalNode(node.function); | 356 writeOptionalNode(node.function); |
383 _variableIndexer = null; | 357 _variableIndexer = null; |
384 } | 358 } |
385 | 359 |
386 visitField(Field node) { | 360 visitField(Field node) { |
| 361 if (node.canonicalName == null) { |
| 362 throw 'Missing canonical name for $node'; |
| 363 } |
387 _variableIndexer = new VariableIndexer(); | 364 _variableIndexer = new VariableIndexer(); |
388 writeByte(Tag.Field); | 365 writeByte(Tag.Field); |
| 366 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
389 writeOffset(node, node.fileOffset); | 367 writeOffset(node, node.fileOffset); |
390 writeOffset(node, node.fileEndOffset); | 368 writeOffset(node, node.fileEndOffset); |
391 writeByte(node.flags); | 369 writeByte(node.flags); |
392 writeName(node.name ?? ''); | 370 writeName(node.name); |
393 writeUriReference(node.fileUri ?? ''); | 371 writeUriReference(node.fileUri ?? ''); |
394 writeAnnotationList(node.annotations); | 372 writeAnnotationList(node.annotations); |
395 writeNode(node.type); | 373 writeNode(node.type); |
396 writeOptionalInferredValue(node.inferredValue); | 374 writeOptionalInferredValue(node.inferredValue); |
397 writeOptionalNode(node.initializer); | 375 writeOptionalNode(node.initializer); |
398 _variableIndexer = null; | 376 _variableIndexer = null; |
399 } | 377 } |
400 | 378 |
401 visitInvalidInitializer(InvalidInitializer node) { | 379 visitInvalidInitializer(InvalidInitializer node) { |
402 writeByte(Tag.InvalidInitializer); | 380 writeByte(Tag.InvalidInitializer); |
403 } | 381 } |
404 | 382 |
405 visitFieldInitializer(FieldInitializer node) { | 383 visitFieldInitializer(FieldInitializer node) { |
406 writeByte(Tag.FieldInitializer); | 384 writeByte(Tag.FieldInitializer); |
407 writeMemberReference(node.field); | 385 writeReference(node.fieldReference); |
408 writeNode(node.value); | 386 writeNode(node.value); |
409 } | 387 } |
410 | 388 |
411 visitSuperInitializer(SuperInitializer node) { | 389 visitSuperInitializer(SuperInitializer node) { |
412 writeByte(Tag.SuperInitializer); | 390 writeByte(Tag.SuperInitializer); |
413 writeMemberReference(node.target); | 391 writeReference(node.targetReference); |
414 writeNode(node.arguments); | 392 writeNode(node.arguments); |
415 } | 393 } |
416 | 394 |
417 visitRedirectingInitializer(RedirectingInitializer node) { | 395 visitRedirectingInitializer(RedirectingInitializer node) { |
418 writeByte(Tag.RedirectingInitializer); | 396 writeByte(Tag.RedirectingInitializer); |
419 writeMemberReference(node.target); | 397 writeReference(node.targetReference); |
420 writeNode(node.arguments); | 398 writeNode(node.arguments); |
421 } | 399 } |
422 | 400 |
423 visitLocalInitializer(LocalInitializer node) { | 401 visitLocalInitializer(LocalInitializer node) { |
424 writeByte(Tag.LocalInitializer); | 402 writeByte(Tag.LocalInitializer); |
425 writeVariableDeclaration(node.variable); | 403 writeVariableDeclaration(node.variable); |
426 } | 404 } |
427 | 405 |
428 visitFunctionNode(FunctionNode node) { | 406 visitFunctionNode(FunctionNode node) { |
429 assert(_variableIndexer != null); | 407 assert(_variableIndexer != null); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 writeUInt30(_variableIndexer[node.variable]); | 462 writeUInt30(_variableIndexer[node.variable]); |
485 writeNode(node.value); | 463 writeNode(node.value); |
486 } | 464 } |
487 } | 465 } |
488 | 466 |
489 visitPropertyGet(PropertyGet node) { | 467 visitPropertyGet(PropertyGet node) { |
490 writeByte(Tag.PropertyGet); | 468 writeByte(Tag.PropertyGet); |
491 writeOffset(node, node.fileOffset); | 469 writeOffset(node, node.fileOffset); |
492 writeNode(node.receiver); | 470 writeNode(node.receiver); |
493 writeName(node.name); | 471 writeName(node.name); |
494 writeMemberReference(node.interfaceTarget, allowNull: true); | 472 writeReference(node.interfaceTargetReference); |
495 } | 473 } |
496 | 474 |
497 visitPropertySet(PropertySet node) { | 475 visitPropertySet(PropertySet node) { |
498 writeByte(Tag.PropertySet); | 476 writeByte(Tag.PropertySet); |
499 writeOffset(node, node.fileOffset); | 477 writeOffset(node, node.fileOffset); |
500 writeNode(node.receiver); | 478 writeNode(node.receiver); |
501 writeName(node.name); | 479 writeName(node.name); |
502 writeNode(node.value); | 480 writeNode(node.value); |
503 writeMemberReference(node.interfaceTarget, allowNull: true); | 481 writeReference(node.interfaceTargetReference); |
504 } | 482 } |
505 | 483 |
506 visitSuperPropertyGet(SuperPropertyGet node) { | 484 visitSuperPropertyGet(SuperPropertyGet node) { |
507 writeByte(Tag.SuperPropertyGet); | 485 writeByte(Tag.SuperPropertyGet); |
508 writeName(node.name); | 486 writeName(node.name); |
509 writeMemberReference(node.interfaceTarget, allowNull: true); | 487 writeReference(node.interfaceTargetReference); |
510 } | 488 } |
511 | 489 |
512 visitSuperPropertySet(SuperPropertySet node) { | 490 visitSuperPropertySet(SuperPropertySet node) { |
513 writeByte(Tag.SuperPropertySet); | 491 writeByte(Tag.SuperPropertySet); |
514 writeName(node.name); | 492 writeName(node.name); |
515 writeNode(node.value); | 493 writeNode(node.value); |
516 writeMemberReference(node.interfaceTarget, allowNull: true); | 494 writeReference(node.interfaceTargetReference); |
517 } | 495 } |
518 | 496 |
519 visitDirectPropertyGet(DirectPropertyGet node) { | 497 visitDirectPropertyGet(DirectPropertyGet node) { |
520 writeByte(Tag.DirectPropertyGet); | 498 writeByte(Tag.DirectPropertyGet); |
521 writeNode(node.receiver); | 499 writeNode(node.receiver); |
522 writeMemberReference(node.target); | 500 writeReference(node.targetReference); |
523 } | 501 } |
524 | 502 |
525 visitDirectPropertySet(DirectPropertySet node) { | 503 visitDirectPropertySet(DirectPropertySet node) { |
526 writeByte(Tag.DirectPropertySet); | 504 writeByte(Tag.DirectPropertySet); |
527 writeNode(node.receiver); | 505 writeNode(node.receiver); |
528 writeMemberReference(node.target); | 506 writeReference(node.targetReference); |
529 writeNode(node.value); | 507 writeNode(node.value); |
530 } | 508 } |
531 | 509 |
532 visitStaticGet(StaticGet node) { | 510 visitStaticGet(StaticGet node) { |
533 writeByte(Tag.StaticGet); | 511 writeByte(Tag.StaticGet); |
534 writeOffset(node, node.fileOffset); | 512 writeOffset(node, node.fileOffset); |
535 writeMemberReference(node.target); | 513 writeReference(node.targetReference); |
536 } | 514 } |
537 | 515 |
538 visitStaticSet(StaticSet node) { | 516 visitStaticSet(StaticSet node) { |
539 writeByte(Tag.StaticSet); | 517 writeByte(Tag.StaticSet); |
540 writeMemberReference(node.target); | 518 writeReference(node.targetReference); |
541 writeNode(node.value); | 519 writeNode(node.value); |
542 } | 520 } |
543 | 521 |
544 visitMethodInvocation(MethodInvocation node) { | 522 visitMethodInvocation(MethodInvocation node) { |
545 writeByte(Tag.MethodInvocation); | 523 writeByte(Tag.MethodInvocation); |
546 writeOffset(node, node.fileOffset); | 524 writeOffset(node, node.fileOffset); |
547 writeNode(node.receiver); | 525 writeNode(node.receiver); |
548 writeName(node.name); | 526 writeName(node.name); |
549 writeNode(node.arguments); | 527 writeNode(node.arguments); |
550 writeMemberReference(node.interfaceTarget, allowNull: true); | 528 writeReference(node.interfaceTargetReference); |
551 } | 529 } |
552 | 530 |
553 visitSuperMethodInvocation(SuperMethodInvocation node) { | 531 visitSuperMethodInvocation(SuperMethodInvocation node) { |
554 writeByte(Tag.SuperMethodInvocation); | 532 writeByte(Tag.SuperMethodInvocation); |
555 writeOffset(node, node.fileOffset); | 533 writeOffset(node, node.fileOffset); |
556 writeName(node.name); | 534 writeName(node.name); |
557 writeNode(node.arguments); | 535 writeNode(node.arguments); |
558 writeMemberReference(node.interfaceTarget, allowNull: true); | 536 writeReference(node.interfaceTargetReference); |
559 } | 537 } |
560 | 538 |
561 visitDirectMethodInvocation(DirectMethodInvocation node) { | 539 visitDirectMethodInvocation(DirectMethodInvocation node) { |
562 writeByte(Tag.DirectMethodInvocation); | 540 writeByte(Tag.DirectMethodInvocation); |
563 writeNode(node.receiver); | 541 writeNode(node.receiver); |
564 writeMemberReference(node.target); | 542 writeReference(node.targetReference); |
565 writeNode(node.arguments); | 543 writeNode(node.arguments); |
566 } | 544 } |
567 | 545 |
568 visitStaticInvocation(StaticInvocation node) { | 546 visitStaticInvocation(StaticInvocation node) { |
569 writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation); | 547 writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation); |
570 writeOffset(node, node.fileOffset); | 548 writeOffset(node, node.fileOffset); |
571 writeMemberReference(node.target); | 549 writeReference(node.targetReference); |
572 writeNode(node.arguments); | 550 writeNode(node.arguments); |
573 } | 551 } |
574 | 552 |
575 visitConstructorInvocation(ConstructorInvocation node) { | 553 visitConstructorInvocation(ConstructorInvocation node) { |
576 writeByte(node.isConst | 554 writeByte(node.isConst |
577 ? Tag.ConstConstructorInvocation | 555 ? Tag.ConstConstructorInvocation |
578 : Tag.ConstructorInvocation); | 556 : Tag.ConstructorInvocation); |
579 writeOffset(node, node.fileOffset); | 557 writeOffset(node, node.fileOffset); |
580 writeMemberReference(node.target); | 558 writeReference(node.targetReference); |
581 writeNode(node.arguments); | 559 writeNode(node.arguments); |
582 } | 560 } |
583 | 561 |
584 visitArguments(Arguments node) { | 562 visitArguments(Arguments node) { |
585 writeNodeList(node.types); | 563 writeNodeList(node.types); |
586 writeNodeList(node.positional); | 564 writeNodeList(node.positional); |
587 writeNodeList(node.named); | 565 writeNodeList(node.named); |
588 } | 566 } |
589 | 567 |
590 visitNamedExpression(NamedExpression node) { | 568 visitNamedExpression(NamedExpression node) { |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 writeByte(Tag.DynamicType); | 918 writeByte(Tag.DynamicType); |
941 } | 919 } |
942 | 920 |
943 visitVoidType(VoidType node) { | 921 visitVoidType(VoidType node) { |
944 writeByte(Tag.VoidType); | 922 writeByte(Tag.VoidType); |
945 } | 923 } |
946 | 924 |
947 visitInterfaceType(InterfaceType node) { | 925 visitInterfaceType(InterfaceType node) { |
948 if (node.typeArguments.isEmpty) { | 926 if (node.typeArguments.isEmpty) { |
949 writeByte(Tag.SimpleInterfaceType); | 927 writeByte(Tag.SimpleInterfaceType); |
950 writeClassReference(node.classNode); | 928 writeReference(node.className); |
951 } else { | 929 } else { |
952 writeByte(Tag.InterfaceType); | 930 writeByte(Tag.InterfaceType); |
953 writeClassReference(node.classNode); | 931 writeReference(node.className); |
954 writeNodeList(node.typeArguments); | 932 writeNodeList(node.typeArguments); |
955 } | 933 } |
956 } | 934 } |
957 | 935 |
958 visitSupertype(Supertype node) { | 936 visitSupertype(Supertype node) { |
959 if (node.typeArguments.isEmpty) { | 937 if (node.typeArguments.isEmpty) { |
960 writeByte(Tag.SimpleInterfaceType); | 938 writeByte(Tag.SimpleInterfaceType); |
961 writeClassReference(node.classNode); | 939 writeReference(node.className); |
962 } else { | 940 } else { |
963 writeByte(Tag.InterfaceType); | 941 writeByte(Tag.InterfaceType); |
964 writeClassReference(node.classNode); | 942 writeReference(node.className); |
965 writeNodeList(node.typeArguments); | 943 writeNodeList(node.typeArguments); |
966 } | 944 } |
967 } | 945 } |
968 | 946 |
969 visitFunctionType(FunctionType node) { | 947 visitFunctionType(FunctionType node) { |
970 if (node.requiredParameterCount == node.positionalParameters.length && | 948 if (node.requiredParameterCount == node.positionalParameters.length && |
971 node.typeParameters.isEmpty && | 949 node.typeParameters.isEmpty && |
972 node.namedParameters.isEmpty) { | 950 node.namedParameters.isEmpty) { |
973 writeByte(Tag.SimpleFunctionType); | 951 writeByte(Tag.SimpleFunctionType); |
974 writeNodeList(node.positionalParameters); | 952 writeNodeList(node.positionalParameters); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 class StringIndexer extends RecursiveVisitor<Null> { | 1071 class StringIndexer extends RecursiveVisitor<Null> { |
1094 final List<StringTableEntry> entries = <StringTableEntry>[]; | 1072 final List<StringTableEntry> entries = <StringTableEntry>[]; |
1095 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); | 1073 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); |
1096 | 1074 |
1097 StringIndexer() { | 1075 StringIndexer() { |
1098 put(''); | 1076 put(''); |
1099 } | 1077 } |
1100 | 1078 |
1101 int get numberOfStrings => index.length; | 1079 int get numberOfStrings => index.length; |
1102 | 1080 |
1103 void build(Node node) { | 1081 void scanProgram(Node node) { |
1104 node.accept(this); | 1082 node.accept(this); |
1105 entries.sort(); | 1083 entries.sort(); |
1106 for (int i = 0; i < entries.length; ++i) { | 1084 for (int i = 0; i < entries.length; ++i) { |
1107 index[entries[i].value] = i; | 1085 index[entries[i].value] = i; |
1108 } | 1086 } |
1109 } | 1087 } |
1110 | 1088 |
| 1089 void visitCanonicalName(CanonicalName name) { |
| 1090 put(name.name); |
| 1091 name.children.forEach(visitCanonicalName); |
| 1092 } |
| 1093 |
1111 void put(String string) { | 1094 void put(String string) { |
1112 int i = index.putIfAbsent(string, () { | 1095 int i = index.putIfAbsent(string, () { |
1113 entries.add(new StringTableEntry(string)); | 1096 entries.add(new StringTableEntry(string)); |
1114 return index.length; | 1097 return index.length; |
1115 }); | 1098 }); |
1116 ++entries[i].frequency; | 1099 ++entries[i].frequency; |
1117 } | 1100 } |
1118 | 1101 |
1119 void putOptional(String string) { | 1102 void putOptional(String string) { |
1120 if (string != null) { | 1103 if (string != null) { |
1121 put(string); | 1104 put(string); |
1122 } | 1105 } |
1123 } | 1106 } |
1124 | 1107 |
1125 int operator [](String string) => index[string]; | 1108 int operator [](String string) => index[string]; |
1126 | 1109 |
1127 void addLibraryImports(LibraryImportTable imports) { | 1110 void addLibraryImports(LibraryImportTable imports) { |
1128 imports.importPaths.forEach(put); | 1111 imports.importPaths.forEach(put); |
1129 } | 1112 } |
1130 | 1113 |
1131 visitName(Name node) { | 1114 visitName(Name node) { |
1132 put(node.name); | 1115 put(node.name); |
1133 } | 1116 } |
1134 | 1117 |
1135 visitLibrary(Library node) { | 1118 visitLibrary(Library node) { |
| 1119 visitCanonicalName(node.canonicalName); |
1136 putOptional(node.name); | 1120 putOptional(node.name); |
1137 put('${node.importUri}'); | 1121 put('${node.importUri}'); |
1138 node.visitChildren(this); | 1122 node.visitChildren(this); |
1139 } | 1123 } |
1140 | 1124 |
1141 visitDeferredImport(DeferredImport node) { | 1125 visitDeferredImport(DeferredImport node) { |
1142 put(node.name); | 1126 put(node.name); |
1143 } | 1127 } |
1144 | 1128 |
1145 visitClass(Class node) { | 1129 visitClass(Class node) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 void flush() { | 1269 void flush() { |
1286 _sink.add(_buffer.sublist(0, length)); | 1270 _sink.add(_buffer.sublist(0, length)); |
1287 _buffer = new Uint8List(SIZE); | 1271 _buffer = new Uint8List(SIZE); |
1288 length = 0; | 1272 length = 0; |
1289 } | 1273 } |
1290 | 1274 |
1291 void flushAndDestroy() { | 1275 void flushAndDestroy() { |
1292 _sink.add(_buffer.sublist(0, length)); | 1276 _sink.add(_buffer.sublist(0, length)); |
1293 } | 1277 } |
1294 } | 1278 } |
OLD | NEW |