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 = new 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 /// Create a printer that writes to the given [sink]. | 29 /// Create a printer that writes to the given [sink]. |
30 /// | 30 /// |
31 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 31 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
32 /// one. | 32 /// one. |
33 /// | 33 /// |
34 /// If multiple binaries are to be written based on the same IR, a shared | 34 /// 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 | 35 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
36 /// in every printer. | 36 /// in every printer. |
37 BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink); | 37 BinaryPrinter(Sink<List<int>> sink, {StringIndexer stringIndexer}) |
| 38 : _sink = new BufferedSink(sink), |
| 39 stringIndexer = stringIndexer ?? new StringIndexer(); |
38 | 40 |
39 void _flush() { | 41 void _flush() { |
40 _sink.flushAndDestroy(); | 42 _sink.flushAndDestroy(); |
41 } | 43 } |
42 | 44 |
43 void writeByte(int byte) { | 45 void writeByte(int byte) { |
44 _sink.addByte(byte); | 46 _sink.addByte(byte); |
45 } | 47 } |
46 | 48 |
47 void writeBytes(List<int> bytes) { | 49 void writeBytes(List<int> bytes) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 endOffset += entry.utf8Bytes.length; | 85 endOffset += entry.utf8Bytes.length; |
84 writeUInt30(endOffset); | 86 writeUInt30(endOffset); |
85 } | 87 } |
86 // Write the UTF-8 encoded strings. | 88 // Write the UTF-8 encoded strings. |
87 for (var entry in indexer.entries) { | 89 for (var entry in indexer.entries) { |
88 writeBytes(entry.utf8Bytes); | 90 writeBytes(entry.utf8Bytes); |
89 } | 91 } |
90 } | 92 } |
91 | 93 |
92 void writeStringReference(String string) { | 94 void writeStringReference(String string) { |
93 writeUInt30(_stringIndexer[string]); | 95 writeUInt30(stringIndexer[string]); |
94 } | 96 } |
95 | 97 |
96 void writeStringReferenceList(List<String> strings) { | 98 void writeStringReferenceList(List<String> strings) { |
97 writeList(strings, writeStringReference); | 99 writeList(strings, writeStringReference); |
98 } | 100 } |
99 | 101 |
100 void writeUriReference(String string) { | 102 void writeUriReference(String string) { |
101 int index = _sourceUriIndexer[string]; | 103 int index = _sourceUriIndexer[string]; |
102 if (index == null) { | 104 if (index == null) { |
103 // Assume file was loaded without linking. Bail out to empty string. | 105 // Assume file was loaded without linking. Bail out to empty string. |
(...skipping 26 matching lines...) Expand all Loading... |
130 | 132 |
131 void writeLinkTable(Program program) { | 133 void writeLinkTable(Program program) { |
132 List<CanonicalName> list = <CanonicalName>[]; | 134 List<CanonicalName> list = <CanonicalName>[]; |
133 void visitCanonicalName(CanonicalName node) { | 135 void visitCanonicalName(CanonicalName node) { |
134 node.index = list.length; | 136 node.index = list.length; |
135 list.add(node); | 137 list.add(node); |
136 node.children.forEach(visitCanonicalName); | 138 node.children.forEach(visitCanonicalName); |
137 } | 139 } |
138 | 140 |
139 for (var library in program.libraries) { | 141 for (var library in program.libraries) { |
| 142 if (!shouldWriteLibraryCanonicalNames(library)) continue; |
140 visitCanonicalName(library.canonicalName); | 143 visitCanonicalName(library.canonicalName); |
141 } | 144 } |
| 145 addCanonicalNamesForLinkTable(list); |
142 writeList(list, writeCanonicalNameEntry); | 146 writeList(list, writeCanonicalNameEntry); |
143 } | 147 } |
144 | 148 |
| 149 /// Return `true` if all canonical names of the [library] should be written |
| 150 /// into the link table. If some libraries of the program are skipped, |
| 151 /// then [addCanonicalNamesForLinkTable] should append all the additional |
| 152 /// names referenced by the libraries that are written by [writeLibraries]. |
| 153 bool shouldWriteLibraryCanonicalNames(Library library) => true; |
| 154 |
| 155 /// Append additional names for entities that are referenced by the |
| 156 /// libraries that are written by [writeLibraries], but declared outside |
| 157 /// of these libraries. |
| 158 void addCanonicalNamesForLinkTable(List<CanonicalName> list) {} |
| 159 |
145 void writeCanonicalNameEntry(CanonicalName node) { | 160 void writeCanonicalNameEntry(CanonicalName node) { |
146 var parent = node.parent; | 161 var parent = node.parent; |
147 if (parent.isRoot) { | 162 if (parent.isRoot) { |
148 writeByte(0); | 163 writeByte(0); |
149 } else { | 164 } else { |
150 writeUInt30(parent.index + 1); | 165 writeUInt30(parent.index + 1); |
151 } | 166 } |
152 writeStringReference(node.name); | 167 writeStringReference(node.name); |
153 } | 168 } |
154 | 169 |
155 void writeProgramFile(Program program) { | 170 void writeProgramFile(Program program) { |
156 program.computeCanonicalNames(); | 171 program.computeCanonicalNames(); |
157 writeMagicWord(Tag.ProgramFile); | 172 writeMagicWord(Tag.ProgramFile); |
158 _stringIndexer.scanProgram(program); | 173 buildStringIndex(program); |
159 writeStringTable(_stringIndexer); | 174 writeStringTable(stringIndexer); |
160 writeUriToSource(program); | 175 writeUriToSource(program); |
161 writeLinkTable(program); | 176 writeLinkTable(program); |
162 writeList(program.libraries, writeNode); | 177 writeLibraries(program); |
163 writeMemberReference(program.mainMethod, allowNull: true); | 178 writeMemberReference(program.mainMethod, allowNull: true); |
164 _flush(); | 179 _flush(); |
165 } | 180 } |
166 | 181 |
| 182 /// Fill the [stringIndexer] with all strings we are going to reference. |
| 183 void buildStringIndex(Program program) { |
| 184 stringIndexer.scanProgram(program); |
| 185 } |
| 186 |
| 187 /// Write all of some of the libraries of the [program]. |
| 188 void writeLibraries(Program program) { |
| 189 writeList(program.libraries, writeNode); |
| 190 } |
| 191 |
167 void writeUriToSource(Program program) { | 192 void writeUriToSource(Program program) { |
168 program.uriToSource.keys.forEach((uri) { | 193 program.uriToSource.keys.forEach((uri) { |
169 _sourceUriIndexer.put(uri); | 194 _sourceUriIndexer.put(uri); |
170 }); | 195 }); |
171 writeStringTable(_sourceUriIndexer); | 196 writeStringTable(_sourceUriIndexer); |
172 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 197 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
173 String uri = _sourceUriIndexer.entries[i].value; | 198 String uri = _sourceUriIndexer.entries[i].value; |
174 Source source = | 199 Source source = |
175 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); | 200 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); |
176 writeUtf8Bytes(source.source); | 201 writeUtf8Bytes(source.source); |
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 final LibraryFilter predicate; | 1107 final LibraryFilter predicate; |
1083 | 1108 |
1084 LibraryFilteringBinaryPrinter( | 1109 LibraryFilteringBinaryPrinter( |
1085 Sink<List<int>> sink, bool predicate(Library library)) | 1110 Sink<List<int>> sink, bool predicate(Library library)) |
1086 : predicate = predicate, | 1111 : predicate = predicate, |
1087 super(sink); | 1112 super(sink); |
1088 | 1113 |
1089 void writeProgramFile(Program program) { | 1114 void writeProgramFile(Program program) { |
1090 program.computeCanonicalNames(); | 1115 program.computeCanonicalNames(); |
1091 writeMagicWord(Tag.ProgramFile); | 1116 writeMagicWord(Tag.ProgramFile); |
1092 _stringIndexer.scanProgram(program); | 1117 stringIndexer.scanProgram(program); |
1093 writeStringTable(_stringIndexer); | 1118 writeStringTable(stringIndexer); |
1094 writeUriToSource(program); | 1119 writeUriToSource(program); |
1095 writeLinkTable(program); | 1120 writeLinkTable(program); |
1096 writeList(program.libraries.where(predicate).toList(), writeNode); | 1121 writeList(program.libraries.where(predicate).toList(), writeNode); |
1097 writeMemberReference(program.mainMethod, allowNull: true); | 1122 writeMemberReference(program.mainMethod, allowNull: true); |
1098 _flush(); | 1123 _flush(); |
1099 } | 1124 } |
1100 } | 1125 } |
1101 | 1126 |
1102 class VariableIndexer { | 1127 class VariableIndexer { |
1103 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; | 1128 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1190 class StringIndexer extends RecursiveVisitor<Null> { | 1215 class StringIndexer extends RecursiveVisitor<Null> { |
1191 final List<StringTableEntry> entries = <StringTableEntry>[]; | 1216 final List<StringTableEntry> entries = <StringTableEntry>[]; |
1192 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); | 1217 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); |
1193 | 1218 |
1194 StringIndexer() { | 1219 StringIndexer() { |
1195 put(''); | 1220 put(''); |
1196 } | 1221 } |
1197 | 1222 |
1198 int get numberOfStrings => index.length; | 1223 int get numberOfStrings => index.length; |
1199 | 1224 |
1200 void scanProgram(Node node) { | 1225 /// Scan all the [program] libraries and [finish] indexing. |
1201 node.accept(this); | 1226 void scanProgram(Program program) { |
| 1227 program.accept(this); |
| 1228 finish(); |
| 1229 } |
| 1230 |
| 1231 /// Scan the given library, but don't [finish] indexing yet. |
| 1232 void scanLibrary(Library library) { |
| 1233 library.accept(this); |
| 1234 } |
| 1235 |
| 1236 /// Finish building of the index - sort and assign indices for entries. |
| 1237 void finish() { |
1202 entries.sort(); | 1238 entries.sort(); |
1203 for (int i = 0; i < entries.length; ++i) { | 1239 for (int i = 0; i < entries.length; ++i) { |
1204 index[entries[i].value] = i; | 1240 index[entries[i].value] = i; |
1205 } | 1241 } |
1206 } | 1242 } |
1207 | 1243 |
1208 void visitCanonicalName(CanonicalName name) { | 1244 void visitCanonicalName(CanonicalName name) { |
1209 put(name.name); | 1245 put(name.name); |
1210 name.children.forEach(visitCanonicalName); | 1246 name.children.forEach(visitCanonicalName); |
1211 } | 1247 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1405 _sink.add(_buffer.sublist(0, length)); | 1441 _sink.add(_buffer.sublist(0, length)); |
1406 _buffer = new Uint8List(SIZE); | 1442 _buffer = new Uint8List(SIZE); |
1407 flushedLength += length; | 1443 flushedLength += length; |
1408 length = 0; | 1444 length = 0; |
1409 } | 1445 } |
1410 | 1446 |
1411 void flushAndDestroy() { | 1447 void flushAndDestroy() { |
1412 _sink.add(_buffer.sublist(0, length)); | 1448 _sink.add(_buffer.sublist(0, length)); |
1413 } | 1449 } |
1414 } | 1450 } |
OLD | NEW |