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 | 24 |
28 final BufferedSink _sink; | 25 final BufferedSink _sink; |
29 | 26 |
30 /// Create a printer that writes to the given [sink]. | 27 /// Create a printer that writes to the given [sink]. |
31 /// | 28 /// |
32 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 29 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
33 /// one. | 30 /// one. |
34 /// | 31 /// |
35 /// If multiple binaries are to be written based on the same IR, a shared | 32 /// If multiple binaries are to be written based on the same IR, a shared |
36 /// [globalIndexer] may be passed in to avoid rebuilding the same indices | 33 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
37 /// in every printer. | 34 /// in every printer. |
38 BinaryPrinter(Sink<List<int>> sink, {GlobalIndexer globalIndexer}) | 35 BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink); |
39 : _sink = new BufferedSink(sink), | |
40 _globalIndexer = globalIndexer ?? new GlobalIndexer(); | |
41 | 36 |
42 void _flush() { | 37 void _flush() { |
43 _sink.flushAndDestroy(); | 38 _sink.flushAndDestroy(); |
44 } | 39 } |
45 | 40 |
46 void writeByte(int byte) { | 41 void writeByte(int byte) { |
47 _sink.addByte(byte); | 42 _sink.addByte(byte); |
48 } | 43 } |
49 | 44 |
50 void writeBytes(List<int> bytes) { | 45 void writeBytes(List<int> bytes) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 if (node == null) { | 120 if (node == null) { |
126 writeByte(Tag.Nothing); | 121 writeByte(Tag.Nothing); |
127 } else { | 122 } else { |
128 writeByte(Tag.Something); | 123 writeByte(Tag.Something); |
129 writeClassReference(node.baseClass, allowNull: true); | 124 writeClassReference(node.baseClass, allowNull: true); |
130 writeByte(node.baseClassKind.index); | 125 writeByte(node.baseClassKind.index); |
131 writeByte(node.valueBits); | 126 writeByte(node.valueBits); |
132 } | 127 } |
133 } | 128 } |
134 | 129 |
| 130 void writeLinkTable(Program program) { |
| 131 List<CanonicalName> list = <CanonicalName>[]; |
| 132 void visitCanonicalName(CanonicalName node) { |
| 133 node.index = list.length; |
| 134 list.add(node); |
| 135 node.children.forEach(visitCanonicalName); |
| 136 } |
| 137 |
| 138 for (var library in program.libraries) { |
| 139 visitCanonicalName(library.canonicalName); |
| 140 } |
| 141 writeList(list, writeCanonicalNameEntry); |
| 142 } |
| 143 |
| 144 void writeCanonicalNameEntry(CanonicalName node) { |
| 145 var parent = node.parent; |
| 146 if (parent.isRoot) { |
| 147 writeByte(0); |
| 148 } else { |
| 149 writeUInt30(parent.index + 1); |
| 150 } |
| 151 writeStringReference(node.name); |
| 152 } |
| 153 |
135 void writeProgramFile(Program program) { | 154 void writeProgramFile(Program program) { |
136 writeMagicWord(Tag.ProgramFile); | 155 writeMagicWord(Tag.ProgramFile); |
137 _importTable = new ProgramImportTable(program); | 156 _stringIndexer.scanProgram(program); |
138 _stringIndexer.build(program); | |
139 writeStringTable(_stringIndexer); | 157 writeStringTable(_stringIndexer); |
140 writeUriToSource(program); | 158 writeUriToSource(program); |
| 159 writeLinkTable(program); |
141 writeList(program.libraries, writeNode); | 160 writeList(program.libraries, writeNode); |
142 writeMemberReference(program.mainMethod, allowNull: true); | 161 writeMemberReference(program.mainMethod, allowNull: true); |
143 _flush(); | 162 _flush(); |
144 } | 163 } |
145 | 164 |
146 void writeUriToSource(Program program) { | 165 void writeUriToSource(Program program) { |
147 program.uriToSource.keys.forEach((uri) { | 166 program.uriToSource.keys.forEach((uri) { |
148 _sourceUriIndexer.put(uri); | 167 _sourceUriIndexer.put(uri); |
149 }); | 168 }); |
150 writeStringTable(_sourceUriIndexer); | 169 writeStringTable(_sourceUriIndexer); |
151 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 170 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
152 String uri = _sourceUriIndexer.entries[i].value; | 171 String uri = _sourceUriIndexer.entries[i].value; |
153 Source source = program.uriToSource[uri] ?? new Source([], ''); | 172 Source source = program.uriToSource[uri] ?? new Source([], ''); |
154 String sourceCode = source.source; | 173 String sourceCode = source.source; |
155 writeStringTableEntry(sourceCode); | 174 writeStringTableEntry(sourceCode); |
156 List<int> lineStarts = source.lineStarts; | 175 List<int> lineStarts = source.lineStarts; |
157 writeUInt30(lineStarts.length); | 176 writeUInt30(lineStarts.length); |
158 int previousLineStart = 0; | 177 int previousLineStart = 0; |
159 lineStarts.forEach((lineStart) { | 178 lineStarts.forEach((lineStart) { |
160 writeUInt30(lineStart - previousLineStart); | 179 writeUInt30(lineStart - previousLineStart); |
161 previousLineStart = lineStart; | 180 previousLineStart = lineStart; |
162 }); | 181 }); |
163 } | 182 } |
164 } | 183 } |
165 | 184 |
166 void writeLibraryImportTable(LibraryImportTable imports) { | 185 void writeCanonicalNameReference(CanonicalName name) { |
167 writeList(imports.importPaths, writeStringReference); | 186 if (name == null) { |
| 187 writeByte(0); |
| 188 } else { |
| 189 writeUInt30(name.index + 1); |
| 190 } |
168 } | 191 } |
169 | 192 |
170 void writeLibraryReference(Library node) { | 193 void writeLibraryReference(Library node) { |
171 int index = _importTable.getImportIndex(node); | 194 writeCanonicalNameReference(node.canonicalName); |
172 if (index == -1) { | |
173 throw 'Missing import for library: ${node.importUri}'; | |
174 } | |
175 writeUInt30(index); | |
176 } | |
177 | |
178 void writeClassIndex(Class node) { | |
179 writeUInt30(_globalIndexer[node]); | |
180 } | |
181 | |
182 void writeClassReference(Class node, {bool allowNull: false}) { | |
183 if (node == null) { | |
184 if (allowNull) { | |
185 writeByte(Tag.NullReference); | |
186 } else { | |
187 throw 'Expected a class reference to be valid but was `null`.'; | |
188 } | |
189 } else { | |
190 node.acceptReference(this); | |
191 } | |
192 } | |
193 | |
194 void writeMemberReference(Member node, {bool allowNull: false}) { | |
195 if (node == null) { | |
196 if (allowNull) { | |
197 writeByte(Tag.NullReference); | |
198 } else { | |
199 throw 'Expected a member reference to be valid but was `null`.'; | |
200 } | |
201 } else { | |
202 node.acceptReference(this); | |
203 } | |
204 } | 195 } |
205 | 196 |
206 writeOffset(TreeNode node, int offset) { | 197 writeOffset(TreeNode node, int offset) { |
207 // TODO(jensj): Delta-encoding. | 198 // TODO(jensj): Delta-encoding. |
208 // File offset ranges from -1 and up, | 199 // File offset ranges from -1 and up, |
209 // but is here saved as unsigned (thus the +1) | 200 // but is here saved as unsigned (thus the +1) |
210 writeUInt30(offset + 1); | 201 writeUInt30(offset + 1); |
211 } | 202 } |
212 | 203 |
213 void visitClassReference(Class node) { | 204 void writeClassReference(Class class_, {bool allowNull: false}) { |
214 var library = node.enclosingLibrary; | 205 if (class_ == null && !allowNull) { |
215 writeByte(node.isMixinApplication | 206 throw 'Expected a class reference to be valid but was `null`.'; |
216 ? Tag.MixinClassReference | 207 } |
217 : Tag.NormalClassReference); | 208 writeCanonicalNameReference(getCanonicalNameOfClass(class_)); |
218 writeLibraryReference(library); | |
219 writeClassIndex(node); | |
220 } | 209 } |
221 | 210 |
222 void visitFieldReference(Field node) { | 211 void writeMemberReference(Member member, {bool allowNull: false}) { |
223 if (node.enclosingClass != null) { | 212 if (member == null && !allowNull) { |
224 writeByte(Tag.ClassFieldReference); | 213 throw 'Expected a member reference to be valid but was `null`.'; |
225 Class classNode = node.enclosingClass; | |
226 writeClassReference(classNode); | |
227 writeUInt30(_globalIndexer[node]); | |
228 } else { | |
229 writeByte(Tag.LibraryFieldReference); | |
230 writeLibraryReference(node.enclosingLibrary); | |
231 writeUInt30(_globalIndexer[node]); | |
232 } | 214 } |
233 } | 215 writeCanonicalNameReference(getCanonicalNameOfMember(member)); |
234 | |
235 void visitConstructorReference(Constructor node) { | |
236 writeByte(Tag.ClassConstructorReference); | |
237 writeClassReference(node.enclosingClass); | |
238 writeUInt30(_globalIndexer[node]); | |
239 } | |
240 | |
241 void visitProcedureReference(Procedure node) { | |
242 if (node.enclosingClass != null) { | |
243 writeByte(Tag.ClassProcedureReference); | |
244 Class classNode = node.enclosingClass; | |
245 writeClassReference(classNode); | |
246 writeUInt30(_globalIndexer[node]); | |
247 } else { | |
248 writeByte(Tag.LibraryProcedureReference); | |
249 writeLibraryReference(node.enclosingLibrary); | |
250 writeUInt30(_globalIndexer[node]); | |
251 } | |
252 } | 216 } |
253 | 217 |
254 void writeName(Name node) { | 218 void writeName(Name node) { |
255 writeStringReference(node.name); | 219 writeStringReference(node.name); |
256 // TODO: Consider a more compressed format for private names within the | 220 // TODO: Consider a more compressed format for private names within the |
257 // enclosing library. | 221 // enclosing library. |
258 if (node.isPrivate) { | 222 if (node.isPrivate) { |
259 writeLibraryReference(node.library); | 223 writeLibraryReference(node.library); |
260 } | 224 } |
261 } | 225 } |
262 | 226 |
263 bool insideExternalLibrary = false; | 227 bool insideExternalLibrary = false; |
264 | 228 |
265 visitLibrary(Library node) { | 229 visitLibrary(Library node) { |
266 insideExternalLibrary = node.isExternal; | 230 insideExternalLibrary = node.isExternal; |
267 writeByte(insideExternalLibrary ? 1 : 0); | 231 writeByte(insideExternalLibrary ? 1 : 0); |
| 232 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); |
268 writeStringReference(node.name ?? ''); | 233 writeStringReference(node.name ?? ''); |
269 writeStringReference('${node.importUri}'); | |
270 // TODO(jensj): We save (almost) the same URI twice. | 234 // TODO(jensj): We save (almost) the same URI twice. |
271 writeUriReference(node.fileUri ?? ''); | 235 writeUriReference(node.fileUri ?? ''); |
272 writeNodeList(node.classes); | 236 writeNodeList(node.classes); |
273 writeNodeList(node.fields); | 237 writeNodeList(node.fields); |
274 writeNodeList(node.procedures); | 238 writeNodeList(node.procedures); |
275 } | 239 } |
276 | 240 |
277 void writeAnnotation(Expression annotation) { | 241 void writeAnnotation(Expression annotation) { |
278 _variableIndexer ??= new VariableIndexer(); | 242 _variableIndexer ??= new VariableIndexer(); |
279 writeNode(annotation); | 243 writeNode(annotation); |
280 } | 244 } |
281 | 245 |
282 void writeAnnotationList(List<Expression> annotations) { | 246 void writeAnnotationList(List<Expression> annotations) { |
283 writeList(annotations, writeAnnotation); | 247 writeList(annotations, writeAnnotation); |
284 } | 248 } |
285 | 249 |
286 visitClass(Class node) { | 250 visitClass(Class node) { |
287 int flags = node.isAbstract ? 1 : 0; | 251 int flags = node.isAbstract ? 1 : 0; |
288 if (node.level == ClassLevel.Type) { | 252 if (node.level == ClassLevel.Type) { |
289 flags |= 0x2; | 253 flags |= 0x2; |
290 } | 254 } |
291 if (node.isMixinApplication) { | 255 if (node.canonicalName == null) { |
292 writeByte(Tag.MixinClass); | 256 throw 'Missing canonical name for $node'; |
293 writeOffset(node, node.fileOffset); | |
294 writeByte(flags); | |
295 writeStringReference(node.name ?? ''); | |
296 writeUriReference(node.fileUri ?? ''); | |
297 writeAnnotationList(node.annotations); | |
298 _typeParameterIndexer.enter(node.typeParameters); | |
299 writeNodeList(node.typeParameters); | |
300 writeNode(node.supertype); | |
301 writeNode(node.mixedInType); | |
302 writeNodeList(node.implementedTypes); | |
303 writeNodeList(node.constructors); | |
304 _typeParameterIndexer.exit(node.typeParameters); | |
305 } else { | |
306 writeByte(Tag.NormalClass); | |
307 writeOffset(node, node.fileOffset); | |
308 writeByte(flags); | |
309 writeStringReference(node.name ?? ''); | |
310 writeUriReference(node.fileUri ?? ''); | |
311 writeAnnotationList(node.annotations); | |
312 _typeParameterIndexer.enter(node.typeParameters); | |
313 writeNodeList(node.typeParameters); | |
314 writeOptionalNode(node.supertype); | |
315 writeNodeList(node.implementedTypes); | |
316 writeNodeList(node.fields); | |
317 writeNodeList(node.constructors); | |
318 writeNodeList(node.procedures); | |
319 _typeParameterIndexer.exit(node.typeParameters); | |
320 } | 257 } |
| 258 writeByte(Tag.Class); |
| 259 writeCanonicalNameReference(getCanonicalNameOfClass(node)); |
| 260 writeOffset(node, node.fileOffset); |
| 261 writeByte(flags); |
| 262 writeStringReference(node.name ?? ''); |
| 263 writeUriReference(node.fileUri ?? ''); |
| 264 writeAnnotationList(node.annotations); |
| 265 _typeParameterIndexer.enter(node.typeParameters); |
| 266 writeNodeList(node.typeParameters); |
| 267 writeOptionalNode(node.supertype); |
| 268 writeOptionalNode(node.mixedInType); |
| 269 writeNodeList(node.implementedTypes); |
| 270 writeNodeList(node.fields); |
| 271 writeNodeList(node.constructors); |
| 272 writeNodeList(node.procedures); |
| 273 _typeParameterIndexer.exit(node.typeParameters); |
321 } | 274 } |
322 | 275 |
323 static final Name _emptyName = new Name(''); | 276 static final Name _emptyName = new Name(''); |
324 | 277 |
325 visitConstructor(Constructor node) { | 278 visitConstructor(Constructor node) { |
| 279 if (node.canonicalName == null) { |
| 280 throw 'Missing canonical name for $node'; |
| 281 } |
326 _variableIndexer = new VariableIndexer(); | 282 _variableIndexer = new VariableIndexer(); |
327 writeByte(Tag.Constructor); | 283 writeByte(Tag.Constructor); |
| 284 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
328 writeOffset(node, node.fileOffset); | 285 writeOffset(node, node.fileOffset); |
329 writeOffset(node, node.fileEndOffset); | 286 writeOffset(node, node.fileEndOffset); |
330 writeByte(node.flags); | 287 writeByte(node.flags); |
331 writeName(node.name ?? _emptyName); | 288 writeName(node.name ?? _emptyName); |
332 writeAnnotationList(node.annotations); | 289 writeAnnotationList(node.annotations); |
333 assert(node.function.typeParameters.isEmpty); | 290 assert(node.function.typeParameters.isEmpty); |
334 writeNode(node.function); | 291 writeNode(node.function); |
335 // Parameters are in scope in the initializers. | 292 // Parameters are in scope in the initializers. |
336 _variableIndexer.restoreScope(node.function.positionalParameters.length + | 293 _variableIndexer.restoreScope(node.function.positionalParameters.length + |
337 node.function.namedParameters.length); | 294 node.function.namedParameters.length); |
338 writeNodeList(node.initializers); | 295 writeNodeList(node.initializers); |
339 _variableIndexer = null; | 296 _variableIndexer = null; |
340 } | 297 } |
341 | 298 |
342 visitProcedure(Procedure node) { | 299 visitProcedure(Procedure node) { |
| 300 if (node.canonicalName == null) { |
| 301 throw 'Missing canonical name for $node'; |
| 302 } |
343 _variableIndexer = new VariableIndexer(); | 303 _variableIndexer = new VariableIndexer(); |
344 writeByte(Tag.Procedure); | 304 writeByte(Tag.Procedure); |
| 305 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
345 writeOffset(node, node.fileOffset); | 306 writeOffset(node, node.fileOffset); |
346 writeOffset(node, node.fileEndOffset); | 307 writeOffset(node, node.fileEndOffset); |
347 writeByte(node.kind.index); | 308 writeByte(node.kind.index); |
348 writeByte(node.flags); | 309 writeByte(node.flags); |
349 writeName(node.name ?? ''); | 310 writeName(node.name ?? ''); |
350 writeUriReference(node.fileUri ?? ''); | 311 writeUriReference(node.fileUri ?? ''); |
351 writeAnnotationList(node.annotations); | 312 writeAnnotationList(node.annotations); |
352 writeOptionalNode(node.function); | 313 writeOptionalNode(node.function); |
353 _variableIndexer = null; | 314 _variableIndexer = null; |
354 } | 315 } |
355 | 316 |
356 visitField(Field node) { | 317 visitField(Field node) { |
| 318 if (node.canonicalName == null) { |
| 319 throw 'Missing canonical name for $node'; |
| 320 } |
357 _variableIndexer = new VariableIndexer(); | 321 _variableIndexer = new VariableIndexer(); |
358 writeByte(Tag.Field); | 322 writeByte(Tag.Field); |
| 323 writeCanonicalNameReference(getCanonicalNameOfMember(node)); |
359 writeOffset(node, node.fileOffset); | 324 writeOffset(node, node.fileOffset); |
360 writeOffset(node, node.fileEndOffset); | 325 writeOffset(node, node.fileEndOffset); |
361 writeByte(node.flags); | 326 writeByte(node.flags); |
362 writeName(node.name ?? ''); | 327 writeName(node.name ?? ''); |
363 writeUriReference(node.fileUri ?? ''); | 328 writeUriReference(node.fileUri ?? ''); |
364 writeAnnotationList(node.annotations); | 329 writeAnnotationList(node.annotations); |
365 writeNode(node.type); | 330 writeNode(node.type); |
366 writeOptionalInferredValue(node.inferredValue); | 331 writeOptionalInferredValue(node.inferredValue); |
367 writeOptionalNode(node.initializer); | 332 writeOptionalNode(node.initializer); |
368 _variableIndexer = null; | 333 _variableIndexer = null; |
369 } | 334 } |
370 | 335 |
371 visitInvalidInitializer(InvalidInitializer node) { | 336 visitInvalidInitializer(InvalidInitializer node) { |
372 writeByte(Tag.InvalidInitializer); | 337 writeByte(Tag.InvalidInitializer); |
373 } | 338 } |
374 | 339 |
375 visitFieldInitializer(FieldInitializer node) { | 340 visitFieldInitializer(FieldInitializer node) { |
376 writeByte(Tag.FieldInitializer); | 341 writeByte(Tag.FieldInitializer); |
377 writeMemberReference(node.field); | 342 writeCanonicalNameReference(node.fieldName); |
378 writeNode(node.value); | 343 writeNode(node.value); |
379 } | 344 } |
380 | 345 |
381 visitSuperInitializer(SuperInitializer node) { | 346 visitSuperInitializer(SuperInitializer node) { |
382 writeByte(Tag.SuperInitializer); | 347 writeByte(Tag.SuperInitializer); |
383 writeMemberReference(node.target); | 348 writeCanonicalNameReference(node.targetName); |
384 writeNode(node.arguments); | 349 writeNode(node.arguments); |
385 } | 350 } |
386 | 351 |
387 visitRedirectingInitializer(RedirectingInitializer node) { | 352 visitRedirectingInitializer(RedirectingInitializer node) { |
388 writeByte(Tag.RedirectingInitializer); | 353 writeByte(Tag.RedirectingInitializer); |
389 writeMemberReference(node.target); | 354 writeCanonicalNameReference(node.targetName); |
390 writeNode(node.arguments); | 355 writeNode(node.arguments); |
391 } | 356 } |
392 | 357 |
393 visitLocalInitializer(LocalInitializer node) { | 358 visitLocalInitializer(LocalInitializer node) { |
394 writeByte(Tag.LocalInitializer); | 359 writeByte(Tag.LocalInitializer); |
395 writeVariableDeclaration(node.variable); | 360 writeVariableDeclaration(node.variable); |
396 } | 361 } |
397 | 362 |
398 visitFunctionNode(FunctionNode node) { | 363 visitFunctionNode(FunctionNode node) { |
399 assert(_variableIndexer != null); | 364 assert(_variableIndexer != null); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 writeUInt30(_variableIndexer[node.variable]); | 419 writeUInt30(_variableIndexer[node.variable]); |
455 writeNode(node.value); | 420 writeNode(node.value); |
456 } | 421 } |
457 } | 422 } |
458 | 423 |
459 visitPropertyGet(PropertyGet node) { | 424 visitPropertyGet(PropertyGet node) { |
460 writeByte(Tag.PropertyGet); | 425 writeByte(Tag.PropertyGet); |
461 writeOffset(node, node.fileOffset); | 426 writeOffset(node, node.fileOffset); |
462 writeNode(node.receiver); | 427 writeNode(node.receiver); |
463 writeName(node.name); | 428 writeName(node.name); |
464 writeMemberReference(node.interfaceTarget, allowNull: true); | 429 writeCanonicalNameReference(node.interfaceTargetName); |
465 } | 430 } |
466 | 431 |
467 visitPropertySet(PropertySet node) { | 432 visitPropertySet(PropertySet node) { |
468 writeByte(Tag.PropertySet); | 433 writeByte(Tag.PropertySet); |
469 writeOffset(node, node.fileOffset); | 434 writeOffset(node, node.fileOffset); |
470 writeNode(node.receiver); | 435 writeNode(node.receiver); |
471 writeName(node.name); | 436 writeName(node.name); |
472 writeNode(node.value); | 437 writeNode(node.value); |
473 writeMemberReference(node.interfaceTarget, allowNull: true); | 438 writeCanonicalNameReference(node.interfaceTargetName); |
474 } | 439 } |
475 | 440 |
476 visitSuperPropertyGet(SuperPropertyGet node) { | 441 visitSuperPropertyGet(SuperPropertyGet node) { |
477 writeByte(Tag.SuperPropertyGet); | 442 writeByte(Tag.SuperPropertyGet); |
478 writeName(node.name); | 443 writeName(node.name); |
479 writeMemberReference(node.interfaceTarget, allowNull: true); | 444 writeCanonicalNameReference(node.interfaceTargetName); |
480 } | 445 } |
481 | 446 |
482 visitSuperPropertySet(SuperPropertySet node) { | 447 visitSuperPropertySet(SuperPropertySet node) { |
483 writeByte(Tag.SuperPropertySet); | 448 writeByte(Tag.SuperPropertySet); |
484 writeName(node.name); | 449 writeName(node.name); |
485 writeNode(node.value); | 450 writeNode(node.value); |
486 writeMemberReference(node.interfaceTarget, allowNull: true); | 451 writeCanonicalNameReference(node.interfaceTargetName); |
487 } | 452 } |
488 | 453 |
489 visitDirectPropertyGet(DirectPropertyGet node) { | 454 visitDirectPropertyGet(DirectPropertyGet node) { |
490 writeByte(Tag.DirectPropertyGet); | 455 writeByte(Tag.DirectPropertyGet); |
491 writeNode(node.receiver); | 456 writeNode(node.receiver); |
492 writeMemberReference(node.target); | 457 writeCanonicalNameReference(node.targetName); |
493 } | 458 } |
494 | 459 |
495 visitDirectPropertySet(DirectPropertySet node) { | 460 visitDirectPropertySet(DirectPropertySet node) { |
496 writeByte(Tag.DirectPropertySet); | 461 writeByte(Tag.DirectPropertySet); |
497 writeNode(node.receiver); | 462 writeNode(node.receiver); |
498 writeMemberReference(node.target); | 463 writeCanonicalNameReference(node.targetName); |
499 writeNode(node.value); | 464 writeNode(node.value); |
500 } | 465 } |
501 | 466 |
502 visitStaticGet(StaticGet node) { | 467 visitStaticGet(StaticGet node) { |
503 writeByte(Tag.StaticGet); | 468 writeByte(Tag.StaticGet); |
504 writeOffset(node, node.fileOffset); | 469 writeOffset(node, node.fileOffset); |
505 writeMemberReference(node.target); | 470 writeCanonicalNameReference(node.targetName); |
506 } | 471 } |
507 | 472 |
508 visitStaticSet(StaticSet node) { | 473 visitStaticSet(StaticSet node) { |
509 writeByte(Tag.StaticSet); | 474 writeByte(Tag.StaticSet); |
510 writeMemberReference(node.target); | 475 writeCanonicalNameReference(node.targetName); |
511 writeNode(node.value); | 476 writeNode(node.value); |
512 } | 477 } |
513 | 478 |
514 visitMethodInvocation(MethodInvocation node) { | 479 visitMethodInvocation(MethodInvocation node) { |
515 writeByte(Tag.MethodInvocation); | 480 writeByte(Tag.MethodInvocation); |
516 writeOffset(node, node.fileOffset); | 481 writeOffset(node, node.fileOffset); |
517 writeNode(node.receiver); | 482 writeNode(node.receiver); |
518 writeName(node.name); | 483 writeName(node.name); |
519 writeNode(node.arguments); | 484 writeNode(node.arguments); |
520 writeMemberReference(node.interfaceTarget, allowNull: true); | 485 writeCanonicalNameReference(node.interfaceTargetName); |
521 } | 486 } |
522 | 487 |
523 visitSuperMethodInvocation(SuperMethodInvocation node) { | 488 visitSuperMethodInvocation(SuperMethodInvocation node) { |
524 writeByte(Tag.SuperMethodInvocation); | 489 writeByte(Tag.SuperMethodInvocation); |
525 writeOffset(node, node.fileOffset); | 490 writeOffset(node, node.fileOffset); |
526 writeName(node.name); | 491 writeName(node.name); |
527 writeNode(node.arguments); | 492 writeNode(node.arguments); |
528 writeMemberReference(node.interfaceTarget, allowNull: true); | 493 writeCanonicalNameReference(node.interfaceTargetName); |
529 } | 494 } |
530 | 495 |
531 visitDirectMethodInvocation(DirectMethodInvocation node) { | 496 visitDirectMethodInvocation(DirectMethodInvocation node) { |
532 writeByte(Tag.DirectMethodInvocation); | 497 writeByte(Tag.DirectMethodInvocation); |
533 writeNode(node.receiver); | 498 writeNode(node.receiver); |
534 writeMemberReference(node.target); | 499 writeCanonicalNameReference(node.targetName); |
535 writeNode(node.arguments); | 500 writeNode(node.arguments); |
536 } | 501 } |
537 | 502 |
538 visitStaticInvocation(StaticInvocation node) { | 503 visitStaticInvocation(StaticInvocation node) { |
539 writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation); | 504 writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation); |
540 writeOffset(node, node.fileOffset); | 505 writeOffset(node, node.fileOffset); |
541 writeMemberReference(node.target); | 506 writeCanonicalNameReference(node.targetName); |
542 writeNode(node.arguments); | 507 writeNode(node.arguments); |
543 } | 508 } |
544 | 509 |
545 visitConstructorInvocation(ConstructorInvocation node) { | 510 visitConstructorInvocation(ConstructorInvocation node) { |
546 writeByte(node.isConst | 511 writeByte(node.isConst |
547 ? Tag.ConstConstructorInvocation | 512 ? Tag.ConstConstructorInvocation |
548 : Tag.ConstructorInvocation); | 513 : Tag.ConstructorInvocation); |
549 writeOffset(node, node.fileOffset); | 514 writeOffset(node, node.fileOffset); |
550 writeMemberReference(node.target); | 515 writeCanonicalNameReference(node.targetName); |
551 writeNode(node.arguments); | 516 writeNode(node.arguments); |
552 } | 517 } |
553 | 518 |
554 visitArguments(Arguments node) { | 519 visitArguments(Arguments node) { |
555 writeNodeList(node.types); | 520 writeNodeList(node.types); |
556 writeNodeList(node.positional); | 521 writeNodeList(node.positional); |
557 writeNodeList(node.named); | 522 writeNodeList(node.named); |
558 } | 523 } |
559 | 524 |
560 visitNamedExpression(NamedExpression node) { | 525 visitNamedExpression(NamedExpression node) { |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 writeByte(Tag.DynamicType); | 865 writeByte(Tag.DynamicType); |
901 } | 866 } |
902 | 867 |
903 visitVoidType(VoidType node) { | 868 visitVoidType(VoidType node) { |
904 writeByte(Tag.VoidType); | 869 writeByte(Tag.VoidType); |
905 } | 870 } |
906 | 871 |
907 visitInterfaceType(InterfaceType node) { | 872 visitInterfaceType(InterfaceType node) { |
908 if (node.typeArguments.isEmpty) { | 873 if (node.typeArguments.isEmpty) { |
909 writeByte(Tag.SimpleInterfaceType); | 874 writeByte(Tag.SimpleInterfaceType); |
910 writeClassReference(node.classNode); | 875 writeCanonicalNameReference(node.className); |
911 } else { | 876 } else { |
912 writeByte(Tag.InterfaceType); | 877 writeByte(Tag.InterfaceType); |
913 writeClassReference(node.classNode); | 878 writeCanonicalNameReference(node.className); |
914 writeNodeList(node.typeArguments); | 879 writeNodeList(node.typeArguments); |
915 } | 880 } |
916 } | 881 } |
917 | 882 |
918 visitSupertype(Supertype node) { | 883 visitSupertype(Supertype node) { |
919 if (node.typeArguments.isEmpty) { | 884 if (node.typeArguments.isEmpty) { |
920 writeByte(Tag.SimpleInterfaceType); | 885 writeByte(Tag.SimpleInterfaceType); |
921 writeClassReference(node.classNode); | 886 writeCanonicalNameReference(node.className); |
922 } else { | 887 } else { |
923 writeByte(Tag.InterfaceType); | 888 writeByte(Tag.InterfaceType); |
924 writeClassReference(node.classNode); | 889 writeCanonicalNameReference(node.className); |
925 writeNodeList(node.typeArguments); | 890 writeNodeList(node.typeArguments); |
926 } | 891 } |
927 } | 892 } |
928 | 893 |
929 visitFunctionType(FunctionType node) { | 894 visitFunctionType(FunctionType node) { |
930 if (node.requiredParameterCount == node.positionalParameters.length && | 895 if (node.requiredParameterCount == node.positionalParameters.length && |
931 node.typeParameters.isEmpty && | 896 node.typeParameters.isEmpty && |
932 node.namedParameters.isEmpty) { | 897 node.namedParameters.isEmpty) { |
933 writeByte(Tag.SimpleFunctionType); | 898 writeByte(Tag.SimpleFunctionType); |
934 writeNodeList(node.positionalParameters); | 899 writeNodeList(node.positionalParameters); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 class StringIndexer extends RecursiveVisitor<Null> { | 1018 class StringIndexer extends RecursiveVisitor<Null> { |
1054 final List<StringTableEntry> entries = <StringTableEntry>[]; | 1019 final List<StringTableEntry> entries = <StringTableEntry>[]; |
1055 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); | 1020 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); |
1056 | 1021 |
1057 StringIndexer() { | 1022 StringIndexer() { |
1058 put(''); | 1023 put(''); |
1059 } | 1024 } |
1060 | 1025 |
1061 int get numberOfStrings => index.length; | 1026 int get numberOfStrings => index.length; |
1062 | 1027 |
1063 void build(Node node) { | 1028 void scanProgram(Node node) { |
1064 node.accept(this); | 1029 node.accept(this); |
1065 entries.sort(); | 1030 entries.sort(); |
1066 for (int i = 0; i < entries.length; ++i) { | 1031 for (int i = 0; i < entries.length; ++i) { |
1067 index[entries[i].value] = i; | 1032 index[entries[i].value] = i; |
1068 } | 1033 } |
1069 } | 1034 } |
1070 | 1035 |
| 1036 void visitCanonicalName(CanonicalName name) { |
| 1037 put(name.name); |
| 1038 name.children.forEach(visitCanonicalName); |
| 1039 } |
| 1040 |
1071 void put(String string) { | 1041 void put(String string) { |
1072 int i = index.putIfAbsent(string, () { | 1042 int i = index.putIfAbsent(string, () { |
1073 entries.add(new StringTableEntry(string)); | 1043 entries.add(new StringTableEntry(string)); |
1074 return index.length; | 1044 return index.length; |
1075 }); | 1045 }); |
1076 ++entries[i].frequency; | 1046 ++entries[i].frequency; |
1077 } | 1047 } |
1078 | 1048 |
1079 void putOptional(String string) { | 1049 void putOptional(String string) { |
1080 if (string != null) { | 1050 if (string != null) { |
1081 put(string); | 1051 put(string); |
1082 } | 1052 } |
1083 } | 1053 } |
1084 | 1054 |
1085 int operator [](String string) => index[string]; | 1055 int operator [](String string) => index[string]; |
1086 | 1056 |
1087 void addLibraryImports(LibraryImportTable imports) { | 1057 void addLibraryImports(LibraryImportTable imports) { |
1088 imports.importPaths.forEach(put); | 1058 imports.importPaths.forEach(put); |
1089 } | 1059 } |
1090 | 1060 |
1091 visitName(Name node) { | 1061 visitName(Name node) { |
1092 put(node.name); | 1062 put(node.name); |
1093 } | 1063 } |
1094 | 1064 |
1095 visitLibrary(Library node) { | 1065 visitLibrary(Library node) { |
| 1066 visitCanonicalName(node.canonicalName); |
1096 putOptional(node.name); | 1067 putOptional(node.name); |
1097 put('${node.importUri}'); | 1068 put('${node.importUri}'); |
1098 node.visitChildren(this); | 1069 node.visitChildren(this); |
1099 } | 1070 } |
1100 | 1071 |
1101 visitClass(Class node) { | 1072 visitClass(Class node) { |
1102 putOptional(node.name); | 1073 putOptional(node.name); |
1103 node.visitChildren(this); | 1074 node.visitChildren(this); |
1104 } | 1075 } |
1105 | 1076 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 void flush() { | 1212 void flush() { |
1242 _sink.add(_buffer.sublist(0, length)); | 1213 _sink.add(_buffer.sublist(0, length)); |
1243 _buffer = new Uint8List(SIZE); | 1214 _buffer = new Uint8List(SIZE); |
1244 length = 0; | 1215 length = 0; |
1245 } | 1216 } |
1246 | 1217 |
1247 void flushAndDestroy() { | 1218 void flushAndDestroy() { |
1248 _sink.add(_buffer.sublist(0, length)); | 1219 _sink.add(_buffer.sublist(0, length)); |
1249 } | 1220 } |
1250 } | 1221 } |
OLD | NEW |