Chromium Code Reviews| 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 |
| 71 void writeUInt32(int value) { | |
| 72 writeByte((value >> 24) & 0xFF); | |
| 73 writeByte((value >> 16) & 0xFF); | |
| 74 writeByte((value >> 8) & 0xFF); | |
| 75 writeByte(value & 0xFF); | |
| 76 } | |
| 77 | |
| 68 void writeMagicWord(int value) { | 78 void writeMagicWord(int value) { |
|
Kevin Millikin (Google)
2017/06/29 12:27:36
Why replace readMagicWord with readUInt32 but not
jensj
2017/06/30 05:51:17
Done.
| |
| 69 writeByte((value >> 24) & 0xFF); | 79 writeByte((value >> 24) & 0xFF); |
| 70 writeByte((value >> 16) & 0xFF); | 80 writeByte((value >> 16) & 0xFF); |
| 71 writeByte((value >> 8) & 0xFF); | 81 writeByte((value >> 8) & 0xFF); |
| 72 writeByte(value & 0xFF); | 82 writeByte(value & 0xFF); |
| 73 } | 83 } |
| 74 | 84 |
| 75 void writeUtf8Bytes(List<int> utf8Bytes) { | 85 void writeUtf8Bytes(List<int> utf8Bytes) { |
| 76 writeUInt30(utf8Bytes.length); | 86 writeUInt30(utf8Bytes.length); |
| 77 writeBytes(utf8Bytes); | 87 writeBytes(utf8Bytes); |
| 78 } | 88 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 void writeOptionalNode(Node node) { | 134 void writeOptionalNode(Node node) { |
| 125 if (node == null) { | 135 if (node == null) { |
| 126 writeByte(Tag.Nothing); | 136 writeByte(Tag.Nothing); |
| 127 } else { | 137 } else { |
| 128 writeByte(Tag.Something); | 138 writeByte(Tag.Something); |
| 129 writeNode(node); | 139 writeNode(node); |
| 130 } | 140 } |
| 131 } | 141 } |
| 132 | 142 |
| 133 void writeLinkTable(Program program) { | 143 void writeLinkTable(Program program) { |
| 144 _binaryOffsetForLinkTable = _sink.flushedLength + _sink.length; | |
| 134 List<CanonicalName> list = <CanonicalName>[]; | 145 List<CanonicalName> list = <CanonicalName>[]; |
| 135 void visitCanonicalName(CanonicalName node) { | 146 void visitCanonicalName(CanonicalName node) { |
| 136 node.index = list.length; | 147 node.index = list.length; |
| 137 list.add(node); | 148 list.add(node); |
| 138 node.children.forEach(visitCanonicalName); | 149 node.children.forEach(visitCanonicalName); |
| 139 } | 150 } |
| 140 | 151 |
| 141 for (var library in program.libraries) { | 152 for (var library in program.libraries) { |
| 142 if (!shouldWriteLibraryCanonicalNames(library)) continue; | 153 if (!shouldWriteLibraryCanonicalNames(library)) continue; |
| 143 visitCanonicalName(library.canonicalName); | 154 visitCanonicalName(library.canonicalName); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 174 | 185 |
| 175 void writeProgramFile(Program program) { | 186 void writeProgramFile(Program program) { |
| 176 computeCanonicalNames(program); | 187 computeCanonicalNames(program); |
| 177 writeMagicWord(Tag.ProgramFile); | 188 writeMagicWord(Tag.ProgramFile); |
| 178 buildStringIndex(program); | 189 buildStringIndex(program); |
| 179 writeStringTable(stringIndexer); | 190 writeStringTable(stringIndexer); |
| 180 writeUriToSource(program); | 191 writeUriToSource(program); |
| 181 writeLinkTable(program); | 192 writeLinkTable(program); |
| 182 writeLibraries(program); | 193 writeLibraries(program); |
| 183 writeMemberReference(program.mainMethod, allowNull: true); | 194 writeMemberReference(program.mainMethod, allowNull: true); |
| 195 | |
| 196 // Fixed-size ints at the end. | |
| 197 writeFixedProgramFooter(program, program.libraries); | |
|
Kevin Millikin (Google)
2017/06/29 12:27:36
Adopt a uniform terminology. In the comments this
jensj
2017/06/30 05:51:17
I have uniformly renamed to "program index".
| |
| 198 | |
| 184 _flush(); | 199 _flush(); |
| 185 } | 200 } |
| 186 | 201 |
| 187 /// Fill the [stringIndexer] with all strings we are going to reference. | 202 /// Fill the [stringIndexer] with all strings we are going to reference. |
| 188 void buildStringIndex(Program program) { | 203 void buildStringIndex(Program program) { |
| 189 stringIndexer.scanProgram(program); | 204 stringIndexer.scanProgram(program); |
| 190 } | 205 } |
| 191 | 206 |
| 192 /// Write all of some of the libraries of the [program]. | 207 /// Write all of some of the libraries of the [program]. |
| 193 void writeLibraries(Program program) { | 208 void writeLibraries(Program program) { |
| 194 writeList(program.libraries, writeNode); | 209 writeList(program.libraries, writeNode); |
| 195 } | 210 } |
| 196 | 211 |
| 212 void writeFixedProgramFooter(Program program, List<Library> libraries) { | |
| 213 // Fixed-size ints at the end. | |
| 214 writeUInt32(_binaryOffsetForSourceTable); | |
| 215 writeUInt32(_binaryOffsetForLinkTable); | |
| 216 | |
| 217 CanonicalName main = getCanonicalNameOfMember(program.mainMethod); | |
| 218 if (main == null) { | |
| 219 writeUInt32(0); | |
| 220 } else { | |
| 221 writeUInt32(main.index + 1); | |
| 222 } | |
| 223 for (Library library in libraries) { | |
| 224 writeUInt32(library.binaryOffset); | |
| 225 } | |
| 226 writeUInt32(libraries.length); | |
| 227 } | |
| 228 | |
| 197 void writeUriToSource(Program program) { | 229 void writeUriToSource(Program program) { |
| 230 _binaryOffsetForSourceTable = _sink.flushedLength + _sink.length; | |
| 198 program.uriToSource.keys.forEach((uri) { | 231 program.uriToSource.keys.forEach((uri) { |
| 199 _sourceUriIndexer.put(uri); | 232 _sourceUriIndexer.put(uri); |
| 200 }); | 233 }); |
| 201 writeStringTable(_sourceUriIndexer); | 234 writeStringTable(_sourceUriIndexer); |
| 202 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 235 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
| 203 String uri = _sourceUriIndexer.entries[i].value; | 236 String uri = _sourceUriIndexer.entries[i].value; |
| 204 Source source = | 237 Source source = |
| 205 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); | 238 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); |
| 206 writeUtf8Bytes(source.source); | 239 writeUtf8Bytes(source.source); |
| 207 List<int> lineStarts = source.lineStarts; | 240 List<int> lineStarts = source.lineStarts; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 // enclosing library. | 306 // enclosing library. |
| 274 if (node.isPrivate) { | 307 if (node.isPrivate) { |
| 275 writeLibraryReference(node.library); | 308 writeLibraryReference(node.library); |
| 276 } | 309 } |
| 277 } | 310 } |
| 278 | 311 |
| 279 bool insideExternalLibrary = false; | 312 bool insideExternalLibrary = false; |
| 280 | 313 |
| 281 visitLibrary(Library node) { | 314 visitLibrary(Library node) { |
| 282 insideExternalLibrary = node.isExternal; | 315 insideExternalLibrary = node.isExternal; |
| 316 node.binaryOffset = _sink.flushedLength + _sink.length; | |
| 283 writeByte(insideExternalLibrary ? 1 : 0); | 317 writeByte(insideExternalLibrary ? 1 : 0); |
| 284 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); | 318 writeCanonicalNameReference(getCanonicalNameOfLibrary(node)); |
| 285 writeStringReference(node.name ?? ''); | 319 writeStringReference(node.name ?? ''); |
| 286 // TODO(jensj): We save (almost) the same URI twice. | 320 // TODO(jensj): We save (almost) the same URI twice. |
| 287 writeUriReference(node.fileUri ?? ''); | 321 writeUriReference(node.fileUri ?? ''); |
| 288 writeAnnotationList(node.annotations); | 322 writeAnnotationList(node.annotations); |
| 289 writeLibraryDependencies(node); | 323 writeLibraryDependencies(node); |
| 290 writeNodeList(node.typedefs); | 324 writeNodeList(node.typedefs); |
| 291 writeNodeList(node.classes); | 325 writeNodeList(node.classes); |
| 292 writeNodeList(node.fields); | 326 writeNodeList(node.fields); |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1138 : predicate = predicate, | 1172 : predicate = predicate, |
| 1139 super(sink); | 1173 super(sink); |
| 1140 | 1174 |
| 1141 void writeProgramFile(Program program) { | 1175 void writeProgramFile(Program program) { |
| 1142 program.computeCanonicalNames(); | 1176 program.computeCanonicalNames(); |
| 1143 writeMagicWord(Tag.ProgramFile); | 1177 writeMagicWord(Tag.ProgramFile); |
| 1144 stringIndexer.scanProgram(program); | 1178 stringIndexer.scanProgram(program); |
| 1145 writeStringTable(stringIndexer); | 1179 writeStringTable(stringIndexer); |
| 1146 writeUriToSource(program); | 1180 writeUriToSource(program); |
| 1147 writeLinkTable(program); | 1181 writeLinkTable(program); |
| 1148 writeList(program.libraries.where(predicate).toList(), writeNode); | 1182 final List<Library> filteredLibraries = |
| 1183 program.libraries.where(predicate).toList(); | |
| 1184 writeList(filteredLibraries, writeNode); | |
| 1149 writeMemberReference(program.mainMethod, allowNull: true); | 1185 writeMemberReference(program.mainMethod, allowNull: true); |
| 1186 | |
| 1187 // Fixed-size ints at the end. | |
| 1188 writeFixedProgramFooter(program, filteredLibraries); | |
| 1189 | |
| 1150 _flush(); | 1190 _flush(); |
| 1151 } | 1191 } |
| 1152 } | 1192 } |
| 1153 | 1193 |
| 1154 class VariableIndexer { | 1194 class VariableIndexer { |
| 1155 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; | 1195 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; |
| 1156 final List<int> scopes = <int>[]; | 1196 final List<int> scopes = <int>[]; |
| 1157 int stackHeight = 0; | 1197 int stackHeight = 0; |
| 1158 | 1198 |
| 1159 void declare(VariableDeclaration node) { | 1199 void declare(VariableDeclaration node) { |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1471 _sink.add(_buffer.sublist(0, length)); | 1511 _sink.add(_buffer.sublist(0, length)); |
| 1472 _buffer = new Uint8List(SIZE); | 1512 _buffer = new Uint8List(SIZE); |
| 1473 flushedLength += length; | 1513 flushedLength += length; |
| 1474 length = 0; | 1514 length = 0; |
| 1475 } | 1515 } |
| 1476 | 1516 |
| 1477 void flushAndDestroy() { | 1517 void flushAndDestroy() { |
| 1478 _sink.add(_buffer.sublist(0, length)); | 1518 _sink.add(_buffer.sublist(0, length)); |
| 1479 } | 1519 } |
| 1480 } | 1520 } |
| OLD | NEW |