Chromium Code Reviews| 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::AddToCHAClasses(Class* cls) { | |
| 16 for (intptr_t i = 0; i < cha_classes_.length(); i++) { | |
| 17 if (cha_classes_[i]->raw() == cls->raw()) { | |
| 18 return; | |
| 19 } | |
| 20 } | |
| 21 cha_classes_.Add(cls); | |
| 22 } | |
| 23 | |
|
Vyacheslav Egorov (Google)
2014/08/12 12:16:55
add empty line
Florian Schneider
2014/08/13 10:34:40
Done.
| |
| 15 bool CHA::HasSubclasses(intptr_t cid) { | 24 bool CHA::HasSubclasses(intptr_t cid) { |
| 16 Isolate* isolate = Isolate::Current(); | |
| 17 const bool has_subclasses = HasSubclassesSafe(cid); | 25 const bool has_subclasses = HasSubclassesSafe(cid); |
| 18 if (!has_subclasses) { | 26 if (!has_subclasses) { |
| 19 isolate->set_cha_used(true); | 27 const ClassTable& class_table = *isolate_->class_table(); |
| 28 Class& cls = Class::ZoneHandle(isolate_, class_table.At(cid)); | |
| 29 AddToCHAClasses(&cls); | |
| 20 } | 30 } |
| 21 return has_subclasses; | 31 return has_subclasses; |
| 22 } | 32 } |
| 23 | 33 |
| 24 | 34 |
| 25 bool CHA::HasSubclassesSafe(intptr_t cid) { | 35 bool CHA::HasSubclassesSafe(intptr_t cid) { |
|
Vyacheslav Egorov (Google)
2014/08/12 12:16:55
I find the name HasSubclassesSafe confusing.
Florian Schneider
2014/08/13 10:34:40
I removed it.
| |
| 26 ASSERT(cid >= kInstanceCid); | 36 ASSERT(cid >= kInstanceCid); |
| 27 Isolate* isolate = Isolate::Current(); | 37 const ClassTable& class_table = *isolate_->class_table(); |
| 28 const ClassTable& class_table = *isolate->class_table(); | 38 const Class& cls = Class::Handle(isolate_, class_table.At(cid)); |
| 29 const Class& cls = Class::Handle(isolate, class_table.At(cid)); | |
| 30 ASSERT(!cls.IsNull()); | 39 ASSERT(!cls.IsNull()); |
| 31 if (cls.IsObjectClass()) { | 40 if (cls.IsObjectClass()) { |
| 32 // Class Object has subclasses, although we do not keep track of them. | 41 // Class Object has subclasses, although we do not keep track of them. |
| 33 return true; | 42 return true; |
| 34 } | 43 } |
| 35 const GrowableObjectArray& cls_direct_subclasses = | 44 const GrowableObjectArray& cls_direct_subclasses = |
| 36 GrowableObjectArray::Handle(isolate, cls.direct_subclasses()); | 45 GrowableObjectArray::Handle(isolate_, cls.direct_subclasses()); |
| 37 return | 46 return !cls_direct_subclasses.IsNull() |
| 38 !cls_direct_subclasses.IsNull() && (cls_direct_subclasses.Length() > 0); | 47 && (cls_direct_subclasses.Length() > 0); |
| 39 } | |
| 40 | |
| 41 | |
| 42 // Returns true if the given array of cids contains the given cid. | |
| 43 static bool ContainsCid(ZoneGrowableArray<intptr_t>* cids, intptr_t cid) { | |
| 44 for (intptr_t i = 0; i < cids->length(); i++) { | |
| 45 if ((*cids)[i] == cid) { | |
| 46 return true; | |
| 47 } | |
| 48 } | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 | |
| 53 // Recursively collect direct and indirect subclass ids of cls. | |
| 54 static void CollectSubclassIds(ZoneGrowableArray<intptr_t>* cids, | |
| 55 const Class& cls) { | |
| 56 const GrowableObjectArray& cls_direct_subclasses = | |
| 57 GrowableObjectArray::Handle(cls.direct_subclasses()); | |
| 58 if (cls_direct_subclasses.IsNull()) { | |
| 59 return; | |
| 60 } | |
| 61 Class& direct_subclass = Class::Handle(); | |
| 62 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | |
| 63 direct_subclass ^= cls_direct_subclasses.At(i); | |
| 64 intptr_t direct_subclass_id = direct_subclass.id(); | |
| 65 if (!ContainsCid(cids, direct_subclass_id)) { | |
| 66 cids->Add(direct_subclass_id); | |
| 67 CollectSubclassIds(cids, direct_subclass); | |
| 68 } | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 | |
| 73 ZoneGrowableArray<intptr_t>* CHA::GetSubclassIdsOf(intptr_t cid) { | |
| 74 ASSERT(cid > kInstanceCid); | |
| 75 Isolate* isolate = Isolate::Current(); | |
| 76 const ClassTable& class_table = *isolate->class_table(); | |
| 77 const Class& cls = Class::Handle(isolate, class_table.At(cid)); | |
| 78 ASSERT(!cls.IsNull()); | |
| 79 ZoneGrowableArray<intptr_t>* ids = new ZoneGrowableArray<intptr_t>(); | |
| 80 CollectSubclassIds(ids, cls); | |
| 81 isolate->set_cha_used(true); | |
| 82 return ids; | |
| 83 } | 48 } |
| 84 | 49 |
| 85 | 50 |
| 86 bool CHA::HasOverride(const Class& cls, const String& function_name) { | 51 bool CHA::HasOverride(const Class& cls, const String& function_name) { |
| 87 Isolate* isolate = Isolate::Current(); | |
| 88 const GrowableObjectArray& cls_direct_subclasses = | 52 const GrowableObjectArray& cls_direct_subclasses = |
| 89 GrowableObjectArray::Handle(isolate, cls.direct_subclasses()); | 53 GrowableObjectArray::Handle(isolate_, cls.direct_subclasses()); |
| 90 // Subclasses of Object are not tracked by CHA. Safely assume that overrides | 54 // Subclasses of Object are not tracked by CHA. Safely assume that overrides |
| 91 // exist. | 55 // exist. |
| 92 if (cls.IsObjectClass()) { | 56 if (cls.IsObjectClass()) { |
| 93 return true; | 57 return true; |
| 94 } | 58 } |
| 95 | 59 |
| 96 if (cls_direct_subclasses.IsNull()) { | 60 if (cls_direct_subclasses.IsNull()) { |
| 97 isolate->set_cha_used(true); | 61 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); |
|
Vyacheslav Egorov (Google)
2014/08/12 12:16:55
Maybe it's better to have a single return false in
| |
| 98 return false; | 62 return false; |
| 99 } | 63 } |
| 100 Class& direct_subclass = Class::Handle(isolate); | 64 Class& direct_subclass = Class::Handle(isolate_); |
| 101 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | 65 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { |
| 102 direct_subclass ^= cls_direct_subclasses.At(i); | 66 direct_subclass ^= cls_direct_subclasses.At(i); |
| 103 // Unfinalized classes are treated as non-existent for CHA purposes, | 67 // Unfinalized classes are treated as non-existent for CHA purposes, |
| 104 // as that means that no instance of that class exists at runtime. | 68 // as that means that no instance of that class exists at runtime. |
| 105 if (direct_subclass.is_finalized() && | 69 if (direct_subclass.is_finalized() && |
| 106 (direct_subclass.LookupDynamicFunction(function_name) != | 70 (direct_subclass.LookupDynamicFunction(function_name) != |
| 107 Function::null())) { | 71 Function::null())) { |
| 108 return true; | 72 return true; |
| 109 } | 73 } |
| 110 if (HasOverride(direct_subclass, function_name)) { | 74 if (HasOverride(direct_subclass, function_name)) { |
| 111 return true; | 75 return true; |
| 112 } | 76 } |
| 113 } | 77 } |
| 114 isolate->set_cha_used(true); | 78 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); |
| 115 return false; | 79 return false; |
| 116 } | 80 } |
| 117 | 81 |
| 118 | |
| 119 ZoneGrowableArray<Function*>* CHA::GetNamedInstanceFunctionsOf( | |
| 120 const ZoneGrowableArray<intptr_t>& cids, | |
| 121 const String& function_name) { | |
| 122 Isolate* isolate = Isolate::Current(); | |
| 123 ASSERT(!function_name.IsNull()); | |
| 124 const ClassTable& class_table = *isolate->class_table(); | |
| 125 ZoneGrowableArray<Function*>* functions = new ZoneGrowableArray<Function*>(); | |
| 126 Class& cls = Class::Handle(isolate); | |
| 127 Function& cls_function = Function::Handle(isolate); | |
| 128 for (intptr_t i = 0; i < cids.length(); i++) { | |
| 129 const intptr_t cid = cids[i]; | |
| 130 ASSERT(cid > kInstanceCid); | |
| 131 cls = class_table.At(cid); | |
| 132 cls_function = cls.LookupDynamicFunction(function_name); | |
| 133 if (!cls_function.IsNull()) { | |
| 134 functions->Add(&Function::ZoneHandle(isolate, cls_function.raw())); | |
| 135 } | |
| 136 } | |
| 137 isolate->set_cha_used(true); | |
| 138 return functions; | |
| 139 } | |
| 140 | |
| 141 | |
| 142 ZoneGrowableArray<Function*>* CHA::GetOverridesOf(const Function& function) { | |
| 143 ASSERT(!function.IsNull()); | |
| 144 ASSERT(function.IsDynamicFunction()); | |
| 145 Isolate* isolate = Isolate::Current(); | |
| 146 const Class& function_owner = Class::Handle(isolate, function.Owner()); | |
| 147 const String& function_name = String::Handle(isolate, function.name()); | |
| 148 ZoneGrowableArray<intptr_t>* cids = new ZoneGrowableArray<intptr_t>(); | |
| 149 CollectSubclassIds(cids, function_owner); | |
| 150 isolate->set_cha_used(true); | |
| 151 return GetNamedInstanceFunctionsOf(*cids, function_name); | |
| 152 } | |
| 153 | |
| 154 } // namespace dart | 82 } // namespace dart |
| OLD | NEW |