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 6d3dabda980afd5aa453172db000a029a3974d87..721f0a6c60f88c78fb9b57ab8cd42df41f0ad0c3 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(); |
@@ -35,9 +32,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(); |
@@ -132,12 +127,36 @@ 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) { |
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(); |
@@ -163,44 +182,16 @@ 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 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 writeCanonicalNameReference(CanonicalName name) { |
+ if (name == null) { |
+ writeByte(0); |
} else { |
- node.acceptReference(this); |
+ 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`.'; |
- } |
- } else { |
- node.acceptReference(this); |
- } |
+ void writeLibraryReference(Library node) { |
+ writeCanonicalNameReference(node.canonicalName); |
} |
writeOffset(TreeNode node, int offset) { |
@@ -210,45 +201,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) { |
@@ -265,8 +229,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 ?? ''); |
writeNodeList(node.classes); |
@@ -288,43 +252,36 @@ class BinaryPrinter extends Visitor { |
if (node.level == ClassLevel.Type) { |
flags |= 0x2; |
} |
- 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); |
@@ -340,8 +297,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); |
@@ -354,8 +315,12 @@ 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); |
@@ -374,19 +339,19 @@ class BinaryPrinter extends Visitor { |
visitFieldInitializer(FieldInitializer node) { |
writeByte(Tag.FieldInitializer); |
- writeMemberReference(node.field); |
+ writeCanonicalNameReference(node.fieldName); |
writeNode(node.value); |
} |
visitSuperInitializer(SuperInitializer node) { |
writeByte(Tag.SuperInitializer); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.arguments); |
} |
visitRedirectingInitializer(RedirectingInitializer node) { |
writeByte(Tag.RedirectingInitializer); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.arguments); |
} |
@@ -461,7 +426,7 @@ class BinaryPrinter extends Visitor { |
writeOffset(node, node.fileOffset); |
writeNode(node.receiver); |
writeName(node.name); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitPropertySet(PropertySet node) { |
@@ -470,44 +435,44 @@ class BinaryPrinter extends Visitor { |
writeNode(node.receiver); |
writeName(node.name); |
writeNode(node.value); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitSuperPropertyGet(SuperPropertyGet node) { |
writeByte(Tag.SuperPropertyGet); |
writeName(node.name); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitSuperPropertySet(SuperPropertySet node) { |
writeByte(Tag.SuperPropertySet); |
writeName(node.name); |
writeNode(node.value); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitDirectPropertyGet(DirectPropertyGet node) { |
writeByte(Tag.DirectPropertyGet); |
writeNode(node.receiver); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
} |
visitDirectPropertySet(DirectPropertySet node) { |
writeByte(Tag.DirectPropertySet); |
writeNode(node.receiver); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.value); |
} |
visitStaticGet(StaticGet node) { |
writeByte(Tag.StaticGet); |
writeOffset(node, node.fileOffset); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
} |
visitStaticSet(StaticSet node) { |
writeByte(Tag.StaticSet); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.value); |
} |
@@ -517,7 +482,7 @@ class BinaryPrinter extends Visitor { |
writeNode(node.receiver); |
writeName(node.name); |
writeNode(node.arguments); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitSuperMethodInvocation(SuperMethodInvocation node) { |
@@ -525,20 +490,20 @@ class BinaryPrinter extends Visitor { |
writeOffset(node, node.fileOffset); |
writeName(node.name); |
writeNode(node.arguments); |
- writeMemberReference(node.interfaceTarget, allowNull: true); |
+ writeCanonicalNameReference(node.interfaceTargetName); |
} |
visitDirectMethodInvocation(DirectMethodInvocation node) { |
writeByte(Tag.DirectMethodInvocation); |
writeNode(node.receiver); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.arguments); |
} |
visitStaticInvocation(StaticInvocation node) { |
writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation); |
writeOffset(node, node.fileOffset); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.arguments); |
} |
@@ -547,7 +512,7 @@ class BinaryPrinter extends Visitor { |
? Tag.ConstConstructorInvocation |
: Tag.ConstructorInvocation); |
writeOffset(node, node.fileOffset); |
- writeMemberReference(node.target); |
+ writeCanonicalNameReference(node.targetName); |
writeNode(node.arguments); |
} |
@@ -907,10 +872,10 @@ class BinaryPrinter extends Visitor { |
visitInterfaceType(InterfaceType node) { |
if (node.typeArguments.isEmpty) { |
writeByte(Tag.SimpleInterfaceType); |
- writeClassReference(node.classNode); |
+ writeCanonicalNameReference(node.className); |
} else { |
writeByte(Tag.InterfaceType); |
- writeClassReference(node.classNode); |
+ writeCanonicalNameReference(node.className); |
writeNodeList(node.typeArguments); |
} |
} |
@@ -918,10 +883,10 @@ class BinaryPrinter extends Visitor { |
visitSupertype(Supertype node) { |
if (node.typeArguments.isEmpty) { |
writeByte(Tag.SimpleInterfaceType); |
- writeClassReference(node.classNode); |
+ writeCanonicalNameReference(node.className); |
} else { |
writeByte(Tag.InterfaceType); |
- writeClassReference(node.classNode); |
+ writeCanonicalNameReference(node.className); |
writeNodeList(node.typeArguments); |
} |
} |
@@ -1060,7 +1025,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) { |
@@ -1068,6 +1033,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)); |
@@ -1093,6 +1063,7 @@ class StringIndexer extends RecursiveVisitor<Null> { |
} |
visitLibrary(Library node) { |
+ visitCanonicalName(node.canonicalName); |
putOptional(node.name); |
put('${node.importUri}'); |
node.visitChildren(this); |