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 |