| 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 |