Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
cha.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/compiler/cha.h"
6#include "vm/class_table.h"
8#include "vm/flags.h"
9#include "vm/log.h"
10#include "vm/object.h"
11#include "vm/raw_object.h"
12#include "vm/visitor.h"
13
14namespace dart {
15
16void CHA::AddToGuardedClasses(const Class& cls,
17 intptr_t subclass_count,
18 intptr_t implementor_cid,
19 bool track_future) {
20 for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
21 if (guarded_classes_[i].cls->ptr() == cls.ptr()) {
22 if ((subclass_count >= 0) && (guarded_classes_[i].subclass_count == -1)) {
23 guarded_classes_[i].subclass_count = subclass_count;
24 }
25 if ((implementor_cid != kIllegalCid) &&
26 (guarded_classes_[i].implementor_cid == kIllegalCid)) {
27 guarded_classes_[i].implementor_cid = implementor_cid;
28 }
29 if (track_future && !guarded_classes_[i].track_future) {
30 guarded_classes_[i].track_future = track_future;
31 }
32 return;
33 }
34 }
35 GuardedClassInfo info = {&Class::ZoneHandle(thread_->zone(), cls.ptr()),
36 subclass_count, implementor_cid, track_future};
37 guarded_classes_.Add(info);
38}
39
41 intptr_t subclass_count) {
42 ASSERT(subclass_count >= 0);
43 AddToGuardedClasses(cls, subclass_count, kIllegalCid, false);
44}
45
47 intptr_t implementor_cid) {
48 ASSERT(implementor_cid != kIllegalCid);
49 ASSERT(implementor_cid != kDynamicCid);
50 AddToGuardedClasses(cls, -1, implementor_cid, false);
51}
52
54 AddToGuardedClasses(cls, -1, kIllegalCid, true);
55}
56
57bool CHA::IsGuardedClass(intptr_t cid) const {
58 for (intptr_t i = 0; i < guarded_classes_.length(); ++i) {
59 if (guarded_classes_[i].cls->id() == cid) return true;
60 }
61 return false;
62}
63
64bool CHA::HasSubclasses(const Class& cls) {
65 ASSERT(!cls.IsNull());
67 // Can't track dependencies for classes on the VM heap since those are
68 // read-only.
69 // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
70 // classes.
71 if (cls.InVMIsolateHeap()) return true;
72
73 if (cls.IsObjectClass()) {
74 // Class Object has subclasses, although we do not keep track of them.
75 return true;
76 }
77 Thread* thread = Thread::Current();
78 SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
79 const GrowableObjectArray& direct_subclasses =
81 return !direct_subclasses.IsNull() && (direct_subclasses.Length() > 0);
82}
83
84bool CHA::HasSubclasses(intptr_t cid) const {
85 const ClassTable& class_table = *thread_->isolate_group()->class_table();
86 Class& cls = Class::Handle(thread_->zone(), class_table.At(cid));
87 return HasSubclasses(cls);
88}
89
91 GrowableArray<intptr_t>* class_ids) {
92 if (cls.InVMIsolateHeap()) return false;
93 if (cls.IsObjectClass()) return false;
94
95 if (!cls.is_abstract()) {
96 class_ids->Add(cls.id());
97 }
98
99 // This is invoked from precompiler only, we can use unsafe version of
100 // Class::direct_subclasses getter.
101 ASSERT(FLAG_precompiled_mode);
102 const GrowableObjectArray& direct_subclasses =
104 if (direct_subclasses.IsNull()) {
105 return true;
106 }
107 Class& subclass = Class::Handle();
108 for (intptr_t i = 0; i < direct_subclasses.Length(); i++) {
109 subclass ^= direct_subclasses.At(i);
110 if (!ConcreteSubclasses(subclass, class_ids)) {
111 return false;
112 }
113 }
114 return true;
115}
116
117bool CHA::IsImplemented(const Class& cls) {
118 // Can't track dependencies for classes on the VM heap since those are
119 // read-only.
120 // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
121 // classes.
122 if (cls.InVMIsolateHeap()) return true;
123
124 return cls.is_implemented();
125}
126
128 intptr_t* implementation_cid) {
129 intptr_t cid = interface.implementor_cid();
130 if ((cid == kIllegalCid) || (cid == kDynamicCid)) {
131 // No implementations / multiple implementations.
132 *implementation_cid = kDynamicCid;
133 return false;
134 }
135
136 Thread* thread = Thread::Current();
137 if (FLAG_use_cha_deopt || thread->isolate_group()->all_classes_finalized()) {
138 if (FLAG_trace_cha) {
139 THR_Print(" **(CHA) Type has one implementation: %s\n",
140 interface.ToCString());
141 }
142 if (FLAG_use_cha_deopt) {
143 CHA& cha = thread->compiler_state().cha();
145 }
146 *implementation_cid = cid;
147 return true;
148 } else {
149 *implementation_cid = kDynamicCid;
150 return false;
151 }
152}
153
154bool CHA::ClassCanBeFuture(const Class& cls) {
155 if (cls.can_be_future()) {
156 return true;
157 }
158
159 // Class cannot be Future with the current set of
160 // finalized classes. However, as new classes are loaded
161 // and finalized, there could be a new subtype of [cls]
162 // which is also a subtype of Future.
163 // We should deoptimize in such cases.
164 Thread* thread = Thread::Current();
165 if (FLAG_use_cha_deopt || thread->isolate_group()->all_classes_finalized()) {
166 if (FLAG_use_cha_deopt) {
167 CHA& cha = thread->compiler_state().cha();
169 }
170 return false;
171 }
172
173 // Conservatively assume that class can be Future.
174 return true;
175}
176
177static intptr_t CountFinalizedSubclasses(Thread* thread, const Class& cls) {
178 intptr_t count = 0;
179 const GrowableObjectArray& cls_direct_subclasses =
181 if (cls_direct_subclasses.IsNull()) return count;
182 Class& direct_subclass = Class::Handle(thread->zone());
183 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) {
184 direct_subclass ^= cls_direct_subclasses.At(i);
185 // Unfinalized classes are treated as nonexistent for CHA purposes,
186 // as that means that no instance of that class exists at runtime.
187 if (!direct_subclass.is_finalized()) {
188 continue;
189 }
190
191 count += 1 + CountFinalizedSubclasses(thread, direct_subclass);
192 }
193 return count;
194}
195
197 for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
198 if (guarded_classes_[i].subclass_count != -1) {
199 intptr_t current_subclass_count =
200 CountFinalizedSubclasses(thread_, *guarded_classes_[i].cls);
201 if (guarded_classes_[i].subclass_count != current_subclass_count) {
202 return false; // New subclass appeared during compilation.
203 }
204 }
205 if (guarded_classes_[i].implementor_cid != kIllegalCid) {
206 intptr_t current_implementor_cid =
207 guarded_classes_[i].cls->implementor_cid();
208 if (guarded_classes_[i].implementor_cid != current_implementor_cid) {
209 return false; // New implementor appeared during compilation.
210 }
211 }
212 if (guarded_classes_[i].track_future) {
213 if (guarded_classes_[i].cls->can_be_future()) {
214 return false;
215 }
216 }
217 }
218 return true;
219}
220
221bool CHA::HasOverride(const Class& cls,
222 const String& function_name,
223 intptr_t* subclasses_count) {
224 // Can't track dependencies for classes on the VM heap since those are
225 // read-only.
226 // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
227 // classes.
228 if (cls.InVMIsolateHeap()) return true;
229
230 // Subclasses of Object are not tracked by CHA. Safely assume that overrides
231 // exist.
232 if (cls.IsObjectClass()) {
233 return true;
234 }
235
236 SafepointReadRwLocker ml(thread_, thread_->isolate_group()->program_lock());
237 const GrowableObjectArray& cls_direct_subclasses =
239 if (cls_direct_subclasses.IsNull()) {
240 return false;
241 }
242 Class& direct_subclass = Class::Handle(thread_->zone());
243 for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) {
244 direct_subclass ^= cls_direct_subclasses.At(i);
245 // Unfinalized classes are treated as nonexistent for CHA purposes,
246 // as that means that no instance of that class exists at runtime.
247 if (!direct_subclass.is_finalized()) {
248 continue;
249 }
250
251 if (direct_subclass.LookupDynamicFunctionUnsafe(function_name) !=
252 Function::null()) {
253 return true;
254 }
255
256 if (HasOverride(direct_subclass, function_name, subclasses_count)) {
257 return true;
258 }
259
260 (*subclasses_count)++;
261 }
262
263 return false;
264}
265
266void CHA::RegisterDependencies(const Code& code) const {
267 for (intptr_t i = 0; i < guarded_classes_.length(); ++i) {
268 guarded_classes_[i].cls->RegisterCHACode(code);
269 }
270}
271
272} // namespace dart
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
void Add(const T &value)
intptr_t length() const
bool HasOverride(const Class &cls, const String &function_name, intptr_t *subclass_count)
Definition cha.cc:221
void AddToGuardedClassesForImplementorCid(const Class &cls, intptr_t implementor_cid)
Definition cha.cc:46
void RegisterDependencies(const Code &code) const
Definition cha.cc:266
static bool IsImplemented(const Class &cls)
Definition cha.cc:117
bool IsGuardedClass(intptr_t cid) const
Definition cha.cc:57
static bool HasSubclasses(const Class &cls)
Definition cha.cc:64
void AddToGuardedClassesForSubclassCount(const Class &cls, intptr_t subclass_count)
Definition cha.cc:40
static bool ConcreteSubclasses(const Class &cls, GrowableArray< intptr_t > *class_ids)
Definition cha.cc:90
void AddToGuardedClassesToTrackFuture(const Class &cls)
Definition cha.cc:53
static bool ClassCanBeFuture(const Class &cls)
Definition cha.cc:154
bool IsConsistentWithCurrentHierarchy() const
Definition cha.cc:196
static bool HasSingleConcreteImplementation(const Class &interface, intptr_t *implementation_cid)
Definition cha.cc:127
ClassPtr At(intptr_t cid) const
bool can_be_future() const
Definition object.h:2178
GrowableObjectArrayPtr direct_subclasses() const
Definition object.h:1539
intptr_t id() const
Definition object.h:1235
bool IsObjectClass() const
Definition object.h:1567
intptr_t implementor_cid() const
Definition object.h:1247
FunctionPtr LookupDynamicFunctionUnsafe(const String &name) const
Definition object.cc:6184
bool is_abstract() const
Definition object.h:1698
GrowableObjectArrayPtr direct_subclasses_unsafe() const
Definition object.h:1544
bool is_implemented() const
Definition object.h:1694
bool is_finalized() const
Definition object.h:1725
intptr_t Length() const
Definition object.h:11046
ObjectPtr At(intptr_t index) const
Definition object.h:11059
bool all_classes_finalized() const
Definition isolate.h:706
SafepointRwLock * program_lock()
Definition isolate.h:532
ClassTable * class_table() const
Definition isolate.h:491
static ObjectPtr null()
Definition object.h:433
bool InVMIsolateHeap() const
Definition object.h:395
virtual const char * ToCString() const
Definition object.h:366
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
static Object & ZoneHandle()
Definition object.h:419
Zone * zone() const
static Thread * Current()
Definition thread.h:361
CompilerState & compiler_state()
Definition thread.h:583
IsolateGroup * isolate_group() const
Definition thread.h:540
#define THR_Print(format,...)
Definition log.h:20
#define ASSERT(E)
@ kIllegalCid
Definition class_id.h:214
@ kDynamicCid
Definition class_id.h:253
static intptr_t CountFinalizedSubclasses(Thread *thread, const Class &cls)
Definition cha.cc:177
const intptr_t cid
bool IsInternalOnlyClassId(intptr_t index)
Definition class_id.h:299
const char *const function_name