| 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 VariableIndexer _variableIndexer; | 18 VariableIndexer _variableIndexer; |
| 19 LabelIndexer _labelIndexer; | 19 LabelIndexer _labelIndexer; |
| 20 SwitchCaseIndexer _switchCaseIndexer; | 20 SwitchCaseIndexer _switchCaseIndexer; |
| 21 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); | 21 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); |
| 22 final StringIndexer stringIndexer; | 22 final StringIndexer stringIndexer; |
| 23 final StringIndexer _sourceUriIndexer = new StringIndexer(); | 23 final StringIndexer _sourceUriIndexer = new StringIndexer(); |
| 24 Map<LibraryDependency, int> _libraryDependencyIndex = | 24 Map<LibraryDependency, int> _libraryDependencyIndex = |
| 25 <LibraryDependency, int>{}; | 25 <LibraryDependency, int>{}; |
| 26 | 26 |
| 27 final BufferedSink _sink; | 27 final BufferedSink _sink; |
| 28 | 28 |
| 29 int _binaryOffsetForSourceTable = -1; |
| 30 int _binaryOffsetForLinkTable = -1; |
| 31 |
| 29 /// Create a printer that writes to the given [sink]. | 32 /// Create a printer that writes to the given [sink]. |
| 30 /// | 33 /// |
| 31 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 34 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
| 32 /// one. | 35 /// one. |
| 33 /// | 36 /// |
| 34 /// If multiple binaries are to be written based on the same IR, a shared | 37 /// If multiple binaries are to be written based on the same IR, a shared |
| 35 /// [globalIndexer] may be passed in to avoid rebuilding the same indices | 38 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
| 36 /// in every printer. | 39 /// in every printer. |
| 37 BinaryPrinter(Sink<List<int>> sink, {StringIndexer stringIndexer}) | 40 BinaryPrinter(Sink<List<int>> sink, {StringIndexer stringIndexer}) |
| 38 : _sink = new BufferedSink(sink), | 41 : _sink = new BufferedSink(sink), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 58 writeByte((value >> 8) | 0x80); | 61 writeByte((value >> 8) | 0x80); |
| 59 writeByte(value & 0xFF); | 62 writeByte(value & 0xFF); |
| 60 } else { | 63 } else { |
| 61 writeByte((value >> 24) | 0xC0); | 64 writeByte((value >> 24) | 0xC0); |
| 62 writeByte((value >> 16) & 0xFF); | 65 writeByte((value >> 16) & 0xFF); |
| 63 writeByte((value >> 8) & 0xFF); | 66 writeByte((value >> 8) & 0xFF); |
| 64 writeByte(value & 0xFF); | 67 writeByte(value & 0xFF); |
| 65 } | 68 } |
| 66 } | 69 } |
| 67 | 70 |
| 68 void writeMagicWord(int value) { | 71 void writeUInt32(int value) { |
| 69 writeByte((value >> 24) & 0xFF); | 72 writeByte((value >> 24) & 0xFF); |
| 70 writeByte((value >> 16) & 0xFF); | 73 writeByte((value >> 16) & 0xFF); |
| 71 writeByte((value >> 8) & 0xFF); | 74 writeByte((value >> 8) & 0xFF); |
| 72 writeByte(value & 0xFF); | 75 writeByte(value & 0xFF); |
| 73 } | 76 } |
| 74 | 77 |
| 75 void writeUtf8Bytes(List<int> utf8Bytes) { | 78 void writeUtf8Bytes(List<int> utf8Bytes) { |
| 76 writeUInt30(utf8Bytes.length); | 79 writeUInt30(utf8Bytes.length); |
| 77 writeBytes(utf8Bytes); | 80 writeBytes(utf8Bytes); |
| 78 } | 81 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 void writeOptionalNode(Node node) { | 127 void writeOptionalNode(Node node) { |
| 125 if (node == null) { | 128 if (node == null) { |
| 126 writeByte(Tag.Nothing); | 129 writeByte(Tag.Nothing); |
| 127 } else { | 130 } else { |
| 128 writeByte(Tag.Something); | 131 writeByte(Tag.Something); |
| 129 writeNode(node); | 132 writeNode(node); |
| 130 } | 133 } |
| 131 } | 134 } |
| 132 | 135 |
| 133 void writeLinkTable(Program program) { | 136 void writeLinkTable(Program program) { |
| 137 _binaryOffsetForLinkTable = _sink.flushedLength + _sink.length; |
| 134 List<CanonicalName> list = <CanonicalName>[]; | 138 List<CanonicalName> list = <CanonicalName>[]; |
| 135 void visitCanonicalName(CanonicalName node) { | 139 void visitCanonicalName(CanonicalName node) { |
| 136 node.index = list.length; | 140 node.index = list.length; |
| 137 list.add(node); | 141 list.add(node); |
| 138 node.children.forEach(visitCanonicalName); | 142 node.children.forEach(visitCanonicalName); |
| 139 } | 143 } |
| 140 | 144 |
| 141 for (var library in program.libraries) { | 145 for (var library in program.libraries) { |
| 142 if (!shouldWriteLibraryCanonicalNames(library)) continue; | 146 if (!shouldWriteLibraryCanonicalNames(library)) continue; |
| 143 visitCanonicalName(library.canonicalName); | 147 visitCanonicalName(library.canonicalName); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 167 if (parent.isRoot) { | 171 if (parent.isRoot) { |
| 168 writeByte(0); | 172 writeByte(0); |
| 169 } else { | 173 } else { |
| 170 writeUInt30(parent.index + 1); | 174 writeUInt30(parent.index + 1); |
| 171 } | 175 } |
| 172 writeStringReference(node.name); | 176 writeStringReference(node.name); |
| 173 } | 177 } |
| 174 | 178 |
| 175 void writeProgramFile(Program program) { | 179 void writeProgramFile(Program program) { |
| 176 computeCanonicalNames(program); | 180 computeCanonicalNames(program); |
| 177 writeMagicWord(Tag.ProgramFile); | 181 writeUInt32(Tag.ProgramFile); |
| 178 buildStringIndex(program); | 182 buildStringIndex(program); |
| 179 writeStringTable(stringIndexer); | 183 writeStringTable(stringIndexer); |
| 180 writeUriToSource(program); | 184 writeUriToSource(program); |
| 181 writeLinkTable(program); | 185 writeLinkTable(program); |
| 182 writeLibraries(program); | 186 writeLibraries(program); |
| 183 writeMemberReference(program.mainMethod, allowNull: true); | 187 writeMemberReference(program.mainMethod, allowNull: true); |
| 188 writeProgramIndex(program, program.libraries); |
| 189 |
| 184 _flush(); | 190 _flush(); |
| 185 } | 191 } |
| 186 | 192 |
| 187 /// Fill the [stringIndexer] with all strings we are going to reference. | 193 /// Fill the [stringIndexer] with all strings we are going to reference. |
| 188 void buildStringIndex(Program program) { | 194 void buildStringIndex(Program program) { |
| 189 stringIndexer.scanProgram(program); | 195 stringIndexer.scanProgram(program); |
| 190 } | 196 } |
| 191 | 197 |
| 192 /// Write all of some of the libraries of the [program]. | 198 /// Write all of some of the libraries of the [program]. |
| 193 void writeLibraries(Program program) { | 199 void writeLibraries(Program program) { |
| 194 writeList(program.libraries, writeNode); | 200 writeList(program.libraries, writeNode); |
| 195 } | 201 } |
| 196 | 202 |
| 203 void writeProgramIndex(Program program, List<Library> libraries) { |
| 204 // Fixed-size ints at the end used as an index. |
| 205 writeUInt32(_binaryOffsetForSourceTable); |
| 206 writeUInt32(_binaryOffsetForLinkTable); |
| 207 |
| 208 CanonicalName main = getCanonicalNameOfMember(program.mainMethod); |
| 209 if (main == null) { |
| 210 writeUInt32(0); |
| 211 } else { |
| 212 writeUInt32(main.index + 1); |
| 213 } |
| 214 for (Library library in libraries) { |
| 215 writeUInt32(library.binaryOffset); |
| 216 } |
| 217 writeUInt32(libraries.length); |
| 218 } |
| 219 |
| 197 void writeUriToSource(Program program) { | 220 void writeUriToSource(Program program) { |
| 221 _binaryOffsetForSourceTable = _sink.flushedLength + _sink.length; |
| 198 program.uriToSource.keys.forEach((uri) { | 222 program.uriToSource.keys.forEach((uri) { |
| 199 _sourceUriIndexer.put(uri); | 223 _sourceUriIndexer.put(uri); |
| 200 }); | 224 }); |
| 201 writeStringTable(_sourceUriIndexer); | 225 writeStringTable(_sourceUriIndexer); |
| 202 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 226 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
| 203 String uri = _sourceUriIndexer.entries[i].value; | 227 String uri = _sourceUriIndexer.entries[i].value; |
| 204 Source source = | 228 Source source = |
| 205 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); | 229 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); |
| 206 writeUtf8Bytes(source.source); | 230 writeUtf8Bytes(source.source); |
| 207 List<int> lineStarts = source.lineStarts; | 231 List<int> lineStarts = source.lineStarts; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 // enclosing library. | 297 // enclosing library. |
| 274 if (node.isPrivate) { | 298 if (node.isPrivate) { |
| 275 writeLibraryReference(node.library); | 299 writeLibraryReference(node.library); |
| 276 } | 300 } |
| 277 } | 301 } |
| 278 | 302 |
| 279 bool insideExternalLibrary = false; | 303 bool insideExternalLibrary = false; |
| 280 | 304 |
| 281 visitLibrary(Library node) { | 305 visitLibrary(Library node) { |
| 282 insideExternalLibrary = node.isExternal; | 306 insideExternalLibrary = node.isExternal; |
| 307 node.binaryOffset = _sink.flushedLength + _sink.length; |
| 283 writeByte(insideExternalLibrary ? 1 : 0); | 308 writeByte(insideExternalLibrary ? 1 : 0); |
| 284 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); | 309 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); |
| 285 writeStringReference(node.name ?? ''); | 310 writeStringReference(node.name ?? ''); |
| 286 // TODO(jensj): We save (almost) the same URI twice. | 311 // TODO(jensj): We save (almost) the same URI twice. |
| 287 writeUriReference(node.fileUri ?? ''); | 312 writeUriReference(node.fileUri ?? ''); |
| 288 writeAnnotationList(node.annotations); | 313 writeAnnotationList(node.annotations); |
| 289 writeLibraryDependencies(node); | 314 writeLibraryDependencies(node); |
| 290 writeNodeList(node.typedefs); | 315 writeNodeList(node.typedefs); |
| 291 writeNodeList(node.classes); | 316 writeNodeList(node.classes); |
| 292 writeNodeList(node.fields); | 317 writeNodeList(node.fields); |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 class LibraryFilteringBinaryPrinter extends BinaryPrinter { | 1158 class LibraryFilteringBinaryPrinter extends BinaryPrinter { |
| 1134 final LibraryFilter predicate; | 1159 final LibraryFilter predicate; |
| 1135 | 1160 |
| 1136 LibraryFilteringBinaryPrinter( | 1161 LibraryFilteringBinaryPrinter( |
| 1137 Sink<List<int>> sink, bool predicate(Library library)) | 1162 Sink<List<int>> sink, bool predicate(Library library)) |
| 1138 : predicate = predicate, | 1163 : predicate = predicate, |
| 1139 super(sink); | 1164 super(sink); |
| 1140 | 1165 |
| 1141 void writeProgramFile(Program program) { | 1166 void writeProgramFile(Program program) { |
| 1142 program.computeCanonicalNames(); | 1167 program.computeCanonicalNames(); |
| 1143 writeMagicWord(Tag.ProgramFile); | 1168 writeUInt32(Tag.ProgramFile); |
| 1144 stringIndexer.scanProgram(program); | 1169 stringIndexer.scanProgram(program); |
| 1145 writeStringTable(stringIndexer); | 1170 writeStringTable(stringIndexer); |
| 1146 writeUriToSource(program); | 1171 writeUriToSource(program); |
| 1147 writeLinkTable(program); | 1172 writeLinkTable(program); |
| 1148 writeList(program.libraries.where(predicate).toList(), writeNode); | 1173 final List<Library> filteredLibraries = |
| 1174 program.libraries.where(predicate).toList(); |
| 1175 writeList(filteredLibraries, writeNode); |
| 1149 writeMemberReference(program.mainMethod, allowNull: true); | 1176 writeMemberReference(program.mainMethod, allowNull: true); |
| 1177 writeProgramIndex(program, filteredLibraries); |
| 1178 |
| 1150 _flush(); | 1179 _flush(); |
| 1151 } | 1180 } |
| 1152 } | 1181 } |
| 1153 | 1182 |
| 1154 class VariableIndexer { | 1183 class VariableIndexer { |
| 1155 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; | 1184 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; |
| 1156 final List<int> scopes = <int>[]; | 1185 final List<int> scopes = <int>[]; |
| 1157 int stackHeight = 0; | 1186 int stackHeight = 0; |
| 1158 | 1187 |
| 1159 void declare(VariableDeclaration node) { | 1188 void declare(VariableDeclaration node) { |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1471 _sink.add(_buffer.sublist(0, length)); | 1500 _sink.add(_buffer.sublist(0, length)); |
| 1472 _buffer = new Uint8List(SIZE); | 1501 _buffer = new Uint8List(SIZE); |
| 1473 flushedLength += length; | 1502 flushedLength += length; |
| 1474 length = 0; | 1503 length = 0; |
| 1475 } | 1504 } |
| 1476 | 1505 |
| 1477 void flushAndDestroy() { | 1506 void flushAndDestroy() { |
| 1478 _sink.add(_buffer.sublist(0, length)); | 1507 _sink.add(_buffer.sublist(0, length)); |
| 1479 } | 1508 } |
| 1480 } | 1509 } |
| OLD | NEW |