| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "vm/cha.h" | 5 #include "vm/cha.h" | 
| 6 #include "vm/class_table.h" | 6 #include "vm/class_table.h" | 
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" | 
| 8 #include "vm/freelist.h" | 8 #include "vm/freelist.h" | 
| 9 #include "vm/object.h" | 9 #include "vm/object.h" | 
| 10 #include "vm/raw_object.h" | 10 #include "vm/raw_object.h" | 
| 11 #include "vm/visitor.h" | 11 #include "vm/visitor.h" | 
| 12 | 12 | 
| 13 namespace dart { | 13 namespace dart { | 
| 14 | 14 | 
| 15 void CHA::AddToLeafClasses(const Class& cls) { | 15 void CHA::AddToGuardedClasses(const Class& cls, intptr_t subclass_count) { | 
| 16   for (intptr_t i = 0; i < leaf_classes_.length(); i++) { | 16   for (intptr_t i = 0; i < guarded_classes_.length(); i++) { | 
| 17     if (leaf_classes_[i]->raw() == cls.raw()) { | 17     if (guarded_classes_[i].cls->raw() == cls.raw()) { | 
| 18       return; | 18       return; | 
| 19     } | 19     } | 
| 20   } | 20   } | 
| 21   leaf_classes_.Add(&Class::ZoneHandle(thread_->zone(), cls.raw())); | 21   GuardedClassInfo info = { | 
|  | 22     &Class::ZoneHandle(thread_->zone(), cls.raw()), | 
|  | 23     subclass_count | 
|  | 24   }; | 
|  | 25   guarded_classes_.Add(info); | 
|  | 26   return; | 
| 22 } | 27 } | 
| 23 | 28 | 
| 24 | 29 | 
|  | 30 bool CHA::IsGuardedClass(intptr_t cid) const { | 
|  | 31   for (intptr_t i = 0; i < guarded_classes_.length(); ++i) { | 
|  | 32     if (guarded_classes_[i].cls->id() == cid) return true; | 
|  | 33   } | 
|  | 34   return false; | 
|  | 35 } | 
|  | 36 | 
|  | 37 | 
| 25 bool CHA::HasSubclasses(const Class& cls) { | 38 bool CHA::HasSubclasses(const Class& cls) { | 
| 26   ASSERT(!cls.IsNull()); | 39   ASSERT(!cls.IsNull()); | 
| 27   ASSERT(cls.id() >= kInstanceCid); | 40   ASSERT(cls.id() >= kInstanceCid); | 
| 28   // Can't track dependencies for classes on the VM heap since those are | 41   // Can't track dependencies for classes on the VM heap since those are | 
| 29   // read-only. | 42   // read-only. | 
| 30   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 43   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 
| 31   // classes. | 44   // classes. | 
| 32   if (cls.InVMHeap()) return true; | 45   if (cls.InVMHeap()) return true; | 
| 33 | 46 | 
| 34   if (cls.IsObjectClass()) { | 47   if (cls.IsObjectClass()) { | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 79   // Can't track dependencies for classes on the VM heap since those are | 92   // Can't track dependencies for classes on the VM heap since those are | 
| 80   // read-only. | 93   // read-only. | 
| 81   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 94   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 
| 82   // classes. | 95   // classes. | 
| 83   if (cls.InVMHeap()) return true; | 96   if (cls.InVMHeap()) return true; | 
| 84 | 97 | 
| 85   return cls.is_implemented(); | 98   return cls.is_implemented(); | 
| 86 } | 99 } | 
| 87 | 100 | 
| 88 | 101 | 
| 89 bool CHA::HasOverride(const Class& cls, const String& function_name) { | 102 static intptr_t CountFinalizedSubclasses(Thread* thread, const Class& cls) { | 
|  | 103   intptr_t count = 0; | 
|  | 104   const GrowableObjectArray& cls_direct_subclasses = | 
|  | 105       GrowableObjectArray::Handle(thread->zone(), cls.direct_subclasses()); | 
|  | 106   if (cls_direct_subclasses.IsNull()) return count; | 
|  | 107   Class& direct_subclass = Class::Handle(thread->zone()); | 
|  | 108   for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | 
|  | 109     direct_subclass ^= cls_direct_subclasses.At(i); | 
|  | 110     // Unfinalized classes are treated as non-existent for CHA purposes, | 
|  | 111     // as that means that no instance of that class exists at runtime. | 
|  | 112     if (!direct_subclass.is_finalized()) { | 
|  | 113       continue; | 
|  | 114     } | 
|  | 115 | 
|  | 116     count += 1 + CountFinalizedSubclasses(thread, direct_subclass); | 
|  | 117   } | 
|  | 118   return count; | 
|  | 119 } | 
|  | 120 | 
|  | 121 | 
|  | 122 bool CHA::IsConsistentWithCurrentHierarchy() const { | 
|  | 123   for (intptr_t i = 0; i < guarded_classes_.length(); i++) { | 
|  | 124     const intptr_t subclass_count = | 
|  | 125         CountFinalizedSubclasses(thread_, *guarded_classes_[i].cls); | 
|  | 126     if (guarded_classes_[i].subclass_count != subclass_count) { | 
|  | 127       return false; | 
|  | 128     } | 
|  | 129   } | 
|  | 130   return true; | 
|  | 131 } | 
|  | 132 | 
|  | 133 | 
|  | 134 bool CHA::HasOverride(const Class& cls, | 
|  | 135                       const String& function_name, | 
|  | 136                       intptr_t* subclasses_count) { | 
| 90   // Can't track dependencies for classes on the VM heap since those are | 137   // Can't track dependencies for classes on the VM heap since those are | 
| 91   // read-only. | 138   // read-only. | 
| 92   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 139   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | 
| 93   // classes. | 140   // classes. | 
| 94   if (cls.InVMHeap()) return true; | 141   if (cls.InVMHeap()) return true; | 
| 95 | 142 | 
| 96   // Subclasses of Object are not tracked by CHA. Safely assume that overrides | 143   // Subclasses of Object are not tracked by CHA. Safely assume that overrides | 
| 97   // exist. | 144   // exist. | 
| 98   if (cls.IsObjectClass()) { | 145   if (cls.IsObjectClass()) { | 
| 99     return true; | 146     return true; | 
| 100   } | 147   } | 
| 101 | 148 | 
| 102   const GrowableObjectArray& cls_direct_subclasses = | 149   const GrowableObjectArray& cls_direct_subclasses = | 
| 103       GrowableObjectArray::Handle(thread_->zone(), cls.direct_subclasses()); | 150       GrowableObjectArray::Handle(thread_->zone(), cls.direct_subclasses()); | 
| 104   if (cls_direct_subclasses.IsNull()) { | 151   if (cls_direct_subclasses.IsNull()) { | 
| 105     return false; | 152     return false; | 
| 106   } | 153   } | 
| 107   Class& direct_subclass = Class::Handle(thread_->zone()); | 154   Class& direct_subclass = Class::Handle(thread_->zone()); | 
| 108   for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | 155   for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | 
| 109     direct_subclass ^= cls_direct_subclasses.At(i); | 156     direct_subclass ^= cls_direct_subclasses.At(i); | 
| 110     // Unfinalized classes are treated as non-existent for CHA purposes, | 157     // Unfinalized classes are treated as non-existent for CHA purposes, | 
| 111     // as that means that no instance of that class exists at runtime. | 158     // as that means that no instance of that class exists at runtime. | 
| 112     if (direct_subclass.is_finalized() && | 159     if (!direct_subclass.is_finalized()) { | 
| 113         (direct_subclass.LookupDynamicFunction(function_name) != | 160       continue; | 
| 114          Function::null())) { | 161     } | 
|  | 162 | 
|  | 163     if (direct_subclass.LookupDynamicFunction(function_name) != | 
|  | 164             Function::null()) { | 
| 115       return true; | 165       return true; | 
| 116     } | 166     } | 
| 117     if (HasOverride(direct_subclass, function_name)) { | 167 | 
|  | 168     if (HasOverride(direct_subclass, function_name, subclasses_count)) { | 
| 118       return true; | 169       return true; | 
| 119     } | 170     } | 
|  | 171 | 
|  | 172     (*subclasses_count)++; | 
| 120   } | 173   } | 
|  | 174 | 
| 121   return false; | 175   return false; | 
| 122 } | 176 } | 
| 123 | 177 | 
|  | 178 | 
|  | 179 void CHA::RegisterDependencies(const Code& code) const { | 
|  | 180   for (intptr_t i = 0; i < guarded_classes_.length(); ++i) { | 
|  | 181     guarded_classes_[i].cls->RegisterCHACode(code); | 
|  | 182   } | 
|  | 183 } | 
|  | 184 | 
|  | 185 | 
| 124 }  // namespace dart | 186 }  // namespace dart | 
| OLD | NEW | 
|---|