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 |