| Index: pkg/kernel/lib/binary/ast_to_binary.dart
|
| diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
|
| index a137d86542196b7e7a2fc10099db832d817cad1a..3dceabca321ea19b324efb69bae6e7cc2d60778d 100644
|
| --- a/pkg/kernel/lib/binary/ast_to_binary.dart
|
| +++ b/pkg/kernel/lib/binary/ast_to_binary.dart
|
| @@ -15,13 +15,10 @@ import 'dart:collection';
|
| /// A [BinaryPrinter] can be used to write one file and must then be
|
| /// discarded.
|
| class BinaryPrinter extends Visitor {
|
| - ImportTable _importTable;
|
| -
|
| VariableIndexer _variableIndexer;
|
| LabelIndexer _labelIndexer;
|
| SwitchCaseIndexer _switchCaseIndexer;
|
| final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer();
|
| - final GlobalIndexer _globalIndexer;
|
| final StringIndexer _stringIndexer = new StringIndexer();
|
| final StringIndexer _sourceUriIndexer = new StringIndexer();
|
| Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{};
|
| @@ -36,9 +33,7 @@ class BinaryPrinter extends Visitor {
|
| /// If multiple binaries are to be written based on the same IR, a shared
|
| /// [globalIndexer] may be passed in to avoid rebuilding the same indices
|
| /// in every printer.
|
| - BinaryPrinter(Sink<List<int>> sink, {GlobalIndexer globalIndexer})
|
| - : _sink = new BufferedSink(sink),
|
| - _globalIndexer = globalIndexer ?? new GlobalIndexer();
|
| + BinaryPrinter(Sink<List<int>> sink) : _sink = new BufferedSink(sink);
|
|
|
| void _flush() {
|
| _sink.flushAndDestroy();
|
| @@ -133,12 +128,37 @@ class BinaryPrinter extends Visitor {
|
| }
|
| }
|
|
|
| + void writeLinkTable(Program program) {
|
| + List<CanonicalName> list = <CanonicalName>[];
|
| + void visitCanonicalName(CanonicalName node) {
|
| + node.index = list.length;
|
| + list.add(node);
|
| + node.children.forEach(visitCanonicalName);
|
| + }
|
| +
|
| + for (var library in program.libraries) {
|
| + visitCanonicalName(library.canonicalName);
|
| + }
|
| + writeList(list, writeCanonicalNameEntry);
|
| + }
|
| +
|
| + void writeCanonicalNameEntry(CanonicalName node) {
|
| + var parent = node.parent;
|
| + if (parent.isRoot) {
|
| + writeByte(0);
|
| + } else {
|
| + writeUInt30(parent.index + 1);
|
| + }
|
| + writeStringReference(node.name);
|
| + }
|
| +
|
| void writeProgramFile(Program program) {
|
| + program.computeCanonicalNames();
|
| writeMagicWord(Tag.ProgramFile);
|
| - _importTable = new ProgramImportTable(program);
|
| - _stringIndexer.build(program);
|
| + _stringIndexer.scanProgram(program);
|
| writeStringTable(_stringIndexer);
|
| writeUriToSource(program);
|
| + writeLinkTable(program);
|
| writeList(program.libraries, writeNode);
|
| writeMemberReference(program.mainMethod, allowNull: true);
|
| _flush();
|
| @@ -164,18 +184,6 @@ class BinaryPrinter extends Visitor {
|
| }
|
| }
|
|
|
| - void writeLibraryImportTable(LibraryImportTable imports) {
|
| - writeList(imports.importPaths, writeStringReference);
|
| - }
|
| -
|
| - void writeLibraryReference(Library node) {
|
| - int index = _importTable.getImportIndex(node);
|
| - if (index == -1) {
|
| - throw 'Missing import for library: ${node.importUri}';
|
| - }
|
| - writeUInt30(index);
|
| - }
|
| -
|
| void writeDeferredImportReference(DeferredImport node) {
|
| int index = _deferredImportIndexer[node];
|
| if (index == null) {
|
| @@ -184,34 +192,30 @@ class BinaryPrinter extends Visitor {
|
| writeUInt30(index);
|
| }
|
|
|
| - void writeClassIndex(Class node) {
|
| - writeUInt30(_globalIndexer[node]);
|
| - }
|
| -
|
| - void writeClassReference(Class node, {bool allowNull: false}) {
|
| - if (node == null) {
|
| - if (allowNull) {
|
| - writeByte(Tag.NullReference);
|
| - } else {
|
| - throw 'Expected a class reference to be valid but was `null`.';
|
| - }
|
| + void writeReference(Reference reference) {
|
| + if (reference == null) {
|
| + writeByte(0);
|
| } else {
|
| - node.acceptReference(this);
|
| + CanonicalName name = reference.canonicalName;
|
| + if (name == null) {
|
| + throw 'Missing canonical name for $reference';
|
| + }
|
| + writeUInt30(name.index + 1);
|
| }
|
| }
|
|
|
| - void writeMemberReference(Member node, {bool allowNull: false}) {
|
| - if (node == null) {
|
| - if (allowNull) {
|
| - writeByte(Tag.NullReference);
|
| - } else {
|
| - throw 'Expected a member reference to be valid but was `null`.';
|
| - }
|
| + void writeCanonicalNameReference(CanonicalName name) {
|
| + if (name == null) {
|
| + writeByte(0);
|
| } else {
|
| - node.acceptReference(this);
|
| + writeUInt30(name.index + 1);
|
| }
|
| }
|
|
|
| + void writeLibraryReference(Library node) {
|
| + writeCanonicalNameReference(node.canonicalName);
|
| + }
|
| +
|
| writeOffset(TreeNode node, int offset) {
|
| // TODO(jensj): Delta-encoding.
|
| // File offset ranges from -1 and up,
|
| @@ -219,45 +223,18 @@ class BinaryPrinter extends Visitor {
|
| writeUInt30(offset + 1);
|
| }
|
|
|
| - void visitClassReference(Class node) {
|
| - var library = node.enclosingLibrary;
|
| - writeByte(node.isMixinApplication
|
| - ? Tag.MixinClassReference
|
| - : Tag.NormalClassReference);
|
| - writeLibraryReference(library);
|
| - writeClassIndex(node);
|
| - }
|
| -
|
| - void visitFieldReference(Field node) {
|
| - if (node.enclosingClass != null) {
|
| - writeByte(Tag.ClassFieldReference);
|
| - Class classNode = node.enclosingClass;
|
| - writeClassReference(classNode);
|
| - writeUInt30(_globalIndexer[node]);
|
| - } else {
|
| - writeByte(Tag.LibraryFieldReference);
|
| - writeLibraryReference(node.enclosingLibrary);
|
| - writeUInt30(_globalIndexer[node]);
|
| + void writeClassReference(Class class_, {bool allowNull: false}) {
|
| + if (class_ == null && !allowNull) {
|
| + throw 'Expected a class reference to be valid but was `null`.';
|
| }
|
| + writeCanonicalNameReference(getCanonicalNameOfClass(class_));
|
| }
|
|
|
| - void visitConstructorReference(Constructor node) {
|
| - writeByte(Tag.ClassConstructorReference);
|
| - writeClassReference(node.enclosingClass);
|
| - writeUInt30(_globalIndexer[node]);
|
| - }
|
| -
|
| - void visitProcedureReference(Procedure node) {
|
| - if (node.enclosingClass != null) {
|
| - writeByte(Tag.ClassProcedureReference);
|
| - Class classNode = node.enclosingClass;
|
| - writeClassReference(classNode);
|
| - writeUInt30(_globalIndexer[node]);
|
| - } else {
|
| - writeByte(Tag.LibraryProcedureReference);
|
| - writeLibraryReference(node.enclosingLibrary);
|
| - writeUInt30(_globalIndexer[node]);
|
| + void writeMemberReference(Member member, {bool allowNull: false}) {
|
| + if (member == null && !allowNull) {
|
| + throw 'Expected a member reference to be valid but was `null`.';
|
| }
|
| + writeCanonicalNameReference(getCanonicalNameOfMember(member));
|
| }
|
|
|
| void writeName(Name node) {
|
| @@ -274,8 +251,8 @@ class BinaryPrinter extends Visitor {
|
| visitLibrary(Library node) {
|
| insideExternalLibrary = node.isExternal;
|
| writeByte(insideExternalLibrary ? 1 : 0);
|
| + writeCanonicalNameReference(getCanonicalNameOfLibrary(node));
|
| writeStringReference(node.name ?? '');
|
| - writeStringReference('${node.importUri}');
|
| // TODO(jensj): We save (almost) the same URI twice.
|
| writeUriReference(node.fileUri ?? '');
|
| writeDeferredImports(node);
|
| @@ -318,43 +295,36 @@ class BinaryPrinter extends Visitor {
|
|
|
| visitClass(Class node) {
|
| int flags = _encodeClassFlags(node.isAbstract, node.level);
|
| - if (node.isMixinApplication) {
|
| - writeByte(Tag.MixinClass);
|
| - writeOffset(node, node.fileOffset);
|
| - writeByte(flags);
|
| - writeStringReference(node.name ?? '');
|
| - writeUriReference(node.fileUri ?? '');
|
| - writeAnnotationList(node.annotations);
|
| - _typeParameterIndexer.enter(node.typeParameters);
|
| - writeNodeList(node.typeParameters);
|
| - writeNode(node.supertype);
|
| - writeNode(node.mixedInType);
|
| - writeNodeList(node.implementedTypes);
|
| - writeNodeList(node.constructors);
|
| - _typeParameterIndexer.exit(node.typeParameters);
|
| - } else {
|
| - writeByte(Tag.NormalClass);
|
| - writeOffset(node, node.fileOffset);
|
| - writeByte(flags);
|
| - writeStringReference(node.name ?? '');
|
| - writeUriReference(node.fileUri ?? '');
|
| - writeAnnotationList(node.annotations);
|
| - _typeParameterIndexer.enter(node.typeParameters);
|
| - writeNodeList(node.typeParameters);
|
| - writeOptionalNode(node.supertype);
|
| - writeNodeList(node.implementedTypes);
|
| - writeNodeList(node.fields);
|
| - writeNodeList(node.constructors);
|
| - writeNodeList(node.procedures);
|
| - _typeParameterIndexer.exit(node.typeParameters);
|
| + if (node.canonicalName == null) {
|
| + throw 'Missing canonical name for $node';
|
| }
|
| + writeByte(Tag.Class);
|
| + writeCanonicalNameReference(getCanonicalNameOfClass(node));
|
| + writeOffset(node, node.fileOffset);
|
| + writeByte(flags);
|
| + writeStringReference(node.name ?? '');
|
| + writeUriReference(node.fileUri ?? '');
|
| + writeAnnotationList(node.annotations);
|
| + _typeParameterIndexer.enter(node.typeParameters);
|
| + writeNodeList(node.typeParameters);
|
| + writeOptionalNode(node.supertype);
|
| + writeOptionalNode(node.mixedInType);
|
| + writeNodeList(node.implementedTypes);
|
| + writeNodeList(node.fields);
|
| + writeNodeList(node.constructors);
|
| + writeNodeList(node.procedures);
|
| + _typeParameterIndexer.exit(node.typeParameters);
|
| }
|
|
|
| static final Name _emptyName = new Name('');
|
|
|
| visitConstructor(Constructor node) {
|
| + if (node.canonicalName == null) {
|
| + throw 'Missing canonical name for $node';
|
| + }
|
| _variableIndexer = new VariableIndexer();
|
| writeByte(Tag.Constructor);
|
| + writeCanonicalNameReference(getCanonicalNameOfMember(node));
|
| writeOffset(node, node.fileOffset);
|
| writeOffset(node, node.fileEndOffset);
|
| writeByte(node.flags);
|
| @@ -370,8 +340,12 @@ class BinaryPrinter extends Visitor {
|
| }
|
|
|
| visitProcedure(Procedure node) {
|
| + if (node.canonicalName == null) {
|
| + throw 'Missing canonical name for $node';
|
| + }
|
| _variableIndexer = new VariableIndexer();
|
| writeByte(Tag.Procedure);
|
| + writeCanonicalNameReference(getCanonicalNameOfMember(node));
|
| writeOffset(node, node.fileOffset);
|
| writeOffset(node, node.fileEndOffset);
|
| writeByte(node.kind.index);
|
| @@ -384,12 +358,16 @@ class BinaryPrinter extends Visitor {
|
| }
|
|
|
| visitField(Field node) {
|
| + if (node.canonicalName == null) {
|
| + throw 'Missing canonical name for $node';
|
| + }
|
| _variableIndexer = new VariableIndexer();
|
| writeByte(Tag.Field);
|
| + writeCanonicalNameReference(getCanonicalNameOfMember(node));
|
| writeOffset(node, node.fileOffset);
|
| writeOffset(node, node.fileEndOffset);
|
| writeByte(node.flags);
|
| - writeName(node.name ?? '');
|
| + writeName(node.name);
|
| writeUriReference(node.fileUri ?? '');
|
| writeAnnotationList(node.annotations);
|
| writeNode(node.type);
|
| @@ -404,19 +382,19 @@ class BinaryPrinter extends Visitor {
|
|
|
| visitFieldInitializer(FieldInitializer node) {
|
| writeByte(Tag.FieldInitializer);
|
| - writeMemberReference(node.field);
|
| + writeReference(node.fieldReference);
|
| writeNode(node.value);
|
| }
|
|
|
| visitSuperInitializer(SuperInitializer node) {
|
| writeByte(Tag.SuperInitializer);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.arguments);
|
| }
|
|
|
| visitRedirectingInitializer(RedirectingInitializer node) {
|
| writeByte(Tag.RedirectingInitializer);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.arguments);
|
| }
|
|
|
| @@ -491,7 +469,7 @@ class BinaryPrinter extends Visitor {
|
| writeOffset(node, node.fileOffset);
|
| writeNode(node.receiver);
|
| writeName(node.name);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitPropertySet(PropertySet node) {
|
| @@ -500,44 +478,44 @@ class BinaryPrinter extends Visitor {
|
| writeNode(node.receiver);
|
| writeName(node.name);
|
| writeNode(node.value);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitSuperPropertyGet(SuperPropertyGet node) {
|
| writeByte(Tag.SuperPropertyGet);
|
| writeName(node.name);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitSuperPropertySet(SuperPropertySet node) {
|
| writeByte(Tag.SuperPropertySet);
|
| writeName(node.name);
|
| writeNode(node.value);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitDirectPropertyGet(DirectPropertyGet node) {
|
| writeByte(Tag.DirectPropertyGet);
|
| writeNode(node.receiver);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| }
|
|
|
| visitDirectPropertySet(DirectPropertySet node) {
|
| writeByte(Tag.DirectPropertySet);
|
| writeNode(node.receiver);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.value);
|
| }
|
|
|
| visitStaticGet(StaticGet node) {
|
| writeByte(Tag.StaticGet);
|
| writeOffset(node, node.fileOffset);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| }
|
|
|
| visitStaticSet(StaticSet node) {
|
| writeByte(Tag.StaticSet);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.value);
|
| }
|
|
|
| @@ -547,7 +525,7 @@ class BinaryPrinter extends Visitor {
|
| writeNode(node.receiver);
|
| writeName(node.name);
|
| writeNode(node.arguments);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitSuperMethodInvocation(SuperMethodInvocation node) {
|
| @@ -555,20 +533,20 @@ class BinaryPrinter extends Visitor {
|
| writeOffset(node, node.fileOffset);
|
| writeName(node.name);
|
| writeNode(node.arguments);
|
| - writeMemberReference(node.interfaceTarget, allowNull: true);
|
| + writeReference(node.interfaceTargetReference);
|
| }
|
|
|
| visitDirectMethodInvocation(DirectMethodInvocation node) {
|
| writeByte(Tag.DirectMethodInvocation);
|
| writeNode(node.receiver);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.arguments);
|
| }
|
|
|
| visitStaticInvocation(StaticInvocation node) {
|
| writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation);
|
| writeOffset(node, node.fileOffset);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.arguments);
|
| }
|
|
|
| @@ -577,7 +555,7 @@ class BinaryPrinter extends Visitor {
|
| ? Tag.ConstConstructorInvocation
|
| : Tag.ConstructorInvocation);
|
| writeOffset(node, node.fileOffset);
|
| - writeMemberReference(node.target);
|
| + writeReference(node.targetReference);
|
| writeNode(node.arguments);
|
| }
|
|
|
| @@ -947,10 +925,10 @@ class BinaryPrinter extends Visitor {
|
| visitInterfaceType(InterfaceType node) {
|
| if (node.typeArguments.isEmpty) {
|
| writeByte(Tag.SimpleInterfaceType);
|
| - writeClassReference(node.classNode);
|
| + writeReference(node.className);
|
| } else {
|
| writeByte(Tag.InterfaceType);
|
| - writeClassReference(node.classNode);
|
| + writeReference(node.className);
|
| writeNodeList(node.typeArguments);
|
| }
|
| }
|
| @@ -958,10 +936,10 @@ class BinaryPrinter extends Visitor {
|
| visitSupertype(Supertype node) {
|
| if (node.typeArguments.isEmpty) {
|
| writeByte(Tag.SimpleInterfaceType);
|
| - writeClassReference(node.classNode);
|
| + writeReference(node.className);
|
| } else {
|
| writeByte(Tag.InterfaceType);
|
| - writeClassReference(node.classNode);
|
| + writeReference(node.className);
|
| writeNodeList(node.typeArguments);
|
| }
|
| }
|
| @@ -1100,7 +1078,7 @@ class StringIndexer extends RecursiveVisitor<Null> {
|
|
|
| int get numberOfStrings => index.length;
|
|
|
| - void build(Node node) {
|
| + void scanProgram(Node node) {
|
| node.accept(this);
|
| entries.sort();
|
| for (int i = 0; i < entries.length; ++i) {
|
| @@ -1108,6 +1086,11 @@ class StringIndexer extends RecursiveVisitor<Null> {
|
| }
|
| }
|
|
|
| + void visitCanonicalName(CanonicalName name) {
|
| + put(name.name);
|
| + name.children.forEach(visitCanonicalName);
|
| + }
|
| +
|
| void put(String string) {
|
| int i = index.putIfAbsent(string, () {
|
| entries.add(new StringTableEntry(string));
|
| @@ -1133,6 +1116,7 @@ class StringIndexer extends RecursiveVisitor<Null> {
|
| }
|
|
|
| visitLibrary(Library node) {
|
| + visitCanonicalName(node.canonicalName);
|
| putOptional(node.name);
|
| put('${node.importUri}');
|
| node.visitChildren(this);
|
|
|