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 StringIndexer _stringIndexer; |
ahe
2017/05/22 09:27:05
You can keep this final by adding an optional para
ahe
2017/05/22 09:27:05
Seems like you need this field to be public.
scheglov
2017/05/22 20:36:01
Done.
scheglov
2017/05/22 20:36:01
Done.
| |
23 final StringIndexer _sourceUriIndexer = new StringIndexer(); | 23 final StringIndexer _sourceUriIndexer = new StringIndexer(); |
24 Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{}; | 24 Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{}; |
25 | 25 |
26 final BufferedSink _sink; | 26 final BufferedSink _sink; |
27 | 27 |
28 /// Create a printer that writes to the given [sink]. | 28 /// Create a printer that writes to the given [sink]. |
29 /// | 29 /// |
30 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 30 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
31 /// one. | 31 /// one. |
32 /// | 32 /// |
33 /// If multiple binaries are to be written based on the same IR, a shared | 33 /// If multiple binaries are to be written based on the same IR, a shared |
34 /// [globalIndexer] may be passed in to avoid rebuilding the same indices | 34 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
35 /// in every printer. | 35 /// in every printer. |
36 BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink); | 36 BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink) { |
37 _stringIndexer = createStringIndexer(); | |
38 } | |
39 | |
40 StringIndexer createStringIndexer() => new StringIndexer(); | |
37 | 41 |
38 void _flush() { | 42 void _flush() { |
39 _sink.flushAndDestroy(); | 43 _sink.flushAndDestroy(); |
40 } | 44 } |
41 | 45 |
42 void writeByte(int byte) { | 46 void writeByte(int byte) { |
43 _sink.addByte(byte); | 47 _sink.addByte(byte); |
44 } | 48 } |
45 | 49 |
46 void writeBytes(List<int> bytes) { | 50 void writeBytes(List<int> bytes) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 | 129 |
126 void writeLinkTable(Program program) { | 130 void writeLinkTable(Program program) { |
127 List<CanonicalName> list = <CanonicalName>[]; | 131 List<CanonicalName> list = <CanonicalName>[]; |
128 void visitCanonicalName(CanonicalName node) { | 132 void visitCanonicalName(CanonicalName node) { |
129 node.index = list.length; | 133 node.index = list.length; |
130 list.add(node); | 134 list.add(node); |
131 node.children.forEach(visitCanonicalName); | 135 node.children.forEach(visitCanonicalName); |
132 } | 136 } |
133 | 137 |
134 for (var library in program.libraries) { | 138 for (var library in program.libraries) { |
139 if (!shouldWriteLibraryCanonicalNames(library)) continue; | |
135 visitCanonicalName(library.canonicalName); | 140 visitCanonicalName(library.canonicalName); |
136 } | 141 } |
142 addCanonicalNamesForLinkTable(list); | |
137 writeList(list, writeCanonicalNameEntry); | 143 writeList(list, writeCanonicalNameEntry); |
138 } | 144 } |
139 | 145 |
146 /// Return `true` if all canonical names of the [library] should be written | |
147 /// into the link table. If some libraries of the program are skipped, | |
148 /// then [addCanonicalNamesForLinkTable] should append all the additional | |
149 /// names referenced by the libraries that are written by [writeLibraries]. | |
150 bool shouldWriteLibraryCanonicalNames(Library library) => true; | |
151 | |
152 /// Append additional names for entities that are referenced by the | |
153 /// libraries that are written by [writeLibraries], but declared outside | |
154 /// of these libraries. | |
155 void addCanonicalNamesForLinkTable(List<CanonicalName> list) {} | |
156 | |
140 void writeCanonicalNameEntry(CanonicalName node) { | 157 void writeCanonicalNameEntry(CanonicalName node) { |
141 var parent = node.parent; | 158 var parent = node.parent; |
142 if (parent.isRoot) { | 159 if (parent.isRoot) { |
143 writeByte(0); | 160 writeByte(0); |
144 } else { | 161 } else { |
145 writeUInt30(parent.index + 1); | 162 writeUInt30(parent.index + 1); |
146 } | 163 } |
147 writeStringReference(node.name); | 164 writeStringReference(node.name); |
148 } | 165 } |
149 | 166 |
150 void writeProgramFile(Program program) { | 167 void writeProgramFile(Program program) { |
151 program.computeCanonicalNames(); | 168 program.computeCanonicalNames(); |
152 writeMagicWord(Tag.ProgramFile); | 169 writeMagicWord(Tag.ProgramFile); |
153 _stringIndexer.scanProgram(program); | 170 buildStringIndex(program); |
154 writeStringTable(_stringIndexer); | 171 writeStringTable(_stringIndexer); |
155 writeUriToSource(program); | 172 writeUriToSource(program); |
156 writeLinkTable(program); | 173 writeLinkTable(program); |
157 writeList(program.libraries, writeNode); | 174 writeLibraries(program); |
158 writeMemberReference(program.mainMethod, allowNull: true); | 175 writeMemberReference(program.mainMethod, allowNull: true); |
159 _flush(); | 176 _flush(); |
160 } | 177 } |
161 | 178 |
179 /// Fill the [_stringIndexer] with all strings we are going to reference. | |
180 void buildStringIndex(Program program) { | |
181 _stringIndexer.scanProgram(program); | |
182 } | |
183 | |
184 /// Write all of some of the libraries of the [program]. | |
185 void writeLibraries(Program program) { | |
186 writeList(program.libraries, writeNode); | |
187 } | |
188 | |
162 void writeUriToSource(Program program) { | 189 void writeUriToSource(Program program) { |
163 program.uriToSource.keys.forEach((uri) { | 190 program.uriToSource.keys.forEach((uri) { |
164 _sourceUriIndexer.put(uri); | 191 _sourceUriIndexer.put(uri); |
165 }); | 192 }); |
166 writeStringTable(_sourceUriIndexer); | 193 writeStringTable(_sourceUriIndexer); |
167 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { | 194 for (int i = 0; i < _sourceUriIndexer.entries.length; i++) { |
168 String uri = _sourceUriIndexer.entries[i].value; | 195 String uri = _sourceUriIndexer.entries[i].value; |
169 Source source = | 196 Source source = |
170 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); | 197 program.uriToSource[uri] ?? new Source(<int>[], const <int>[]); |
171 writeUtf8Bytes(source.source); | 198 writeUtf8Bytes(source.source); |
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1176 class StringIndexer extends RecursiveVisitor<Null> { | 1203 class StringIndexer extends RecursiveVisitor<Null> { |
1177 final List<StringTableEntry> entries = <StringTableEntry>[]; | 1204 final List<StringTableEntry> entries = <StringTableEntry>[]; |
1178 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); | 1205 final LinkedHashMap<String, int> index = new LinkedHashMap<String, int>(); |
1179 | 1206 |
1180 StringIndexer() { | 1207 StringIndexer() { |
1181 put(''); | 1208 put(''); |
1182 } | 1209 } |
1183 | 1210 |
1184 int get numberOfStrings => index.length; | 1211 int get numberOfStrings => index.length; |
1185 | 1212 |
1186 void scanProgram(Node node) { | 1213 /// Scan all the [program] libraries and [finish] indexing. |
1187 node.accept(this); | 1214 void scanProgram(Program program) { |
1215 program.accept(this); | |
1216 finish(); | |
1217 } | |
1218 | |
1219 /// Scan the given library, but don't [finish] indexing yet. | |
1220 void scanLibrary(Library library) { | |
1221 library.accept(this); | |
1222 } | |
1223 | |
1224 /// Finish building of the index - sort and assign indices for entries. | |
1225 void finish() { | |
1188 entries.sort(); | 1226 entries.sort(); |
1189 for (int i = 0; i < entries.length; ++i) { | 1227 for (int i = 0; i < entries.length; ++i) { |
1190 index[entries[i].value] = i; | 1228 index[entries[i].value] = i; |
1191 } | 1229 } |
1192 } | 1230 } |
1193 | 1231 |
1194 void visitCanonicalName(CanonicalName name) { | 1232 void visitCanonicalName(CanonicalName name) { |
1195 put(name.name); | 1233 put(name.name); |
1196 name.children.forEach(visitCanonicalName); | 1234 name.children.forEach(visitCanonicalName); |
1197 } | 1235 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1381 _sink.add(_buffer.sublist(0, length)); | 1419 _sink.add(_buffer.sublist(0, length)); |
1382 _buffer = new Uint8List(SIZE); | 1420 _buffer = new Uint8List(SIZE); |
1383 flushedLength += length; | 1421 flushedLength += length; |
1384 length = 0; | 1422 length = 0; |
1385 } | 1423 } |
1386 | 1424 |
1387 void flushAndDestroy() { | 1425 void flushAndDestroy() { |
1388 _sink.add(_buffer.sublist(0, length)); | 1426 _sink.add(_buffer.sublist(0, length)); |
1389 } | 1427 } |
1390 } | 1428 } |
OLD | NEW |