| 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 |