Remove definitions from Kernel canonical names.

Before: Canonical names contained pointers to the corresponding Kernel
tree which assumed that the whole tree was in memory whenever the
canonical names were.

Now: Canonical names do not contain these pointers.  They were only
really used to perform name-based lookup in the VM's heap so the
canonical name itself is enough.

If we later find that we need to get from a canonical name to its
Kernel tree we can add an offset in the binary (for instance) to the
canonical name or in a separate mapping on the side.

BUG=
R=asgerf@google.com, jensj@google.com, vegorov@google.com

Committed: https://github.com/dart-lang/sdk/commit/ed77783cd32d55fdad61bf9bc749030847ba9384
Review-Url: https://codereview.chromium.org/2781893004 .
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 311d8c5..a27c198 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -997,6 +997,7 @@
   bool get isAccessor => isGetter || isSetter;
   bool get hasGetter => kind != ProcedureKind.Setter;
   bool get hasSetter => kind == ProcedureKind.Setter;
+  bool get isFactory => kind == ProcedureKind.Factory;
 
   accept(MemberVisitor v) => v.visitProcedure(this);
 
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 7bf05dc..f4d2def 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -30,7 +30,7 @@
 ///         "@fields"
 ///         Qualified name
 ///
-///      Procedure that is not an accessor:
+///      Procedure that is not an accessor or factory:
 ///         Canonical name of enclosing class or library
 ///         "@methods"
 ///         Qualified name
@@ -45,6 +45,11 @@
 ///         "@setters"
 ///         Qualified name
 ///
+///      Procedure that is a factory:
+///         Canonical name of enclosing class
+///         "@factories"
+///         Qualified name
+///
 ///      Qualified name:
 ///         if private: URI of library
 ///         Name text
@@ -136,6 +141,7 @@
     if (member is Procedure) {
       if (member.isGetter) return '@getters';
       if (member.isSetter) return '@setters';
+      if (member.isFactory) return '@factories';
       return '@methods';
     }
     if (member is Field) {
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index adb0d2d..85c9ab8 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -304,6 +304,6 @@
 dart/data_uri_import_test/percentencoded: CompileTimeError
 dart/data_uri_import_test/wrongmime: CompileTimeError
 dart/data_uri_spawn_test: RuntimeError
-dart/redirection_type_shuffling_test/00: RuntimeError
-dart/redirection_type_shuffling_test/none: RuntimeError
+dart/redirection_type_shuffling_test/00: Crash # Issue 29201
+dart/redirection_type_shuffling_test/none: Crash # Issue 29201
 dart/spawn_shutdown_test: Timeout
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 9ba7963..6953cea 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -33,24 +33,6 @@
 }
 
 
-void CanonicalName::BindTo(LinkedNode* new_target) {
-  ASSERT(new_target != NULL);
-  if (definition_ == new_target) return;
-  ASSERT(definition_ == NULL);
-  ASSERT(new_target->canonical_name_ == NULL);
-  definition_ = new_target;
-  new_target->canonical_name_ = this;
-}
-
-
-void CanonicalName::Unbind() {
-  if (definition_ == NULL) return;
-  ASSERT(definition_->canonical_name_ == this);
-  definition_->canonical_name_ = NULL;
-  definition_ = NULL;
-}
-
-
 CanonicalName* CanonicalName::AddChild(String* name) {
   CanonicalName* child = new CanonicalName();
   child->parent_ = this;
@@ -60,33 +42,153 @@
 }
 
 
-Library* CanonicalName::AsLibrary() {
-  return Library::Cast(definition());
+bool CanonicalName::IsAdministrative() {
+  // Administrative names start with '@'.
+  return (name()->size() > 0) && (name()->buffer()[0] == '@');
 }
 
 
-Class* CanonicalName::AsClass() {
-  return Class::Cast(definition());
+bool CanonicalName::IsPrivate() {
+  // Private names start with '_'.
+  return (name()->size() > 0) && (name()->buffer()[0] == '_');
 }
 
 
-Member* CanonicalName::AsMember() {
-  return Member::Cast(definition());
+bool CanonicalName::IsRoot() {
+  // The root is the only canonical name with no parent.
+  return parent() == NULL;
 }
 
 
-Field* CanonicalName::AsField() {
-  return Field::Cast(definition());
+bool CanonicalName::IsLibrary() {
+  // Libraries are the only canonical names with the root as their parent.
+  return !IsRoot() && parent()->IsRoot();
 }
 
 
-Constructor* CanonicalName::AsConstructor() {
-  return Constructor::Cast(definition());
+bool CanonicalName::IsClass() {
+  // Classes have the library as their parent and are not an administrative
+  // name starting with @.
+  return !IsAdministrative() && !IsRoot() && parent()->IsLibrary();
 }
 
 
-Procedure* CanonicalName::AsProcedure() {
-  return Procedure::Cast(definition());
+bool CanonicalName::IsMember() {
+  return IsConstructor() || IsField() || IsProcedure();
+}
+
+
+// Note the two occurrences of the parameter 'literal'.
+#define COMPARE_NAME(canonical_name, literal)                                  \
+  memcmp((canonical_name)->name()->buffer(), (literal), strlen(literal)) == 0
+
+bool CanonicalName::IsField() {
+  // Fields with private names have the import URI of the library where they are
+  // visible as the parent and the string "@fields" as the parent's parent.
+  // Fields with non-private names have the string "@fields' as the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@fields");
+}
+
+
+bool CanonicalName::IsConstructor() {
+  // Constructors with private names have the import URI of the library where
+  // they are visible as the parent and the string "@constructors" as the
+  // parent's parent.  Constructors with non-private names have the string
+  // "@constructors" as the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@constructors");
+}
+
+
+bool CanonicalName::IsProcedure() {
+  return IsMethod() || IsGetter() || IsSetter() || IsFactory();
+}
+
+
+bool CanonicalName::IsMethod() {
+  // Methods with private names have the import URI of the library where they
+  // are visible as the parent and the string "@methods" as the parent's parent.
+  // Methods with non-private names have the string "@methods" as the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@methods");
+}
+
+
+bool CanonicalName::IsGetter() {
+  // Getters with private names have the import URI of the library where they
+  // are visible as the parent and the string "@getters" as the parent's parent.
+  // Getters with non-private names have the string "@getters" as the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@getters");
+}
+
+
+bool CanonicalName::IsSetter() {
+  // Setters with private names have the import URI of the library where they
+  // are visible as the parent and the string "@setters" as the parent's parent.
+  // Setters with non-private names have the string "@setters" as the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@setters");
+}
+
+
+bool CanonicalName::IsFactory() {
+  // Factories with private names have the import URI of the library where they
+  // are visible as the parent and the string "@factories" as the parent's
+  // parent.  Factories with non-private names have the string "@factories" as
+  // the parent.
+  if (IsRoot()) {
+    return false;
+  }
+  CanonicalName* kind = this->parent();
+  if (IsPrivate()) {
+    kind = kind->parent();
+  }
+  return COMPARE_NAME(kind, "@factories");
+}
+
+#undef COMPARE_NAME
+
+
+CanonicalName* CanonicalName::EnclosingName() {
+  ASSERT(IsField() || IsConstructor() || IsProcedure());
+  CanonicalName* enclosing = parent()->parent();
+  if (IsPrivate()) {
+    enclosing = enclosing->parent();
+  }
+  ASSERT(enclosing->IsLibrary() || enclosing->IsClass());
+  return enclosing;
 }
 
 
@@ -135,11 +237,6 @@
 }
 
 
-void NormalClass::AcceptReferenceVisitor(ClassReferenceVisitor* visitor) {
-  visitor->VisitNormalClassReference(this);
-}
-
-
 void NormalClass::VisitChildren(Visitor* visitor) {
   VisitList(&type_parameters(), visitor);
   if (super_class() != NULL) visitor->VisitInterfaceType(super_class());
@@ -158,11 +255,6 @@
 }
 
 
-void MixinClass::AcceptReferenceVisitor(ClassReferenceVisitor* visitor) {
-  visitor->VisitMixinClassReference(this);
-}
-
-
 void MixinClass::VisitChildren(Visitor* visitor) {
   VisitList(&type_parameters(), visitor);
   visitor->VisitInterfaceType(first());
@@ -188,11 +280,6 @@
 }
 
 
-void Field::AcceptReferenceVisitor(MemberReferenceVisitor* visitor) {
-  visitor->VisitFieldReference(this);
-}
-
-
 void Field::VisitChildren(Visitor* visitor) {
   type()->AcceptDartTypeVisitor(visitor);
   visitor->VisitName(name());
@@ -208,11 +295,6 @@
 }
 
 
-void Constructor::AcceptReferenceVisitor(MemberReferenceVisitor* visitor) {
-  visitor->VisitConstructorReference(this);
-}
-
-
 void Constructor::VisitChildren(Visitor* visitor) {
   visitor->VisitName(name());
   visitor->VisitFunctionNode(function());
@@ -228,11 +310,6 @@
 }
 
 
-void Procedure::AcceptReferenceVisitor(MemberReferenceVisitor* visitor) {
-  visitor->VisitProcedureReference(this);
-}
-
-
 void Procedure::VisitChildren(Visitor* visitor) {
   visitor->VisitName(name());
   if (function() != NULL) visitor->VisitFunctionNode(function());
@@ -267,7 +344,6 @@
 
 
 void FieldInitializer::VisitChildren(Visitor* visitor) {
-  visitor->VisitFieldReference(field());
   value()->AcceptExpressionVisitor(visitor);
 }
 
@@ -281,7 +357,6 @@
 
 
 void SuperInitializer::VisitChildren(Visitor* visitor) {
-  visitor->VisitConstructorReference(target());
   visitor->VisitArguments(arguments());
 }
 
@@ -296,7 +371,6 @@
 
 
 void RedirectingInitializer::VisitChildren(Visitor* visitor) {
-  visitor->VisitConstructorReference(target());
   visitor->VisitArguments(arguments());
 }
 
@@ -413,7 +487,6 @@
 
 void DirectPropertyGet::VisitChildren(Visitor* visitor) {
   receiver()->AcceptExpressionVisitor(visitor);
-  target()->AcceptReferenceVisitor(visitor);
 }
 
 
@@ -427,7 +500,6 @@
 
 void DirectPropertySet::VisitChildren(Visitor* visitor) {
   receiver()->AcceptExpressionVisitor(visitor);
-  target()->AcceptReferenceVisitor(visitor);
   value()->AcceptExpressionVisitor(visitor);
 }
 
@@ -440,9 +512,7 @@
 }
 
 
-void StaticGet::VisitChildren(Visitor* visitor) {
-  target()->AcceptReferenceVisitor(visitor);
-}
+void StaticGet::VisitChildren(Visitor* visitor) {}
 
 
 StaticSet::~StaticSet() {}
@@ -454,7 +524,6 @@
 
 
 void StaticSet::VisitChildren(Visitor* visitor) {
-  target()->AcceptReferenceVisitor(visitor);
   expression()->AcceptExpressionVisitor(visitor);
 }
 
@@ -513,7 +582,6 @@
 
 void DirectMethodInvocation::VisitChildren(Visitor* visitor) {
   receiver()->AcceptExpressionVisitor(visitor);
-  visitor->VisitProcedureReference(target());
   visitor->VisitArguments(arguments());
 }
 
@@ -527,7 +595,6 @@
 
 
 void StaticInvocation::VisitChildren(Visitor* visitor) {
-  visitor->VisitProcedureReference(procedure());
   visitor->VisitArguments(arguments());
 }
 
@@ -542,7 +609,6 @@
 
 
 void ConstructorInvocation::VisitChildren(Visitor* visitor) {
-  visitor->VisitConstructorReference(target());
   visitor->VisitArguments(arguments());
 }
 
@@ -1194,7 +1260,6 @@
 
 
 void InterfaceType::VisitChildren(Visitor* visitor) {
-  klass()->AcceptReferenceVisitor(visitor);
   VisitList(&type_arguments(), visitor);
 }
 
@@ -1258,7 +1323,6 @@
 
 void Program::VisitChildren(Visitor* visitor) {
   VisitList(&libraries(), visitor);
-  visitor->VisitProcedureReference(main_method());
 }
 
 
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 65a681b..54f1b9a 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -118,8 +118,6 @@
   M(ClassVisitor)                                                              \
   M(InitializerVisitor)                                                        \
   M(DartTypeVisitor)                                                           \
-  M(ClassReferenceVisitor)                                                     \
-  M(MemberReferenceVisitor)                                                    \
   M(TreeVisitor)                                                               \
   M(Visitor)
 
@@ -370,20 +368,29 @@
 
   String* name() { return name_; }
   CanonicalName* parent() { return parent_; }
-  LinkedNode* definition() { return definition_; }
   bool is_referenced() { return is_referenced_; }
   void set_referenced(bool referenced) { is_referenced_ = referenced; }
 
-  void BindTo(LinkedNode* definition);
-  void Unbind();
   CanonicalName* AddChild(String* name);
 
-  Library* AsLibrary();
-  Class* AsClass();
-  Member* AsMember();
-  Field* AsField();
-  Constructor* AsConstructor();
-  Procedure* AsProcedure();
+  bool IsAdministrative();
+  bool IsPrivate();
+
+  bool IsRoot();
+  bool IsLibrary();
+  bool IsClass();
+  bool IsMember();
+  bool IsField();
+  bool IsConstructor();
+  bool IsProcedure();
+  bool IsMethod();
+  bool IsGetter();
+  bool IsSetter();
+  bool IsFactory();
+
+  // For a member (field, constructor, or procedure) return the canonical name
+  // of the enclosing class or library.
+  CanonicalName* EnclosingName();
 
   static CanonicalName* NewRoot();
 
@@ -393,7 +400,6 @@
   bool is_referenced_;
   Ref<CanonicalName> parent_;
   Ref<String> name_;
-  Ref<LinkedNode> definition_;
   MallocGrowableArray<CanonicalName*> children_;
 
   DISALLOW_COPY_AND_ASSIGN(CanonicalName);
@@ -457,9 +463,9 @@
  protected:
   LinkedNode() {}
 
- private:
   Ref<CanonicalName> canonical_name_;
 
+ private:
   friend class CanonicalName;
 
   DISALLOW_COPY_AND_ASSIGN(LinkedNode);
@@ -533,7 +539,6 @@
 
   virtual void AcceptTreeVisitor(TreeVisitor* visitor);
   virtual void AcceptClassVisitor(ClassVisitor* visitor) = 0;
-  virtual void AcceptReferenceVisitor(ClassReferenceVisitor* visitor) = 0;
 
   Library* parent() { return parent_; }
   String* name() { return name_; }
@@ -575,7 +580,6 @@
   DEFINE_CASTING_OPERATIONS(NormalClass);
 
   virtual void AcceptClassVisitor(ClassVisitor* visitor);
-  virtual void AcceptReferenceVisitor(ClassReferenceVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
   virtual TypeParameterList& type_parameters() { return type_parameters_; }
@@ -613,7 +617,6 @@
   DEFINE_CASTING_OPERATIONS(MixinClass);
 
   virtual void AcceptClassVisitor(ClassVisitor* visitor);
-  virtual void AcceptReferenceVisitor(ClassReferenceVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
   virtual TypeParameterList& type_parameters() { return type_parameters_; }
@@ -654,7 +657,6 @@
 
   virtual void AcceptTreeVisitor(TreeVisitor* visitor);
   virtual void AcceptMemberVisitor(MemberVisitor* visitor) = 0;
-  virtual void AcceptReferenceVisitor(MemberReferenceVisitor* visitor) = 0;
 
   TreeNode* parent() { return parent_; }
   Name* name() { return name_; }
@@ -696,7 +698,6 @@
   DEFINE_CASTING_OPERATIONS(Field);
 
   virtual void AcceptMemberVisitor(MemberVisitor* visitor);
-  virtual void AcceptReferenceVisitor(MemberReferenceVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
   bool IsConst() { return (flags_ & kFlagConst) == kFlagConst; }
@@ -736,7 +737,6 @@
   DEFINE_CASTING_OPERATIONS(Constructor);
 
   virtual void AcceptMemberVisitor(MemberVisitor* visitor);
-  virtual void AcceptReferenceVisitor(MemberReferenceVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
   bool IsExternal() { return (flags_ & kFlagExternal) == kFlagExternal; }
@@ -786,7 +786,6 @@
   DEFINE_CASTING_OPERATIONS(Procedure);
 
   virtual void AcceptMemberVisitor(MemberVisitor* visitor);
-  virtual void AcceptReferenceVisitor(MemberReferenceVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
   ProcedureKind kind() { return kind_; }
@@ -860,13 +859,13 @@
   virtual void AcceptInitializerVisitor(InitializerVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Field* field() { return field_reference_->AsField(); }
+  CanonicalName* field() { return field_reference_; }
   Expression* value() { return value_; }
 
  private:
   FieldInitializer() {}
 
-  Ref<CanonicalName> field_reference_;
+  Ref<CanonicalName> field_reference_;  // Field.
   Child<Expression> value_;
 
   DISALLOW_COPY_AND_ASSIGN(FieldInitializer);
@@ -884,13 +883,13 @@
   virtual void AcceptInitializerVisitor(InitializerVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Constructor* target() { return target_reference_->AsConstructor(); }
+  CanonicalName* target() { return target_reference_; }
   Arguments* arguments() { return arguments_; }
 
  private:
   SuperInitializer() {}
 
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Constructor.
   Child<Arguments> arguments_;
 
   DISALLOW_COPY_AND_ASSIGN(SuperInitializer);
@@ -908,13 +907,13 @@
   virtual void AcceptInitializerVisitor(InitializerVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Constructor* target() { return target_reference_->AsConstructor(); }
+  CanonicalName* target() { return target_reference_; }
   Arguments* arguments() { return arguments_; }
 
  private:
   RedirectingInitializer() {}
 
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Constructor.
   Child<Arguments> arguments_;
 
   DISALLOW_COPY_AND_ASSIGN(RedirectingInitializer);
@@ -1147,13 +1146,13 @@
   virtual void VisitChildren(Visitor* visitor);
 
   Expression* receiver() { return receiver_; }
-  Member* target() { return target_reference_->AsMember(); }
+  CanonicalName* target() { return target_reference_; }
 
  private:
   DirectPropertyGet() {}
 
   Child<Expression> receiver_;
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Member.
 
   DISALLOW_COPY_AND_ASSIGN(DirectPropertyGet);
 };
@@ -1171,14 +1170,14 @@
   virtual void VisitChildren(Visitor* visitor);
 
   Expression* receiver() { return receiver_; }
-  Member* target() { return target_reference_->AsMember(); }
+  CanonicalName* target() { return target_reference_; }
   Expression* value() { return value_; }
 
  private:
   DirectPropertySet() {}
 
   Child<Expression> receiver_;
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Member.
   Child<Expression> value_;
 
   DISALLOW_COPY_AND_ASSIGN(DirectPropertySet);
@@ -1196,12 +1195,12 @@
   virtual void AcceptExpressionVisitor(ExpressionVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Member* target() { return target_reference_->AsMember(); }
+  CanonicalName* target() { return target_reference_; }
 
  private:
   StaticGet() {}
 
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Member.
 
   DISALLOW_COPY_AND_ASSIGN(StaticGet);
 };
@@ -1218,13 +1217,13 @@
   virtual void AcceptExpressionVisitor(ExpressionVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Member* target() { return target_reference_->AsMember(); }
+  CanonicalName* target() { return target_reference_; }
   Expression* expression() { return expression_; }
 
  private:
   StaticSet() {}
 
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Member.
   Child<Expression> expression_;
 
   DISALLOW_COPY_AND_ASSIGN(StaticSet);
@@ -1324,14 +1323,14 @@
   virtual void VisitChildren(Visitor* visitor);
 
   Expression* receiver() { return receiver_; }
-  Procedure* target() { return target_reference_->AsProcedure(); }
+  CanonicalName* target() { return target_reference_; }
   Arguments* arguments() { return arguments_; }
 
  private:
   DirectMethodInvocation() {}
 
   Child<Expression> receiver_;
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Procedure.
   Child<Arguments> arguments_;
 
   DISALLOW_COPY_AND_ASSIGN(DirectMethodInvocation);
@@ -1346,14 +1345,14 @@
   virtual void AcceptExpressionVisitor(ExpressionVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Procedure* procedure() { return procedure_reference_->AsProcedure(); }
+  CanonicalName* procedure() { return procedure_reference_; }
   Arguments* arguments() { return arguments_; }
   bool is_const() { return is_const_; }
 
  private:
   StaticInvocation() {}
 
-  Ref<CanonicalName> procedure_reference_;
+  Ref<CanonicalName> procedure_reference_;  // Procedure.
   Child<Arguments> arguments_;
   bool is_const_;
 
@@ -1373,14 +1372,14 @@
   virtual void VisitChildren(Visitor* visitor);
 
   bool is_const() { return is_const_; }
-  Constructor* target() { return target_reference_->AsConstructor(); }
+  CanonicalName* target() { return target_reference_; }
   Arguments* arguments() { return arguments_; }
 
  private:
   ConstructorInvocation() {}
 
   bool is_const_;
-  Ref<CanonicalName> target_reference_;
+  Ref<CanonicalName> target_reference_;  // Constructor.
   Child<Arguments> arguments_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstructorInvocation);
@@ -2529,18 +2528,14 @@
   virtual void VisitChildren(Visitor* visitor);
 
   String* string() { return string_; }
-  Library* library() {
-    if (library_reference_ == NULL) return NULL;
-    return library_reference_->AsLibrary();
-  }
-  CanonicalName* library_reference() { return library_reference_; }
+  CanonicalName* library() { return library_reference_; }
 
  private:
   Name(String* string, CanonicalName* library_reference)
       : string_(string), library_reference_(library_reference) {}  // NOLINT
 
   Ref<String> string_;
-  Ref<CanonicalName> library_reference_;
+  Ref<CanonicalName> library_reference_;  // Library.
 
   DISALLOW_COPY_AND_ASSIGN(Name);
 };
@@ -2633,14 +2628,13 @@
   virtual void AcceptDartTypeVisitor(DartTypeVisitor* visitor);
   virtual void VisitChildren(Visitor* visitor);
 
-  Class* klass() { return class_reference_->AsClass(); }
-  CanonicalName* class_reference() { return class_reference_; }
+  CanonicalName* klass() { return class_reference_; }
   List<DartType>& type_arguments() { return type_arguments_; }
 
  private:
   InterfaceType() {}
 
-  Ref<CanonicalName> class_reference_;
+  Ref<CanonicalName> class_reference_;  // Class.
   List<DartType> type_arguments_;
 
   DISALLOW_COPY_AND_ASSIGN(InterfaceType);
@@ -2745,10 +2739,7 @@
   StringTable& source_uri_table() { return source_uri_table_; }
   SourceTable& source_table() { return source_table_; }
   List<Library>& libraries() { return libraries_; }
-  Procedure* main_method() {
-    if (main_method_reference_ == NULL) return NULL;
-    return main_method_reference_->AsProcedure();
-  }
+  CanonicalName* main_method() { return main_method_reference_; }
   CanonicalName* canonical_name_root() { return canonical_name_root_; }
   MallocGrowableArray<MallocGrowableArray<intptr_t>*> valid_token_positions;
   MallocGrowableArray<MallocGrowableArray<intptr_t>*> yield_token_positions;
@@ -2758,7 +2749,7 @@
 
   Child<CanonicalName> canonical_name_root_;
   List<Library> libraries_;
-  Ref<CanonicalName> main_method_reference_;
+  Ref<CanonicalName> main_method_reference_;  // Procedure.
   StringTable string_table_;
   StringTable source_uri_table_;
   SourceTable source_table_;
@@ -3013,37 +3004,6 @@
 };
 
 
-class ClassReferenceVisitor {
- public:
-  virtual ~ClassReferenceVisitor() {}
-
-  virtual void VisitDefaultClassReference(Class* node) = 0;
-  virtual void VisitNormalClassReference(NormalClass* node) {
-    VisitDefaultClassReference(node);
-  }
-  virtual void VisitMixinClassReference(MixinClass* node) {
-    VisitDefaultClassReference(node);
-  }
-};
-
-
-class MemberReferenceVisitor {
- public:
-  virtual ~MemberReferenceVisitor() {}
-
-  virtual void VisitDefaultMemberReference(Member* node) = 0;
-  virtual void VisitFieldReference(Field* node) {
-    VisitDefaultMemberReference(node);
-  }
-  virtual void VisitConstructorReference(Constructor* node) {
-    VisitDefaultMemberReference(node);
-  }
-  virtual void VisitProcedureReference(Procedure* node) {
-    VisitDefaultMemberReference(node);
-  }
-};
-
-
 class TreeVisitor : public ExpressionVisitor,
                     public StatementVisitor,
                     public MemberVisitor,
@@ -3083,10 +3043,7 @@
 };
 
 
-class Visitor : public TreeVisitor,
-                public DartTypeVisitor,
-                public ClassReferenceVisitor,
-                public MemberReferenceVisitor {
+class Visitor : public TreeVisitor, public DartTypeVisitor {
  public:
   virtual ~Visitor() {}
 
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index a1cad83..4498072 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -494,13 +494,6 @@
     return name;
   }
 
-  CanonicalName* ReadDefiningCanonicalNameReference(LinkedNode* node_to_link) {
-    CanonicalName* name = ReadCanonicalNameReference();
-    ASSERT(name != NULL);
-    name->BindTo(node_to_link);
-    return name;
-  }
-
   intptr_t offset() { return offset_; }
 
  private:
@@ -687,11 +680,9 @@
   int flags = reader->ReadFlags();
   ASSERT(flags == 0);  // external libraries not supported
 
-  CanonicalName* canonical_name =
-      reader->ReadDefiningCanonicalNameReference(this);
-
+  canonical_name_ = reader->ReadCanonicalNameReference();
   name_ = Reference::ReadStringFrom(reader);
-  import_uri_ = canonical_name->name();
+  import_uri_ = canonical_name_->name();
   source_uri_index_ = reader->ReadUInt();
   reader->set_current_script_id(source_uri_index_);
 
@@ -717,7 +708,7 @@
 Class* Class::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
 
-  reader->ReadDefiningCanonicalNameReference(this);
+  canonical_name_ = reader->ReadCanonicalNameReference();
   position_ = reader->ReadPosition(false);
   is_abstract_ = reader->ReadBool();
   name_ = Reference::ReadStringFrom(reader);
@@ -809,7 +800,7 @@
   Tag tag = reader->ReadTag();
   ASSERT(tag == kField);
 
-  reader->ReadDefiningCanonicalNameReference(this);
+  canonical_name_ = reader->ReadCanonicalNameReference();
   position_ = reader->ReadPosition(false);
   end_position_ = reader->ReadPosition(false);
   flags_ = reader->ReadFlags();
@@ -830,7 +821,7 @@
   Tag tag = reader->ReadTag();
   ASSERT(tag == kConstructor);
 
-  reader->ReadDefiningCanonicalNameReference(this);
+  canonical_name_ = reader->ReadCanonicalNameReference();
   VariableScope<ReaderHelper> parameters(reader->helper());
   position_ = reader->ReadPosition();
   end_position_ = reader->ReadPosition();
@@ -848,7 +839,7 @@
   Tag tag = reader->ReadTag();
   ASSERT(tag == kProcedure);
 
-  reader->ReadDefiningCanonicalNameReference(this);
+  canonical_name_ = reader->ReadCanonicalNameReference();
   VariableScope<ReaderHelper> parameters(reader->helper());
   position_ = reader->ReadPosition(false);
   end_position_ = reader->ReadPosition(false);
@@ -1890,15 +1881,6 @@
 
   program->main_method_reference_ = Reference::ReadMemberFrom(reader);
 
-#ifdef DEBUG
-  for (intptr_t i = 0; i < canonical_names; ++i) {
-    CanonicalName* name = reader->helper()->GetCanonicalName(i);
-    if (name->is_referenced() && name->definition() == NULL) {
-      FATAL("Missing definition for canonical name");
-    }
-  }
-#endif
-
   return program;
 }
 
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index d8b7507..231300e 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -134,10 +134,8 @@
     }
 
     if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) {
-      Procedure* main = program_->main_method();
-      Library* kernel_main_library = Library::Cast(main->parent());
-      dart::Library& library =
-          LookupLibrary(kernel_main_library->canonical_name());
+      CanonicalName* main = program_->main_method();
+      dart::Library& library = LookupLibrary(main->EnclosingName());
 
       // Sanity check that we can find the main entrypoint.
       Object& main_obj = Object::Handle(
@@ -360,7 +358,8 @@
     ActiveFunctionScope active_function_scope(&active_class_,
                                               kernel_constructor->function());
 
-    const dart::String& name = H.DartConstructorName(kernel_constructor);
+    const dart::String& name =
+        H.DartConstructorName(kernel_constructor->canonical_name());
     Function& function = dart::Function::ZoneHandle(
         Z, dart::Function::New(name, RawFunction::kConstructor,
                                false,  // is_static
@@ -414,7 +413,8 @@
   ActiveFunctionScope active_function_scope(&active_class_,
                                             kernel_procedure->function());
 
-  const dart::String& name = H.DartProcedureName(kernel_procedure);
+  const dart::String& name =
+      H.DartProcedureName(kernel_procedure->canonical_name());
   bool is_method = kernel_klass != NULL && !kernel_procedure->IsStatic();
   bool is_abstract = kernel_procedure->IsAbstract();
   bool is_external = kernel_procedure->IsExternal();
@@ -428,16 +428,18 @@
       if (!annotation->IsConstructorInvocation()) continue;
       ConstructorInvocation* invocation =
           ConstructorInvocation::Cast(annotation);
-      Class* annotation_class = Class::Cast(invocation->target()->parent());
+      CanonicalName* annotation_class = invocation->target()->EnclosingName();
+      ASSERT(annotation_class->IsClass());
       String* class_name = annotation_class->name();
       // Just compare by name, do not generate the annotation class.
       int length = sizeof("ExternalName") - 1;
       if (class_name->size() != length) continue;
       if (memcmp(class_name->buffer(), "ExternalName", length) != 0) continue;
+      ASSERT(annotation_class->parent()->IsLibrary());
       String* library_name = annotation_class->parent()->name();
-      length = sizeof("dart._internal") - 1;
+      length = sizeof("dart:_internal") - 1;
       if (library_name->size() != length) continue;
-      if (memcmp(library_name->buffer(), "dart._internal", length) != 0) {
+      if (memcmp(library_name->buffer(), "dart:_internal", length) != 0) {
         continue;
       }
 
@@ -493,8 +495,9 @@
 
   if (kernel_klass == NULL) {
     library.AddObject(function, name);
-    ASSERT(!Object::Handle(Z, library.LookupObjectAllowPrivate(
-                                  H.DartProcedureName(kernel_procedure)))
+    ASSERT(!Object::Handle(
+                Z, library.LookupObjectAllowPrivate(
+                       H.DartProcedureName(kernel_procedure->canonical_name())))
                 .IsNull());
   }
   if (FLAG_enable_mirrors) {
@@ -629,7 +632,8 @@
     }
   }
 
-  const dart::String& getter_name = H.DartGetterName(kernel_field->name());
+  const dart::String& getter_name =
+      H.DartGetterName(kernel_field->canonical_name());
   const Object& script_class =
       ClassForScriptAt(klass, kernel_field->source_uri_index());
   Function& getter = Function::ZoneHandle(
@@ -659,7 +663,8 @@
   if (!kernel_field->IsStatic() && !kernel_field->IsFinal()) {
     // Only static fields can be const.
     ASSERT(!kernel_field->IsConst());
-    const dart::String& setter_name = H.DartSetterName(kernel_field->name());
+    const dart::String& setter_name =
+        H.DartSetterName(kernel_field->canonical_name());
     Function& setter = Function::ZoneHandle(
         Z, Function::New(setter_name, RawFunction::kImplicitSetter,
                          false,  // is_static
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 1e0a406..b64ca28 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -277,13 +277,13 @@
       dart::Class::Handle(zone_, parsed_function_->function().Owner());
   Function& outermost_function = Function::Handle(Z);
   TreeNode* outermost_node = NULL;
-  Class* kernel_klass = NULL;
+  Class* kernel_class = NULL;
   DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node,
-                            &kernel_klass);
-  // Use [klass]/[kernel_klass] as active class.  Type parameters will get
-  // resolved via [kernel_klass] unless we are nested inside a static factory
+                            &kernel_class);
+  // Use [klass]/[kernel_class] as active class.  Type parameters will get
+  // resolved via [kernel_class] unless we are nested inside a static factory
   // in which case we will use [member].
-  ActiveClassScope active_class_scope(&active_class_, kernel_klass, &klass);
+  ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass);
   Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
                        ? Member::Cast(outermost_node)
                        : NULL;
@@ -1070,33 +1070,48 @@
 
 
 const dart::String& TranslationHelper::DartClassName(
-    CanonicalName* kernel_klass) {
-  dart::String& name = DartString(kernel_klass->name());
-  return ManglePrivateName(kernel_klass->parent(), &name);
+    CanonicalName* kernel_class) {
+  ASSERT(kernel_class->IsClass());
+  dart::String& name = DartString(kernel_class->name());
+  return ManglePrivateName(kernel_class->parent(), &name);
 }
 
 
-const dart::String& TranslationHelper::DartConstructorName(Constructor* node) {
-  Class* klass = Class::Cast(node->parent());
-  return DartFactoryName(klass, node->name());
+const dart::String& TranslationHelper::DartConstructorName(
+    CanonicalName* constructor) {
+  ASSERT(constructor->IsConstructor());
+  return DartFactoryName(constructor);
 }
 
 
-const dart::String& TranslationHelper::DartProcedureName(Procedure* procedure) {
-  if (procedure->kind() == Procedure::kSetter) {
-    return DartSetterName(procedure->name());
-  } else if (procedure->kind() == Procedure::kGetter) {
-    return DartGetterName(procedure->name());
-  } else if (procedure->kind() == Procedure::kFactory) {
-    return DartFactoryName(Class::Cast(procedure->parent()), procedure->name());
+const dart::String& TranslationHelper::DartProcedureName(
+    CanonicalName* procedure) {
+  ASSERT(procedure->IsProcedure());
+  if (procedure->IsSetter()) {
+    return DartSetterName(procedure);
+  } else if (procedure->IsGetter()) {
+    return DartGetterName(procedure);
+  } else if (procedure->IsFactory()) {
+    return DartFactoryName(procedure);
   } else {
-    return DartMethodName(procedure->name());
+    return DartMethodName(procedure);
   }
 }
 
 
-const dart::String& TranslationHelper::DartSetterName(Name* kernel_name) {
-  // The names flowing into [content] are coming from the Kernel file:
+const dart::String& TranslationHelper::DartSetterName(CanonicalName* setter) {
+  return DartSetterName(setter->parent(), setter->name());
+}
+
+
+const dart::String& TranslationHelper::DartSetterName(Name* setter_name) {
+  return DartSetterName(setter_name->library(), setter_name->string());
+}
+
+
+const dart::String& TranslationHelper::DartSetterName(CanonicalName* parent,
+                                                      String* setter) {
+  // The names flowing into [setter] are coming from the Kernel file:
   //   * user-defined setters: `fieldname=`
   //   * property-set expressions:  `fieldname`
   //
@@ -1104,24 +1119,34 @@
   //
   // => In order to be consistent, we remove the `=` always and adopt the VM
   //    conventions.
-  String* content = kernel_name->string();
-  ASSERT(content->size() > 0);
+  ASSERT(setter->size() > 0);
   intptr_t skip = 0;
-  if (content->buffer()[content->size() - 1] == '=') {
+  if (setter->buffer()[setter->size() - 1] == '=') {
     skip = 1;
   }
   dart::String& name = dart::String::ZoneHandle(
-      Z, dart::String::FromUTF8(content->buffer(), content->size() - skip,
+      Z, dart::String::FromUTF8(setter->buffer(), setter->size() - skip,
                                 allocation_space_));
-  ManglePrivateName(kernel_name->library_reference(), &name, false);
+  ManglePrivateName(parent, &name, false);
   name = dart::Field::SetterSymbol(name);
   return name;
 }
 
 
-const dart::String& TranslationHelper::DartGetterName(Name* kernel_name) {
-  dart::String& name = DartString(kernel_name->string());
-  ManglePrivateName(kernel_name->library_reference(), &name, false);
+const dart::String& TranslationHelper::DartGetterName(CanonicalName* getter) {
+  return DartGetterName(getter->parent(), getter->name());
+}
+
+
+const dart::String& TranslationHelper::DartGetterName(Name* getter_name) {
+  return DartGetterName(getter_name->library(), getter_name->string());
+}
+
+
+const dart::String& TranslationHelper::DartGetterName(CanonicalName* parent,
+                                                      String* getter) {
+  dart::String& name = DartString(getter);
+  ManglePrivateName(parent, &name, false);
   name = dart::Field::GetterSymbol(name);
   return name;
 }
@@ -1129,7 +1154,7 @@
 
 const dart::String& TranslationHelper::DartFieldName(Name* kernel_name) {
   dart::String& name = DartString(kernel_name->string());
-  return ManglePrivateName(kernel_name->library_reference(), &name);
+  return ManglePrivateName(kernel_name->library(), &name);
 }
 
 
@@ -1142,19 +1167,30 @@
 }
 
 
-const dart::String& TranslationHelper::DartMethodName(Name* kernel_name) {
-  dart::String& name = DartString(kernel_name->string());
-  return ManglePrivateName(kernel_name->library_reference(), &name);
+const dart::String& TranslationHelper::DartMethodName(CanonicalName* method) {
+  return DartMethodName(method->parent(), method->name());
 }
 
 
-const dart::String& TranslationHelper::DartFactoryName(Class* klass,
-                                                       Name* method_name) {
-  // [DartMethodName] will mangle the name.
+const dart::String& TranslationHelper::DartMethodName(Name* method_name) {
+  return DartMethodName(method_name->library(), method_name->string());
+}
+
+
+const dart::String& TranslationHelper::DartMethodName(CanonicalName* parent,
+                                                      String* method) {
+  dart::String& name = DartString(method);
+  return ManglePrivateName(parent, &name);
+}
+
+
+const dart::String& TranslationHelper::DartFactoryName(CanonicalName* factory) {
+  ASSERT(factory->IsConstructor() || factory->IsFactory());
   GrowableHandlePtrArray<const dart::String> pieces(Z, 3);
-  pieces.Add(DartClassName(klass->canonical_name()));
+  pieces.Add(DartClassName(factory->EnclosingName()));
   pieces.Add(Symbols::Dot());
-  pieces.Add(DartMethodName(method_name));
+  // [DartMethodName] will mangle the name.
+  pieces.Add(DartMethodName(factory));
   return dart::String::ZoneHandle(
       Z, dart::Symbols::FromConcatAll(thread_, pieces));
 }
@@ -1162,6 +1198,10 @@
 
 dart::RawLibrary* TranslationHelper::LookupLibraryByKernelLibrary(
     CanonicalName* kernel_library) {
+  // We only use the name and don't rely on having any particular parent.  This
+  // ASSERT is just a sanity check.
+  ASSERT(kernel_library->IsLibrary() ||
+         kernel_library->parent()->IsAdministrative());
   const dart::String& library_name = DartSymbol(kernel_library->name());
   ASSERT(!library_name.IsNull());
   dart::RawLibrary* library =
@@ -1172,11 +1212,11 @@
 
 
 dart::RawClass* TranslationHelper::LookupClassByKernelClass(
-    CanonicalName* kernel_klass) {
+    CanonicalName* kernel_class) {
+  ASSERT(kernel_class->IsClass());
   dart::RawClass* klass = NULL;
-
-  const dart::String& class_name = DartClassName(kernel_klass);
-  CanonicalName* kernel_library = kernel_klass->parent();
+  const dart::String& class_name = DartClassName(kernel_class);
+  CanonicalName* kernel_library = kernel_class->parent();
   dart::Library& library =
       dart::Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library));
   klass = library.LookupClassAllowPrivate(class_name);
@@ -1187,36 +1227,44 @@
 
 
 dart::RawField* TranslationHelper::LookupFieldByKernelField(
-    Field* kernel_field) {
-  TreeNode* node = kernel_field->parent();
+    CanonicalName* kernel_field) {
+  ASSERT(kernel_field->IsField());
+  CanonicalName* enclosing = kernel_field->EnclosingName();
 
   dart::Class& klass = dart::Class::Handle(Z);
-  if (node->IsClass()) {
-    klass = LookupClassByKernelClass(Class::Cast(node)->canonical_name());
-  } else {
-    ASSERT(node->IsLibrary());
-    dart::Library& library = dart::Library::Handle(
-        Z, LookupLibraryByKernelLibrary(Library::Cast(node)->canonical_name()));
+  if (enclosing->IsLibrary()) {
+    dart::Library& library =
+        dart::Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing));
     klass = library.toplevel_class();
+  } else {
+    ASSERT(enclosing->IsClass());
+    klass = LookupClassByKernelClass(enclosing);
   }
   dart::RawField* field =
-      klass.LookupFieldAllowPrivate(DartSymbol(kernel_field->name()->string()));
+      klass.LookupFieldAllowPrivate(DartSymbol(kernel_field->name()));
   ASSERT(field != Object::null());
   return field;
 }
 
 
 dart::RawFunction* TranslationHelper::LookupStaticMethodByKernelProcedure(
-    Procedure* procedure) {
-  ASSERT(procedure->IsStatic());
+    CanonicalName* procedure) {
   const dart::String& procedure_name = DartProcedureName(procedure);
 
   // The parent is either a library or a class (in which case the procedure is a
   // static method).
-  TreeNode* parent = procedure->parent();
-  if (parent->IsClass()) {
-    dart::Class& klass = dart::Class::Handle(
-        Z, LookupClassByKernelClass(Class::Cast(parent)->canonical_name()));
+  CanonicalName* enclosing = procedure->EnclosingName();
+  if (enclosing->IsLibrary()) {
+    dart::Library& library =
+        dart::Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing));
+    dart::RawFunction* function =
+        library.LookupFunctionAllowPrivate(procedure_name);
+    ASSERT(function != Object::null());
+    return function;
+  } else {
+    ASSERT(enclosing->IsClass());
+    dart::Class& klass =
+        dart::Class::Handle(Z, LookupClassByKernelClass(enclosing));
     dart::RawFunction* raw_function =
         klass.LookupFunctionAllowPrivate(procedure_name);
     ASSERT(raw_function != Object::null());
@@ -1229,31 +1277,23 @@
       function = function.RedirectionTarget();
     }
     return function.raw();
-  } else {
-    ASSERT(parent->IsLibrary());
-    dart::Library& library = dart::Library::Handle(
-        Z,
-        LookupLibraryByKernelLibrary(Library::Cast(parent)->canonical_name()));
-    dart::RawFunction* function =
-        library.LookupFunctionAllowPrivate(procedure_name);
-    ASSERT(function != Object::null());
-    return function;
   }
 }
 
 
 dart::RawFunction* TranslationHelper::LookupConstructorByKernelConstructor(
-    Constructor* constructor) {
-  Class* kernel_klass = Class::Cast(constructor->parent());
+    CanonicalName* constructor) {
+  ASSERT(constructor->IsConstructor());
   dart::Class& klass = dart::Class::Handle(
-      Z, LookupClassByKernelClass(kernel_klass->canonical_name()));
+      Z, LookupClassByKernelClass(constructor->EnclosingName()));
   return LookupConstructorByKernelConstructor(klass, constructor);
 }
 
 
 dart::RawFunction* TranslationHelper::LookupConstructorByKernelConstructor(
     const dart::Class& owner,
-    Constructor* constructor) {
+    CanonicalName* constructor) {
+  ASSERT(constructor->IsConstructor());
   dart::RawFunction* function =
       owner.LookupConstructorAllowPrivate(DartConstructorName(constructor));
   ASSERT(function != Object::null());
@@ -1306,13 +1346,12 @@
 }
 
 
-dart::String& TranslationHelper::ManglePrivateName(
-    CanonicalName* kernel_library,
-    dart::String* name_to_modify,
-    bool symbolize) {
+dart::String& TranslationHelper::ManglePrivateName(CanonicalName* parent,
+                                                   dart::String* name_to_modify,
+                                                   bool symbolize) {
   if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') {
     const dart::Library& library =
-        dart::Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library));
+        dart::Library::Handle(Z, LookupLibraryByKernelLibrary(parent));
     *name_to_modify = library.PrivateName(*name_to_modify);
   } else if (symbolize) {
     *name_to_modify = Symbols::New(thread_, *name_to_modify);
@@ -1680,11 +1719,10 @@
 
 
 void ConstantEvaluator::VisitStaticGet(StaticGet* node) {
-  Member* member = node->target();
-  if (member->IsField()) {
-    Field* kernel_field = Field::Cast(member);
+  CanonicalName* target = node->target();
+  if (target->IsField()) {
     const dart::Field& field =
-        dart::Field::Handle(Z, H.LookupFieldByKernelField(kernel_field));
+        dart::Field::Handle(Z, H.LookupFieldByKernelField(target));
     if (field.StaticValue() == Object::sentinel().raw() ||
         field.StaticValue() == Object::transition_sentinel().raw()) {
       field.EvaluateInitializer();
@@ -1694,19 +1732,17 @@
     } else {
       result_ = field.StaticValue();
     }
-  } else if (member->IsProcedure()) {
-    Procedure* procedure = Procedure::Cast(member);
-    const Function& target = Function::ZoneHandle(
-        Z, H.LookupStaticMethodByKernelProcedure(procedure));
+  } else if (target->IsProcedure()) {
+    const Function& function =
+        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
 
-    if (procedure->kind() == Procedure::kMethod) {
-      ASSERT(procedure->IsStatic());
+    if (target->IsMethod()) {
       Function& closure_function =
-          Function::ZoneHandle(Z, target.ImplicitClosureFunction());
-      closure_function.set_kernel_function(target.kernel_function());
+          Function::ZoneHandle(Z, function.ImplicitClosureFunction());
+      closure_function.set_kernel_function(function.kernel_function());
       result_ = closure_function.ImplicitStaticClosure();
       result_ = H.Canonicalize(result_);
-    } else if (procedure->kind() == Procedure::kGetter) {
+    } else if (target->IsGetter()) {
       UNIMPLEMENTED();
     } else {
       UNIMPLEMENTED();
@@ -1814,7 +1850,7 @@
 
 
 void ConstantEvaluator::VisitPropertyGet(PropertyGet* node) {
-  const intptr_t kLengthLen = strlen("length");
+  const intptr_t kLengthLen = sizeof("length") - 1;
 
   String* string = node->name()->string();
   if ((string->size() == kLengthLen) &&
@@ -2839,11 +2875,11 @@
 
 
 dart::RawFunction* FlowGraphBuilder::LookupMethodByMember(
-    Member* target,
+    CanonicalName* target,
     const dart::String& method_name) {
-  Class* kernel_klass = Class::Cast(target->parent());
-  dart::Class& klass = dart::Class::Handle(
-      Z, H.LookupClassByKernelClass(kernel_klass->canonical_name()));
+  CanonicalName* kernel_class = target->EnclosingName();
+  dart::Class& klass =
+      dart::Class::Handle(Z, H.LookupClassByKernelClass(kernel_class));
 
   dart::RawFunction* function = klass.LookupFunctionAllowPrivate(method_name);
   ASSERT(function != Object::null());
@@ -3002,14 +3038,14 @@
 
   Function& outermost_function = Function::Handle(Z);
   TreeNode* outermost_node = NULL;
-  Class* kernel_klass = NULL;
+  Class* kernel_class = NULL;
   DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node,
-                            &kernel_klass);
+                            &kernel_class);
 
   // Mark that we are using [klass]/[kernell_klass] as active class.  Resolving
   // of type parameters will get resolved via [kernell_klass] unless we are
   // nested inside a static factory in which case we will use [member].
-  ActiveClassScope active_class_scope(&active_class_, kernel_klass, &klass);
+  ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass);
   Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
                        ? Member::Cast(outermost_node)
                        : NULL;
@@ -3126,8 +3162,8 @@
     // TODO(27590): Currently the [VariableDeclaration]s from the
     // initializers will be visible inside the entire body of the constructor.
     // We should make a separate scope for them.
-    Class* kernel_klass = Class::Cast(constructor->parent());
-    body += TranslateInitializers(kernel_klass, &constructor->initializers());
+    Class* kernel_class = Class::Cast(constructor->parent());
+    body += TranslateInitializers(kernel_class, &constructor->initializers());
   }
 
   // The specification defines the result of `a == b` to be:
@@ -3527,8 +3563,8 @@
 
   bool is_setter = function.IsImplicitSetterFunction();
   bool is_method = !function.IsStaticFunction();
-  dart::Field& field =
-      dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
+  dart::Field& field = dart::Field::ZoneHandle(
+      Z, H.LookupFieldByKernelField(kernel_field->canonical_name()));
 
   TargetEntryInstr* normal_entry = BuildTargetEntry();
   graph_entry_ = new (Z)
@@ -4074,7 +4110,7 @@
 
 
 Fragment FlowGraphBuilder::TranslateInitializers(
-    Class* kernel_klass,
+    Class* kernel_class,
     List<Initializer>* initializers) {
   Fragment instructions;
 
@@ -4082,12 +4118,12 @@
   //   class A {
   //     var x = (expr);
   //   }
-  for (intptr_t i = 0; i < kernel_klass->fields().length(); i++) {
-    Field* kernel_field = kernel_klass->fields()[i];
+  for (intptr_t i = 0; i < kernel_class->fields().length(); i++) {
+    Field* kernel_field = kernel_class->fields()[i];
     Expression* init = kernel_field->initializer();
     if (!kernel_field->IsStatic() && init != NULL) {
-      dart::Field& field =
-          dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
+      dart::Field& field = dart::Field::ZoneHandle(
+          Z, H.LookupFieldByKernelField(kernel_field->canonical_name()));
 
       EnterScope(kernel_field);
       instructions += LoadLocal(scopes_->this_variable);
@@ -4482,8 +4518,8 @@
       node->type_arguments().raw_array(), node->type_arguments().length());
 
 
-  dart::Object& klass = dart::Object::Handle(
-      Z, H.LookupClassByKernelClass(node->class_reference()));
+  dart::Object& klass =
+      dart::Object::Handle(Z, H.LookupClassByKernelClass(node->klass()));
   result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
   if (finalize_) {
     ASSERT(active_class_->klass != NULL);
@@ -4606,16 +4642,15 @@
 
 
 void FlowGraphBuilder::VisitStaticGet(StaticGet* node) {
-  Member* target = node->target();
+  CanonicalName* target = node->target();
   if (target->IsField()) {
-    Field* kernel_field = Field::Cast(target);
     const dart::Field& field =
-        dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
+        dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
     if (field.is_const()) {
       fragment_ = Constant(constant_evaluator_.EvaluateExpression(node));
     } else {
       const dart::Class& owner = dart::Class::Handle(Z, field.Owner());
-      const dart::String& getter_name = H.DartGetterName(kernel_field->name());
+      const dart::String& getter_name = H.DartGetterName(target);
       const Function& getter =
           Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name));
       if (getter.IsNull() || !field.has_initializer()) {
@@ -4626,14 +4661,12 @@
       }
     }
   } else {
-    Procedure* procedure = Procedure::Cast(target);
-    const Function& target = Function::ZoneHandle(
-        Z, H.LookupStaticMethodByKernelProcedure(procedure));
+    const Function& function =
+        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
 
-    if (procedure->kind() == Procedure::kGetter) {
-      fragment_ = StaticCall(node->position(), target, 0);
-    } else if (procedure->kind() == Procedure::kMethod) {
-      ASSERT(procedure->IsStatic());
+    if (target->IsGetter()) {
+      fragment_ = StaticCall(node->position(), function, 0);
+    } else if (target->IsMethod()) {
       fragment_ = Constant(constant_evaluator_.EvaluateExpression(node));
     } else {
       UNIMPLEMENTED();
@@ -4643,11 +4676,10 @@
 
 
 void FlowGraphBuilder::VisitStaticSet(StaticSet* node) {
-  Member* target = node->target();
+  CanonicalName* target = node->target();
   if (target->IsField()) {
-    Field* kernel_field = Field::Cast(target);
     const dart::Field& field =
-        dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
+        dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
     const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
     Fragment instructions = TranslateExpression(node->expression());
     if (NeedsDebugStepCheck(stack_, node->position())) {
@@ -4670,10 +4702,9 @@
     instructions += PushArgument();
 
     // Invoke the setter function.
-    Procedure* procedure = Procedure::Cast(target);
-    const Function& target = Function::ZoneHandle(
-        Z, H.LookupStaticMethodByKernelProcedure(procedure));
-    instructions += StaticCall(node->position(), target, 1);
+    const Function& function =
+        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
+    instructions += StaticCall(node->position(), function, 1);
 
     // Drop the unused result & leave the stored value on the stack.
     fragment_ = instructions + Drop();
@@ -4707,24 +4738,21 @@
 
 void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) {
   Function& target = Function::ZoneHandle(Z);
-  if (node->target()->IsProcedure()) {
-    Procedure* kernel_procedure = Procedure::Cast(node->target());
-    Name* kernel_name = kernel_procedure->name();
-    if (kernel_procedure->kind() == Procedure::kGetter) {
-      target =
-          LookupMethodByMember(kernel_procedure, H.DartGetterName(kernel_name));
+  CanonicalName* kernel_name = node->target();
+  if (kernel_name->IsProcedure()) {
+    if (kernel_name->IsGetter()) {
+      target = LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name));
     } else {
-      target =
-          LookupMethodByMember(kernel_procedure, H.DartMethodName(kernel_name));
+      target = LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
       target = target.ImplicitClosureFunction();
       ASSERT(!target.IsNull());
       fragment_ = BuildImplicitClosureCreation(target);
       return;
     }
   } else {
-    ASSERT(node->target()->IsField());
-    const dart::String& getter_name = H.DartGetterName(node->target()->name());
-    target = LookupMethodByMember(node->target(), getter_name);
+    ASSERT(kernel_name->IsField());
+    const dart::String& getter_name = H.DartGetterName(kernel_name);
+    target = LookupMethodByMember(kernel_name, getter_name);
     ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
   }
 
@@ -4735,7 +4763,7 @@
 
 
 void FlowGraphBuilder::VisitDirectPropertySet(DirectPropertySet* node) {
-  const dart::String& method_name = H.DartSetterName(node->target()->name());
+  const dart::String& method_name = H.DartSetterName(node->target());
   const Function& target = Function::ZoneHandle(
       Z, LookupMethodByMember(node->target(), method_name));
   ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
@@ -4927,10 +4955,8 @@
     return;
   }
 
-  Class* kernel_class = Class::Cast(node->target()->parent());
-
   dart::Class& klass = dart::Class::ZoneHandle(
-      Z, H.LookupClassByKernelClass(kernel_class->canonical_name()));
+      Z, H.LookupClassByKernelClass(node->target()->EnclosingName()));
 
   Fragment instructions;
 
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h
index 1a58d4f..9dd05e6 100644
--- a/runtime/vm/kernel_to_il.h
+++ b/runtime/vm/kernel_to_il.h
@@ -301,16 +301,26 @@
   const dart::String& DartSymbol(const char* content) const;
   dart::String& DartSymbol(String* content) const;
 
-  const dart::String& DartClassName(CanonicalName* kernel_klass);
-  const dart::String& DartConstructorName(Constructor* node);
-  const dart::String& DartProcedureName(Procedure* procedure);
+  const dart::String& DartClassName(CanonicalName* kernel_class);
 
-  const dart::String& DartSetterName(Name* kernel_name);
-  const dart::String& DartGetterName(Name* kernel_name);
+  const dart::String& DartConstructorName(CanonicalName* constructor);
+
+  const dart::String& DartProcedureName(CanonicalName* procedure);
+
+  const dart::String& DartSetterName(CanonicalName* setter);
+  const dart::String& DartSetterName(Name* setter_name);
+
+  const dart::String& DartGetterName(CanonicalName* getter);
+  const dart::String& DartGetterName(Name* getter_name);
+
   const dart::String& DartFieldName(Name* kernel_name);
+
   const dart::String& DartInitializerName(Name* kernel_name);
-  const dart::String& DartMethodName(Name* kernel_name);
-  const dart::String& DartFactoryName(Class* klass, Name* kernel_name);
+
+  const dart::String& DartMethodName(CanonicalName* method);
+  const dart::String& DartMethodName(Name* method_name);
+
+  const dart::String& DartFactoryName(CanonicalName* factory);
 
   const Array& ArgumentNames(List<NamedExpression>* named);
 
@@ -320,12 +330,12 @@
   virtual RawLibrary* LookupLibraryByKernelLibrary(CanonicalName* library);
   virtual RawClass* LookupClassByKernelClass(CanonicalName* klass);
 
-  RawField* LookupFieldByKernelField(Field* field);
-  RawFunction* LookupStaticMethodByKernelProcedure(Procedure* procedure);
-  RawFunction* LookupConstructorByKernelConstructor(Constructor* constructor);
+  RawField* LookupFieldByKernelField(CanonicalName* field);
+  RawFunction* LookupStaticMethodByKernelProcedure(CanonicalName* procedure);
+  RawFunction* LookupConstructorByKernelConstructor(CanonicalName* constructor);
   dart::RawFunction* LookupConstructorByKernelConstructor(
       const dart::Class& owner,
-      Constructor* constructor);
+      CanonicalName* constructor);
 
   dart::Type& GetCanonicalType(const dart::Class& klass);
 
@@ -333,12 +343,18 @@
   void ReportError(const Error& prev_error, const char* format, ...);
 
  private:
-  // This will mangle [kernel_name] (if necessary) and make the result a symbol.
-  // The result will be avilable in [name_to_modify] and it is also returned.
-  dart::String& ManglePrivateName(CanonicalName* kernel_library,
+  // This will mangle [name_to_modify] if necessary and make the result a symbol
+  // if asked.  The result will be avilable in [name_to_modify] and it is also
+  // returned.  If the name is private, the canonical name [parent] will be used
+  // to get the import URI of the library where the name is visible.
+  dart::String& ManglePrivateName(CanonicalName* parent,
                                   dart::String* name_to_modify,
                                   bool symbolize = true);
 
+  const dart::String& DartSetterName(CanonicalName* parent, String* setter);
+  const dart::String& DartGetterName(CanonicalName* parent, String* getter);
+  const dart::String& DartMethodName(CanonicalName* parent, String* method);
+
   dart::Thread* thread_;
   dart::Zone* zone_;
   dart::Isolate* isolate_;
@@ -817,7 +833,7 @@
   Fragment TranslateArguments(Arguments* node, Array* argument_names);
   ArgumentArray GetArguments(int count);
 
-  Fragment TranslateInitializers(Class* kernel_klass,
+  Fragment TranslateInitializers(Class* kernel_class,
                                  List<Initializer>* initialiers);
 
   Fragment TranslateStatement(Statement* statement);
@@ -944,7 +960,7 @@
   bool NeedsDebugStepCheck(Value* value, TokenPosition position);
   Fragment DebugStepCheck(TokenPosition position);
 
-  dart::RawFunction* LookupMethodByMember(Member* target,
+  dart::RawFunction* LookupMethodByMember(CanonicalName* target,
                                           const dart::String& method_name);
 
   LocalVariable* MakeTemporary();
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index fd8f004..97fb616 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -471,7 +471,7 @@
 mirrors/class_mirror_location_test: RuntimeError
 mirrors/constructor_kinds_test/01: RuntimeError
 mirrors/constructor_kinds_test/none: RuntimeError
-mirrors/constructor_optional_args_test: RuntimeError
+mirrors/constructor_optional_args_test: Crash # Issue 29201
 mirrors/constructor_private_name_test: RuntimeError
 mirrors/dart2js_mirrors_test: Crash
 mirrors/deferred_mirrors_metadata_test: RuntimeError