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 bool CHA::HasSubclasses(intptr_t cid) { | 15 void CHA::AddToCHAClasses(Class* cls) { |
Vyacheslav Egorov (Google)
2014/08/13 11:40:28
Accept an normal Handle here?
Florian Schneider
2014/08/13 12:08:57
Done.
| |
16 Isolate* isolate = Isolate::Current(); | 16 for (intptr_t i = 0; i < cha_classes_.length(); i++) { |
17 const bool has_subclasses = HasSubclassesSafe(cid); | 17 if (cha_classes_[i]->raw() == cls->raw()) { |
18 if (!has_subclasses) { | 18 return; |
19 isolate->set_cha_used(true); | 19 } |
20 } | 20 } |
21 return has_subclasses; | 21 cha_classes_.Add(cls); |
Vyacheslav Egorov (Google)
2014/08/13 11:40:27
Rewrap into ZoneHandle here.
Florian Schneider
2014/08/13 12:08:57
Done.
| |
22 } | 22 } |
23 | 23 |
24 | 24 |
25 bool CHA::HasSubclassesSafe(intptr_t cid) { | 25 // Return true if the class is private to our internal libraries (not extendable |
26 ASSERT(cid >= kInstanceCid); | 26 // or implementable by users). |
Vyacheslav Egorov (Google)
2014/08/13 11:40:28
The key point is that it can't be extended later a
| |
27 Isolate* isolate = Isolate::Current(); | 27 // (TODO): Allow more libraries. |
Vyacheslav Egorov (Google)
2014/08/13 11:40:27
TODO(fschneider) ? :)
strange TODO syntax.
Florian Schneider
2014/08/13 12:08:58
Done.
| |
28 const ClassTable& class_table = *isolate->class_table(); | 28 static bool IsKnownPrivateClass(const Class& type_class) { |
29 const Class& cls = Class::Handle(isolate, class_table.At(cid)); | 29 if (!Library::IsPrivate(String::Handle(type_class.Name()))) return false; |
30 const Library& library = Library::Handle(type_class.library()); | |
31 if (library.raw() == Library::CoreLibrary()) return true; | |
32 if (library.raw() == Library::CollectionLibrary()) return true; | |
33 if (library.raw() == Library::TypedDataLibrary()) return true; | |
34 if (library.raw() == Library::MathLibrary()) return true; | |
35 return false; | |
36 } | |
37 | |
38 | |
39 bool CHA::HasSubclasses(const Class& cls) { | |
30 ASSERT(!cls.IsNull()); | 40 ASSERT(!cls.IsNull()); |
41 ASSERT(cls.id() >= kInstanceCid); | |
42 // Can't track dependencies for classes on the VM heap since those are | |
43 // read-only. | |
44 // TODO(fschneider): Enable tracking of CHA dependent code for VM heap | |
45 // classes. | |
46 if (cls.InVMHeap()) return true; | |
47 | |
31 if (cls.IsObjectClass()) { | 48 if (cls.IsObjectClass()) { |
32 // Class Object has subclasses, although we do not keep track of them. | 49 // Class Object has subclasses, although we do not keep track of them. |
33 return true; | 50 return true; |
34 } | 51 } |
35 const GrowableObjectArray& cls_direct_subclasses = | 52 const GrowableObjectArray& direct_subclasses = |
36 GrowableObjectArray::Handle(isolate, cls.direct_subclasses()); | 53 GrowableObjectArray::Handle(isolate_, cls.direct_subclasses()); |
37 return | 54 bool result = |
38 !cls_direct_subclasses.IsNull() && (cls_direct_subclasses.Length() > 0); | 55 !direct_subclasses.IsNull() && (direct_subclasses.Length() > 0); |
56 if (!result && !IsKnownPrivateClass(cls)) { | |
57 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); | |
Vyacheslav Egorov (Google)
2014/08/13 11:40:28
I think you should move IsKnownPrivateClass into t
Florian Schneider
2014/08/13 12:08:58
Done.
| |
58 } | |
59 return result; | |
39 } | 60 } |
40 | 61 |
41 | 62 |
42 // Returns true if the given array of cids contains the given cid. | 63 bool CHA::HasSubclasses(intptr_t cid) { |
43 static bool ContainsCid(ZoneGrowableArray<intptr_t>* cids, intptr_t cid) { | 64 const ClassTable& class_table = *isolate_->class_table(); |
44 for (intptr_t i = 0; i < cids->length(); i++) { | 65 Class& cls = Class::Handle(isolate_, class_table.At(cid)); |
45 if ((*cids)[i] == cid) { | 66 return HasSubclasses(cls); |
46 return true; | |
47 } | |
48 } | |
49 return false; | |
50 } | 67 } |
51 | 68 |
52 | 69 |
53 // Recursively collect direct and indirect subclass ids of cls. | 70 bool CHA::IsImplemented(const Class& cls) { |
54 static void CollectSubclassIds(ZoneGrowableArray<intptr_t>* cids, | 71 // Can't track dependencies for classes on the VM heap since those are |
55 const Class& cls) { | 72 // read-only. |
56 const GrowableObjectArray& cls_direct_subclasses = | 73 // TODO(fschneider): Enable tracking of CHA dependent code for VM heap |
57 GrowableObjectArray::Handle(cls.direct_subclasses()); | 74 // classes. |
58 if (cls_direct_subclasses.IsNull()) { | 75 if (cls.InVMHeap()) return true; |
59 return; | 76 |
77 bool result = cls.is_implemented(); | |
78 if (!result && !IsKnownPrivateClass(cls)) { | |
79 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); | |
60 } | 80 } |
61 Class& direct_subclass = Class::Handle(); | 81 return result; |
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 } | 82 } |
84 | 83 |
85 | 84 |
86 bool CHA::HasOverride(const Class& cls, const String& function_name) { | 85 bool CHA::HasOverride(const Class& cls, const String& function_name) { |
87 Isolate* isolate = Isolate::Current(); | |
88 const GrowableObjectArray& cls_direct_subclasses = | 86 const GrowableObjectArray& cls_direct_subclasses = |
89 GrowableObjectArray::Handle(isolate, cls.direct_subclasses()); | 87 GrowableObjectArray::Handle(isolate_, cls.direct_subclasses()); |
90 // Subclasses of Object are not tracked by CHA. Safely assume that overrides | 88 // Subclasses of Object are not tracked by CHA. Safely assume that overrides |
91 // exist. | 89 // exist. |
92 if (cls.IsObjectClass()) { | 90 if (cls.IsObjectClass()) { |
93 return true; | 91 return true; |
94 } | 92 } |
95 | 93 |
94 bool is_known_private_class = IsKnownPrivateClass(cls); | |
96 if (cls_direct_subclasses.IsNull()) { | 95 if (cls_direct_subclasses.IsNull()) { |
97 isolate->set_cha_used(true); | 96 if (!is_known_private_class) { |
97 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); | |
98 } | |
98 return false; | 99 return false; |
99 } | 100 } |
100 Class& direct_subclass = Class::Handle(isolate); | 101 Class& direct_subclass = Class::Handle(isolate_); |
101 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { | 102 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { |
102 direct_subclass ^= cls_direct_subclasses.At(i); | 103 direct_subclass ^= cls_direct_subclasses.At(i); |
103 // Unfinalized classes are treated as non-existent for CHA purposes, | 104 // Unfinalized classes are treated as non-existent for CHA purposes, |
104 // as that means that no instance of that class exists at runtime. | 105 // as that means that no instance of that class exists at runtime. |
105 if (direct_subclass.is_finalized() && | 106 if (direct_subclass.is_finalized() && |
106 (direct_subclass.LookupDynamicFunction(function_name) != | 107 (direct_subclass.LookupDynamicFunction(function_name) != |
107 Function::null())) { | 108 Function::null())) { |
108 return true; | 109 return true; |
109 } | 110 } |
110 if (HasOverride(direct_subclass, function_name)) { | 111 if (HasOverride(direct_subclass, function_name)) { |
111 return true; | 112 return true; |
112 } | 113 } |
113 } | 114 } |
114 isolate->set_cha_used(true); | 115 if (!is_known_private_class) { |
116 AddToCHAClasses(&Class::ZoneHandle(cls.raw())); | |
117 } | |
115 return false; | 118 return false; |
116 } | 119 } |
117 | 120 |
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 | 121 } // namespace dart |
OLD | NEW |