Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/cha_test.cc ('k') | runtime/vm/class_finalizer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/class_finalizer.h" 5 #include "vm/class_finalizer.h"
6 6
7 #include "vm/flags.h" 7 #include "vm/flags.h"
8 #include "vm/hash_table.h" 8 #include "vm/hash_table.h"
9 #include "vm/heap.h" 9 #include "vm/heap.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
11 #include "vm/log.h" 11 #include "vm/log.h"
12 #include "vm/longjump.h" 12 #include "vm/longjump.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/program_visitor.h" 14 #include "vm/program_visitor.h"
15 #include "vm/runtime_entry.h" 15 #include "vm/runtime_entry.h"
16 #include "vm/symbols.h" 16 #include "vm/symbols.h"
17 #include "vm/timeline.h" 17 #include "vm/timeline.h"
18 #include "vm/type_table.h" 18 #include "vm/type_table.h"
19 19
20 namespace dart { 20 namespace dart {
21 21
22 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); 22 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
23 DEFINE_FLAG(bool, reify, true, "Reify type arguments of generic types."); 23 DEFINE_FLAG(bool, reify, true, "Reify type arguments of generic types.");
24 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); 24 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
25 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); 25 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
26 26
27
28 bool ClassFinalizer::AllClassesFinalized() { 27 bool ClassFinalizer::AllClassesFinalized() {
29 ObjectStore* object_store = Isolate::Current()->object_store(); 28 ObjectStore* object_store = Isolate::Current()->object_store();
30 const GrowableObjectArray& classes = 29 const GrowableObjectArray& classes =
31 GrowableObjectArray::Handle(object_store->pending_classes()); 30 GrowableObjectArray::Handle(object_store->pending_classes());
32 return classes.Length() == 0; 31 return classes.Length() == 0;
33 } 32 }
34 33
35
36 // Removes optimized code once we load more classes, since CHA based 34 // Removes optimized code once we load more classes, since CHA based
37 // optimizations may have become invalid. 35 // optimizations may have become invalid.
38 // Only methods which owner classes where subclasses can be invalid. 36 // Only methods which owner classes where subclasses can be invalid.
39 // TODO(srdjan): Be even more precise by recording the exact CHA optimization. 37 // TODO(srdjan): Be even more precise by recording the exact CHA optimization.
40 static void RemoveCHAOptimizedCode( 38 static void RemoveCHAOptimizedCode(
41 const Class& subclass, 39 const Class& subclass,
42 const GrowableArray<intptr_t>& added_subclass_to_cids) { 40 const GrowableArray<intptr_t>& added_subclass_to_cids) {
43 ASSERT(FLAG_use_cha_deopt); 41 ASSERT(FLAG_use_cha_deopt);
44 if (added_subclass_to_cids.is_empty()) { 42 if (added_subclass_to_cids.is_empty()) {
45 return; 43 return;
46 } 44 }
47 // Switch all functions' code to unoptimized. 45 // Switch all functions' code to unoptimized.
48 const ClassTable& class_table = *Isolate::Current()->class_table(); 46 const ClassTable& class_table = *Isolate::Current()->class_table();
49 Class& cls = Class::Handle(); 47 Class& cls = Class::Handle();
50 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) { 48 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
51 intptr_t cid = added_subclass_to_cids[i]; 49 intptr_t cid = added_subclass_to_cids[i];
52 cls = class_table.At(cid); 50 cls = class_table.At(cid);
53 ASSERT(!cls.IsNull()); 51 ASSERT(!cls.IsNull());
54 cls.DisableCHAOptimizedCode(subclass); 52 cls.DisableCHAOptimizedCode(subclass);
55 } 53 }
56 } 54 }
57 55
58
59 void AddSuperType(const AbstractType& type, 56 void AddSuperType(const AbstractType& type,
60 GrowableArray<intptr_t>* finalized_super_classes) { 57 GrowableArray<intptr_t>* finalized_super_classes) {
61 ASSERT(type.HasResolvedTypeClass()); 58 ASSERT(type.HasResolvedTypeClass());
62 ASSERT(!type.IsDynamicType()); 59 ASSERT(!type.IsDynamicType());
63 if (type.IsObjectType()) { 60 if (type.IsObjectType()) {
64 return; 61 return;
65 } 62 }
66 const Class& cls = Class::Handle(type.type_class()); 63 const Class& cls = Class::Handle(type.type_class());
67 ASSERT(cls.is_finalized()); 64 ASSERT(cls.is_finalized());
68 const intptr_t cid = cls.id(); 65 const intptr_t cid = cls.id();
69 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) { 66 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) {
70 if ((*finalized_super_classes)[i] == cid) { 67 if ((*finalized_super_classes)[i] == cid) {
71 // Already added. 68 // Already added.
72 return; 69 return;
73 } 70 }
74 } 71 }
75 finalized_super_classes->Add(cid); 72 finalized_super_classes->Add(cid);
76 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); 73 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
77 AddSuperType(super_type, finalized_super_classes); 74 AddSuperType(super_type, finalized_super_classes);
78 } 75 }
79 76
80
81 // Use array instead of set since we expect very few subclassed classes 77 // Use array instead of set since we expect very few subclassed classes
82 // to occur. 78 // to occur.
83 static void CollectFinalizedSuperClasses( 79 static void CollectFinalizedSuperClasses(
84 const Class& cls_, 80 const Class& cls_,
85 GrowableArray<intptr_t>* finalized_super_classes) { 81 GrowableArray<intptr_t>* finalized_super_classes) {
86 Class& cls = Class::Handle(cls_.raw()); 82 Class& cls = Class::Handle(cls_.raw());
87 AbstractType& super_type = Type::Handle(); 83 AbstractType& super_type = Type::Handle();
88 super_type = cls.super_type(); 84 super_type = cls.super_type();
89 if (!super_type.IsNull()) { 85 if (!super_type.IsNull()) {
90 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) { 86 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) {
91 cls ^= super_type.type_class(); 87 cls ^= super_type.type_class();
92 if (cls.is_finalized()) { 88 if (cls.is_finalized()) {
93 AddSuperType(super_type, finalized_super_classes); 89 AddSuperType(super_type, finalized_super_classes);
94 } 90 }
95 } 91 }
96 } 92 }
97 } 93 }
98 94
99
100 static void CollectImmediateSuperInterfaces(const Class& cls, 95 static void CollectImmediateSuperInterfaces(const Class& cls,
101 GrowableArray<intptr_t>* cids) { 96 GrowableArray<intptr_t>* cids) {
102 const Array& interfaces = Array::Handle(cls.interfaces()); 97 const Array& interfaces = Array::Handle(cls.interfaces());
103 Class& ifc = Class::Handle(); 98 Class& ifc = Class::Handle();
104 AbstractType& type = AbstractType::Handle(); 99 AbstractType& type = AbstractType::Handle();
105 for (intptr_t i = 0; i < interfaces.Length(); ++i) { 100 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
106 type ^= interfaces.At(i); 101 type ^= interfaces.At(i);
107 if (type.IsMalformed()) continue; 102 if (type.IsMalformed()) continue;
108 if (!type.HasResolvedTypeClass()) continue; 103 if (!type.HasResolvedTypeClass()) continue;
109 ifc ^= type.type_class(); 104 ifc ^= type.type_class();
110 for (intptr_t j = 0; j < cids->length(); ++j) { 105 for (intptr_t j = 0; j < cids->length(); ++j) {
111 if ((*cids)[j] == ifc.id()) { 106 if ((*cids)[j] == ifc.id()) {
112 // Already added. 107 // Already added.
113 return; 108 return;
114 } 109 }
115 } 110 }
116 cids->Add(ifc.id()); 111 cids->Add(ifc.id());
117 } 112 }
118 } 113 }
119 114
120
121 // Processing ObjectStore::pending_classes_ occurs: 115 // Processing ObjectStore::pending_classes_ occurs:
122 // a) when bootstrap process completes (VerifyBootstrapClasses). 116 // a) when bootstrap process completes (VerifyBootstrapClasses).
123 // b) after the user classes are loaded (dart_api). 117 // b) after the user classes are loaded (dart_api).
124 bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) { 118 bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) {
125 Thread* thread = Thread::Current(); 119 Thread* thread = Thread::Current();
126 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), 120 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(),
127 "ProcessPendingClasses")); 121 "ProcessPendingClasses"));
128 Isolate* isolate = thread->isolate(); 122 Isolate* isolate = thread->isolate();
129 ASSERT(isolate != NULL); 123 ASSERT(isolate != NULL);
130 HANDLESCOPE(thread); 124 HANDLESCOPE(thread);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 VerifyImplicitFieldOffsets(); // Verification after an error may fail. 171 VerifyImplicitFieldOffsets(); // Verification after an error may fail.
178 172
179 return true; 173 return true;
180 } else { 174 } else {
181 return false; 175 return false;
182 } 176 }
183 UNREACHABLE(); 177 UNREACHABLE();
184 return true; 178 return true;
185 } 179 }
186 180
187
188 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. 181 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur.
189 // No cycles are allowed. 182 // No cycles are allowed.
190 void ClassFinalizer::CollectInterfaces(const Class& cls, 183 void ClassFinalizer::CollectInterfaces(const Class& cls,
191 GrowableArray<const Class*>* collected) { 184 GrowableArray<const Class*>* collected) {
192 Zone* zone = Thread::Current()->zone(); 185 Zone* zone = Thread::Current()->zone();
193 const Array& interface_array = Array::Handle(zone, cls.interfaces()); 186 const Array& interface_array = Array::Handle(zone, cls.interfaces());
194 AbstractType& interface = AbstractType::Handle(zone); 187 AbstractType& interface = AbstractType::Handle(zone);
195 Class& interface_class = Class::Handle(zone); 188 Class& interface_class = Class::Handle(zone);
196 for (intptr_t i = 0; i < interface_array.Length(); i++) { 189 for (intptr_t i = 0; i < interface_array.Length(); i++) {
197 interface ^= interface_array.At(i); 190 interface ^= interface_array.At(i);
198 interface_class = interface.type_class(); 191 interface_class = interface.type_class();
199 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); 192 collected->Add(&Class::ZoneHandle(zone, interface_class.raw()));
200 CollectInterfaces(interface_class, collected); 193 CollectInterfaces(interface_class, collected);
201 } 194 }
202 } 195 }
203 196
204
205 #if !defined(DART_PRECOMPILED_RUNTIME) 197 #if !defined(DART_PRECOMPILED_RUNTIME)
206 void ClassFinalizer::VerifyBootstrapClasses() { 198 void ClassFinalizer::VerifyBootstrapClasses() {
207 if (FLAG_trace_class_finalization) { 199 if (FLAG_trace_class_finalization) {
208 OS::Print("VerifyBootstrapClasses START.\n"); 200 OS::Print("VerifyBootstrapClasses START.\n");
209 } 201 }
210 ObjectStore* object_store = Isolate::Current()->object_store(); 202 ObjectStore* object_store = Isolate::Current()->object_store();
211 203
212 Class& cls = Class::Handle(); 204 Class& cls = Class::Handle();
213 #if defined(DEBUG) 205 #if defined(DEBUG)
214 // Basic checking. 206 // Basic checking.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 err.ToErrorCString()); 255 err.ToErrorCString());
264 OS::Exit(255); 256 OS::Exit(255);
265 } 257 }
266 if (FLAG_trace_class_finalization) { 258 if (FLAG_trace_class_finalization) {
267 OS::Print("VerifyBootstrapClasses END.\n"); 259 OS::Print("VerifyBootstrapClasses END.\n");
268 } 260 }
269 Isolate::Current()->heap()->Verify(); 261 Isolate::Current()->heap()->Verify();
270 } 262 }
271 #endif // !defined(DART_PRECOMPILED_RUNTIME) 263 #endif // !defined(DART_PRECOMPILED_RUNTIME)
272 264
273
274 static bool IsLoaded(const Type& type) { 265 static bool IsLoaded(const Type& type) {
275 if (type.HasResolvedTypeClass()) { 266 if (type.HasResolvedTypeClass()) {
276 return true; 267 return true;
277 } 268 }
278 const UnresolvedClass& unresolved_class = 269 const UnresolvedClass& unresolved_class =
279 UnresolvedClass::Handle(type.unresolved_class()); 270 UnresolvedClass::Handle(type.unresolved_class());
280 const Object& prefix = 271 const Object& prefix =
281 Object::Handle(unresolved_class.library_or_library_prefix()); 272 Object::Handle(unresolved_class.library_or_library_prefix());
282 if (prefix.IsNull()) { 273 if (prefix.IsNull()) {
283 return true; 274 return true;
284 } else if (prefix.IsLibraryPrefix()) { 275 } else if (prefix.IsLibraryPrefix()) {
285 return LibraryPrefix::Cast(prefix).is_loaded(); 276 return LibraryPrefix::Cast(prefix).is_loaded();
286 } else { 277 } else {
287 return true; 278 return true;
288 } 279 }
289 } 280 }
290 281
291
292 // Resolve unresolved_class in the library of cls, or return null. 282 // Resolve unresolved_class in the library of cls, or return null.
293 RawClass* ClassFinalizer::ResolveClass( 283 RawClass* ClassFinalizer::ResolveClass(
294 const Class& cls, 284 const Class& cls,
295 const UnresolvedClass& unresolved_class) { 285 const UnresolvedClass& unresolved_class) {
296 const String& class_name = String::Handle(unresolved_class.ident()); 286 const String& class_name = String::Handle(unresolved_class.ident());
297 Library& lib = Library::Handle(); 287 Library& lib = Library::Handle();
298 Class& resolved_class = Class::Handle(); 288 Class& resolved_class = Class::Handle();
299 if (unresolved_class.library_or_library_prefix() == Object::null()) { 289 if (unresolved_class.library_or_library_prefix() == Object::null()) {
300 lib = cls.library(); 290 lib = cls.library();
301 ASSERT(!lib.IsNull()); 291 ASSERT(!lib.IsNull());
302 resolved_class = lib.LookupClass(class_name); 292 resolved_class = lib.LookupClass(class_name);
303 } else { 293 } else {
304 const Object& prefix = 294 const Object& prefix =
305 Object::Handle(unresolved_class.library_or_library_prefix()); 295 Object::Handle(unresolved_class.library_or_library_prefix());
306 296
307 if (prefix.IsLibraryPrefix()) { 297 if (prefix.IsLibraryPrefix()) {
308 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name); 298 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name);
309 } else { 299 } else {
310 resolved_class = Library::Cast(prefix).LookupClass(class_name); 300 resolved_class = Library::Cast(prefix).LookupClass(class_name);
311 } 301 }
312 } 302 }
313 return resolved_class.raw(); 303 return resolved_class.raw();
314 } 304 }
315 305
316
317 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, 306 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls,
318 const Function& factory) { 307 const Function& factory) {
319 const Function& target = Function::Handle(factory.RedirectionTarget()); 308 const Function& target = Function::Handle(factory.RedirectionTarget());
320 if (target.IsNull()) { 309 if (target.IsNull()) {
321 Type& type = Type::Handle(factory.RedirectionType()); 310 Type& type = Type::Handle(factory.RedirectionType());
322 if (!type.IsMalformed() && IsLoaded(type)) { 311 if (!type.IsMalformed() && IsLoaded(type)) {
323 const GrowableObjectArray& visited_factories = 312 const GrowableObjectArray& visited_factories =
324 GrowableObjectArray::Handle(GrowableObjectArray::New()); 313 GrowableObjectArray::Handle(GrowableObjectArray::New());
325 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); 314 ResolveRedirectingFactoryTarget(cls, factory, visited_factories);
326 } 315 }
327 if (factory.is_const()) { 316 if (factory.is_const()) {
328 type = factory.RedirectionType(); 317 type = factory.RedirectionType();
329 if (type.IsMalformedOrMalbounded()) { 318 if (type.IsMalformedOrMalbounded()) {
330 ReportError(Error::Handle(type.error())); 319 ReportError(Error::Handle(type.error()));
331 } 320 }
332 } 321 }
333 } 322 }
334 } 323 }
335 324
336
337 void ClassFinalizer::ResolveRedirectingFactoryTarget( 325 void ClassFinalizer::ResolveRedirectingFactoryTarget(
338 const Class& cls, 326 const Class& cls,
339 const Function& factory, 327 const Function& factory,
340 const GrowableObjectArray& visited_factories) { 328 const GrowableObjectArray& visited_factories) {
341 ASSERT(factory.IsRedirectingFactory()); 329 ASSERT(factory.IsRedirectingFactory());
342 330
343 // Check for redirection cycle. 331 // Check for redirection cycle.
344 for (intptr_t i = 0; i < visited_factories.Length(); i++) { 332 for (intptr_t i = 0; i < visited_factories.Length(); i++) {
345 if (visited_factories.At(i) == factory.raw()) { 333 if (visited_factories.At(i) == factory.raw()) {
346 // A redirection cycle is reported as a compile-time error. 334 // A redirection cycle is reported as a compile-time error.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 FinalizeMalformedType(bound_error, script, target_type, 463 FinalizeMalformedType(bound_error, script, target_type,
476 "cannot resolve redirecting factory"); 464 "cannot resolve redirecting factory");
477 target_target = Function::null(); 465 target_target = Function::null();
478 } 466 }
479 } 467 }
480 } 468 }
481 factory.SetRedirectionType(target_type); 469 factory.SetRedirectionType(target_type);
482 factory.SetRedirectionTarget(target_target); 470 factory.SetRedirectionTarget(target_target);
483 } 471 }
484 472
485
486 void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) { 473 void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
487 if (type.IsFinalized()) { 474 if (type.IsFinalized()) {
488 return; 475 return;
489 } 476 }
490 if (FLAG_trace_type_finalization) { 477 if (FLAG_trace_type_finalization) {
491 THR_Print("Resolve type class of '%s'\n", 478 THR_Print("Resolve type class of '%s'\n",
492 String::Handle(type.Name()).ToCString()); 479 String::Handle(type.Name()).ToCString());
493 } 480 }
494 481
495 // Type parameters are always resolved in the parser in the correct 482 // Type parameters are always resolved in the parser in the correct
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 (type.signature() != Function::null())); 516 (type.signature() != Function::null()));
530 517
531 // Replace FutureOr<T> type of async library with dynamic. 518 // Replace FutureOr<T> type of async library with dynamic.
532 if ((type_class.library() == Library::AsyncLibrary()) && 519 if ((type_class.library() == Library::AsyncLibrary()) &&
533 (type_class.Name() == Symbols::FutureOr().raw())) { 520 (type_class.Name() == Symbols::FutureOr().raw())) {
534 Type::Cast(type).set_type_class(Class::Handle(Object::dynamic_class())); 521 Type::Cast(type).set_type_class(Class::Handle(Object::dynamic_class()));
535 type.set_arguments(Object::null_type_arguments()); 522 type.set_arguments(Object::null_type_arguments());
536 } 523 }
537 } 524 }
538 525
539
540 void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) { 526 void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
541 if (type.IsResolved()) { 527 if (type.IsResolved()) {
542 return; 528 return;
543 } 529 }
544 if (FLAG_trace_type_finalization) { 530 if (FLAG_trace_type_finalization) {
545 THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); 531 THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
546 } 532 }
547 if (type.IsType()) { 533 if (type.IsType()) {
548 ResolveTypeClass(cls, Type::Cast(type)); 534 ResolveTypeClass(cls, Type::Cast(type));
549 if (type.IsMalformed()) { 535 if (type.IsMalformed()) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 if (!scope_class.IsTypedefClass()) { 592 if (!scope_class.IsTypedefClass()) {
607 signature.set_owner(Object::Handle()); 593 signature.set_owner(Object::Handle());
608 signature.set_token_pos(TokenPosition::kNoSource); 594 signature.set_token_pos(TokenPosition::kNoSource);
609 } 595 }
610 } 596 }
611 } 597 }
612 } 598 }
613 } 599 }
614 } 600 }
615 601
616
617 void ClassFinalizer::FinalizeTypeParameters(const Class& cls, 602 void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
618 PendingTypes* pending_types) { 603 PendingTypes* pending_types) {
619 if (FLAG_trace_type_finalization) { 604 if (FLAG_trace_type_finalization) {
620 THR_Print("Finalizing type parameters of '%s'\n", 605 THR_Print("Finalizing type parameters of '%s'\n",
621 String::Handle(cls.Name()).ToCString()); 606 String::Handle(cls.Name()).ToCString());
622 } 607 }
623 if (cls.IsMixinApplication()) { 608 if (cls.IsMixinApplication()) {
624 // Setup the type parameters of the mixin application and finalize the 609 // Setup the type parameters of the mixin application and finalize the
625 // mixin type. 610 // mixin type.
626 ApplyMixinType(cls, pending_types); 611 ApplyMixinType(cls, pending_types);
627 } 612 }
628 // The type parameter bounds are not finalized here. 613 // The type parameter bounds are not finalized here.
629 const TypeArguments& type_parameters = 614 const TypeArguments& type_parameters =
630 TypeArguments::Handle(cls.type_parameters()); 615 TypeArguments::Handle(cls.type_parameters());
631 if (!type_parameters.IsNull()) { 616 if (!type_parameters.IsNull()) {
632 TypeParameter& type_parameter = TypeParameter::Handle(); 617 TypeParameter& type_parameter = TypeParameter::Handle();
633 const intptr_t num_types = type_parameters.Length(); 618 const intptr_t num_types = type_parameters.Length();
634 for (intptr_t i = 0; i < num_types; i++) { 619 for (intptr_t i = 0; i < num_types; i++) {
635 type_parameter ^= type_parameters.TypeAt(i); 620 type_parameter ^= type_parameters.TypeAt(i);
636 type_parameter ^= 621 type_parameter ^=
637 FinalizeType(cls, type_parameter, kFinalize, pending_types); 622 FinalizeType(cls, type_parameter, kFinalize, pending_types);
638 type_parameters.SetTypeAt(i, type_parameter); 623 type_parameters.SetTypeAt(i, type_parameter);
639 } 624 }
640 } 625 }
641 } 626 }
642 627
643
644 // This function reports a compilation error if the recursive 'type' T being 628 // This function reports a compilation error if the recursive 'type' T being
645 // finalized is a non-contractive type, i.e. if the induced type set S of P is 629 // finalized is a non-contractive type, i.e. if the induced type set S of P is
646 // not finite, where P is the instantiation of T with its own type parameters. 630 // not finite, where P is the instantiation of T with its own type parameters.
647 // The induced type set S consists of the super types of any type in S as well 631 // The induced type set S consists of the super types of any type in S as well
648 // as the type arguments of any parameterized type in S. 632 // as the type arguments of any parameterized type in S.
649 // The Dart Language Specification does not disallow the declaration and use of 633 // The Dart Language Specification does not disallow the declaration and use of
650 // non-contractive types (this may change). They are nevertheless disallowed 634 // non-contractive types (this may change). They are nevertheless disallowed
651 // as an implementation restriction in the VM since they cause divergence. 635 // as an implementation restriction in the VM since they cause divergence.
652 // A non-contractive type can be detected by looking at the queue of types 636 // A non-contractive type can be detected by looking at the queue of types
653 // pending finalization that are mutually recursive with the checked type. 637 // pending finalization that are mutually recursive with the checked type.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 instantiated_arguments, first_type_param, num_type_params)) { 696 instantiated_arguments, first_type_param, num_type_params)) {
713 const String& type_name = String::Handle(zone, type.Name()); 697 const String& type_name = String::Handle(zone, type.Name());
714 ReportError(cls, type.token_pos(), "illegal recursive type '%s'", 698 ReportError(cls, type.token_pos(), "illegal recursive type '%s'",
715 type_name.ToCString()); 699 type_name.ToCString());
716 } 700 }
717 } 701 }
718 } 702 }
719 } 703 }
720 } 704 }
721 705
722
723 // Expand the type arguments of the given type and finalize its full type 706 // Expand the type arguments of the given type and finalize its full type
724 // argument vector. Return the number of type arguments (0 for a raw type). 707 // argument vector. Return the number of type arguments (0 for a raw type).
725 intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments( 708 intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
726 const Class& cls, 709 const Class& cls,
727 const AbstractType& type, 710 const AbstractType& type,
728 PendingTypes* pending_types) { 711 PendingTypes* pending_types) {
729 Zone* zone = Thread::Current()->zone(); 712 Zone* zone = Thread::Current()->zone();
730 // The type class does not need to be finalized in order to finalize the type, 713 // The type class does not need to be finalized in order to finalize the type,
731 // however, it must at least be resolved (this was done as part of resolving 714 // however, it must at least be resolved (this was done as part of resolving
732 // the type itself, a precondition to calling FinalizeType). 715 // the type itself, a precondition to calling FinalizeType).
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 } else { 815 } else {
833 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. 816 ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
834 } 817 }
835 } 818 }
836 819
837 ASSERT(full_arguments.IsNull() || 820 ASSERT(full_arguments.IsNull() ||
838 !full_arguments.IsRaw(0, num_type_arguments)); 821 !full_arguments.IsRaw(0, num_type_arguments));
839 return full_arguments.IsNull() ? 0 : full_arguments.Length(); 822 return full_arguments.IsNull() ? 0 : full_arguments.Length();
840 } 823 }
841 824
842
843 // Finalize the type argument vector 'arguments' of the type defined by the 825 // Finalize the type argument vector 'arguments' of the type defined by the
844 // class 'cls' parameterized with the type arguments 'cls_args'. 826 // class 'cls' parameterized with the type arguments 'cls_args'.
845 // The vector 'cls_args' is already initialized as a subvector at the correct 827 // The vector 'cls_args' is already initialized as a subvector at the correct
846 // position in the passed in 'arguments' vector. 828 // position in the passed in 'arguments' vector.
847 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at 829 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at
848 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments' 830 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments'
849 // vector. 831 // vector.
850 // The type argument vector of cls may overlap the type argument vector of its 832 // The type argument vector of cls may overlap the type argument vector of its
851 // super class. In case of an overlap, the overlapped type arguments of the 833 // super class. In case of an overlap, the overlapped type arguments of the
852 // super class are already initialized. The still uninitialized ones have an 834 // super class are already initialized. The still uninitialized ones have an
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 } 979 }
998 } 980 }
999 } 981 }
1000 arguments.SetTypeAt(i, super_type_arg); 982 arguments.SetTypeAt(i, super_type_arg);
1001 } 983 }
1002 FinalizeTypeArguments(super_class, arguments, super_offset, bound_error, 984 FinalizeTypeArguments(super_class, arguments, super_offset, bound_error,
1003 pending_types, instantiation_trail); 985 pending_types, instantiation_trail);
1004 } 986 }
1005 } 987 }
1006 988
1007
1008 // Check the type argument vector 'arguments' against the corresponding bounds 989 // Check the type argument vector 'arguments' against the corresponding bounds
1009 // of the type parameters of class 'cls' and, recursively, of its superclasses. 990 // of the type parameters of class 'cls' and, recursively, of its superclasses.
1010 // Replace a type argument that cannot be checked at compile time by a 991 // Replace a type argument that cannot be checked at compile time by a
1011 // BoundedType, thereby postponing the bound check to run time. 992 // BoundedType, thereby postponing the bound check to run time.
1012 // Return a bound error if a type argument is not within bound at compile time. 993 // Return a bound error if a type argument is not within bound at compile time.
1013 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, 994 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
1014 const TypeArguments& arguments, 995 const TypeArguments& arguments,
1015 Error* bound_error) { 996 Error* bound_error) {
1016 if (!cls.is_type_finalized()) { 997 if (!cls.is_type_finalized()) {
1017 FinalizeTypeParameters(cls); 998 FinalizeTypeParameters(cls);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 // bound check to run time, when the bound will be finalized. 1057 // bound check to run time, when the bound will be finalized.
1077 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the 1058 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the
1078 // case with a pair of type parameters of the same class referring to 1059 // case with a pair of type parameters of the same class referring to
1079 // each other via their bounds. 1060 // each other via their bounds.
1080 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); 1061 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
1081 arguments.SetTypeAt(offset + i, type_arg); 1062 arguments.SetTypeAt(offset + i, type_arg);
1082 continue; 1063 continue;
1083 } 1064 }
1084 // Shortcut the special case where we check a type parameter against its 1065 // Shortcut the special case where we check a type parameter against its
1085 // declared upper bound. 1066 // declared upper bound.
1086 if (error.IsNull() && 1067 if (error.IsNull() && !(type_arg.Equals(type_param) &&
1087 !(type_arg.Equals(type_param) && 1068 instantiated_bound.Equals(declared_bound))) {
1088 instantiated_bound.Equals(declared_bound))) {
1089 // If type_arg is a type parameter, its declared bound may not be 1069 // If type_arg is a type parameter, its declared bound may not be
1090 // finalized yet. 1070 // finalized yet.
1091 if (type_arg.IsTypeParameter()) { 1071 if (type_arg.IsTypeParameter()) {
1092 const Class& type_arg_cls = Class::Handle( 1072 const Class& type_arg_cls = Class::Handle(
1093 TypeParameter::Cast(type_arg).parameterized_class()); 1073 TypeParameter::Cast(type_arg).parameterized_class());
1094 AbstractType& bound = 1074 AbstractType& bound =
1095 AbstractType::Handle(TypeParameter::Cast(type_arg).bound()); 1075 AbstractType::Handle(TypeParameter::Cast(type_arg).bound());
1096 if (!bound.IsFinalized() && !bound.IsBeingFinalized()) { 1076 if (!bound.IsFinalized() && !bound.IsBeingFinalized()) {
1097 bound = FinalizeType(type_arg_cls, bound); 1077 bound = FinalizeType(type_arg_cls, bound);
1098 TypeParameter::Cast(type_arg).set_bound(bound); 1078 TypeParameter::Cast(type_arg).set_bound(bound);
(...skipping 14 matching lines...) Expand all
1113 } 1093 }
1114 } 1094 }
1115 } 1095 }
1116 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 1096 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1117 if (!super_type.IsNull()) { 1097 if (!super_type.IsNull()) {
1118 const Class& super_class = Class::Handle(super_type.type_class()); 1098 const Class& super_class = Class::Handle(super_type.type_class());
1119 CheckTypeArgumentBounds(super_class, arguments, bound_error); 1099 CheckTypeArgumentBounds(super_class, arguments, bound_error);
1120 } 1100 }
1121 } 1101 }
1122 1102
1123
1124 void ClassFinalizer::CheckTypeBounds(const Class& cls, 1103 void ClassFinalizer::CheckTypeBounds(const Class& cls,
1125 const AbstractType& type) { 1104 const AbstractType& type) {
1126 Zone* zone = Thread::Current()->zone(); 1105 Zone* zone = Thread::Current()->zone();
1127 ASSERT(type.IsType()); 1106 ASSERT(type.IsType());
1128 ASSERT(type.IsFinalized()); 1107 ASSERT(type.IsFinalized());
1129 ASSERT(!type.IsCanonical()); 1108 ASSERT(!type.IsCanonical());
1130 TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments()); 1109 TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
1131 if (arguments.IsNull()) { 1110 if (arguments.IsNull()) {
1132 return; 1111 return;
1133 } 1112 }
(...skipping 22 matching lines...) Expand all
1156 bound_error.ToErrorCString()); 1135 bound_error.ToErrorCString());
1157 } 1136 }
1158 } 1137 }
1159 } 1138 }
1160 if (FLAG_trace_type_finalization) { 1139 if (FLAG_trace_type_finalization) {
1161 THR_Print("Done checking bounds of type '%s': %s\n", 1140 THR_Print("Done checking bounds of type '%s': %s\n",
1162 String::Handle(zone, type.Name()).ToCString(), type.ToCString()); 1141 String::Handle(zone, type.Name()).ToCString(), type.ToCString());
1163 } 1142 }
1164 } 1143 }
1165 1144
1166
1167 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, 1145 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
1168 const AbstractType& type, 1146 const AbstractType& type,
1169 FinalizationKind finalization, 1147 FinalizationKind finalization,
1170 PendingTypes* pending_types) { 1148 PendingTypes* pending_types) {
1171 // Only the 'root' type of the graph can be canonicalized, after all depending 1149 // Only the 'root' type of the graph can be canonicalized, after all depending
1172 // types have been bound checked. 1150 // types have been bound checked.
1173 ASSERT((pending_types == NULL) || (finalization < kCanonicalize)); 1151 ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
1174 if (type.IsFinalized()) { 1152 if (type.IsFinalized()) {
1175 // Ensure type is canonical if canonicalization is requested, unless type is 1153 // Ensure type is canonical if canonicalization is requested, unless type is
1176 // malformed. 1154 // malformed.
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 THR_Print("Done canonicalizing type '%s'\n", 1320 THR_Print("Done canonicalizing type '%s'\n",
1343 String::Handle(zone, canonical_type.Name()).ToCString()); 1321 String::Handle(zone, canonical_type.Name()).ToCString());
1344 return canonical_type.raw(); 1322 return canonical_type.raw();
1345 } 1323 }
1346 return type.Canonicalize(); 1324 return type.Canonicalize();
1347 } else { 1325 } else {
1348 return type.raw(); 1326 return type.raw();
1349 } 1327 }
1350 } 1328 }
1351 1329
1352
1353 void ClassFinalizer::ResolveSignature(const Class& cls, 1330 void ClassFinalizer::ResolveSignature(const Class& cls,
1354 const Function& function) { 1331 const Function& function) {
1355 AbstractType& type = AbstractType::Handle(); 1332 AbstractType& type = AbstractType::Handle();
1356 // Resolve upper bounds of function type parameters. 1333 // Resolve upper bounds of function type parameters.
1357 const intptr_t num_type_params = function.NumTypeParameters(); 1334 const intptr_t num_type_params = function.NumTypeParameters();
1358 if (num_type_params > 0) { 1335 if (num_type_params > 0) {
1359 TypeParameter& type_param = TypeParameter::Handle(); 1336 TypeParameter& type_param = TypeParameter::Handle();
1360 const TypeArguments& type_params = 1337 const TypeArguments& type_params =
1361 TypeArguments::Handle(function.type_parameters()); 1338 TypeArguments::Handle(function.type_parameters());
1362 for (intptr_t i = 0; i < num_type_params; i++) { 1339 for (intptr_t i = 0; i < num_type_params; i++) {
1363 type_param ^= type_params.TypeAt(i); 1340 type_param ^= type_params.TypeAt(i);
1364 type = type_param.bound(); 1341 type = type_param.bound();
1365 ResolveType(cls, type); 1342 ResolveType(cls, type);
1366 } 1343 }
1367 } 1344 }
1368 // Resolve result type. 1345 // Resolve result type.
1369 type = function.result_type(); 1346 type = function.result_type();
1370 // It is not a compile time error if this name does not resolve to a class or 1347 // It is not a compile time error if this name does not resolve to a class or
1371 // interface. 1348 // interface.
1372 ResolveType(cls, type); 1349 ResolveType(cls, type);
1373 // Resolve formal parameter types. 1350 // Resolve formal parameter types.
1374 const intptr_t num_parameters = function.NumParameters(); 1351 const intptr_t num_parameters = function.NumParameters();
1375 for (intptr_t i = 0; i < num_parameters; i++) { 1352 for (intptr_t i = 0; i < num_parameters; i++) {
1376 type = function.ParameterTypeAt(i); 1353 type = function.ParameterTypeAt(i);
1377 ResolveType(cls, type); 1354 ResolveType(cls, type);
1378 } 1355 }
1379 } 1356 }
1380 1357
1381
1382 void ClassFinalizer::FinalizeSignature(const Class& cls, 1358 void ClassFinalizer::FinalizeSignature(const Class& cls,
1383 const Function& function, 1359 const Function& function,
1384 FinalizationKind finalization) { 1360 FinalizationKind finalization) {
1385 AbstractType& type = AbstractType::Handle(); 1361 AbstractType& type = AbstractType::Handle();
1386 AbstractType& finalized_type = AbstractType::Handle(); 1362 AbstractType& finalized_type = AbstractType::Handle();
1387 // Finalize function type parameters and their upper bounds. 1363 // Finalize function type parameters and their upper bounds.
1388 const intptr_t num_parent_type_params = function.NumParentTypeParameters(); 1364 const intptr_t num_parent_type_params = function.NumParentTypeParameters();
1389 const intptr_t num_type_params = function.NumTypeParameters(); 1365 const intptr_t num_type_params = function.NumTypeParameters();
1390 if (num_type_params > 0) { 1366 if (num_type_params > 0) {
1391 TypeParameter& type_param = TypeParameter::Handle(); 1367 TypeParameter& type_param = TypeParameter::Handle();
(...skipping 24 matching lines...) Expand all
1416 for (intptr_t i = 0; i < num_parameters; i++) { 1392 for (intptr_t i = 0; i < num_parameters; i++) {
1417 type = function.ParameterTypeAt(i); 1393 type = function.ParameterTypeAt(i);
1418 finalized_type = FinalizeType(cls, type, finalization); 1394 finalized_type = FinalizeType(cls, type, finalization);
1419 // The parameter type may be malformed or malbounded. 1395 // The parameter type may be malformed or malbounded.
1420 if (type.raw() != finalized_type.raw()) { 1396 if (type.raw() != finalized_type.raw()) {
1421 function.SetParameterTypeAt(i, finalized_type); 1397 function.SetParameterTypeAt(i, finalized_type);
1422 } 1398 }
1423 } 1399 }
1424 } 1400 }
1425 1401
1426
1427 // Check if an instance field, getter, or method of same name exists 1402 // Check if an instance field, getter, or method of same name exists
1428 // in any super class. 1403 // in any super class.
1429 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, 1404 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls,
1430 const String& name, 1405 const String& name,
1431 const String& getter_name) { 1406 const String& getter_name) {
1432 Class& super_class = Class::Handle(); 1407 Class& super_class = Class::Handle();
1433 Function& function = Function::Handle(); 1408 Function& function = Function::Handle();
1434 Field& field = Field::Handle(); 1409 Field& field = Field::Handle();
1435 super_class = cls.SuperClass(); 1410 super_class = cls.SuperClass();
1436 while (!super_class.IsNull()) { 1411 while (!super_class.IsNull()) {
1437 function = super_class.LookupFunction(name); 1412 function = super_class.LookupFunction(name);
1438 if (!function.IsNull() && !function.is_static()) { 1413 if (!function.IsNull() && !function.is_static()) {
1439 return super_class.raw(); 1414 return super_class.raw();
1440 } 1415 }
1441 function = super_class.LookupFunction(getter_name); 1416 function = super_class.LookupFunction(getter_name);
1442 if (!function.IsNull() && !function.is_static()) { 1417 if (!function.IsNull() && !function.is_static()) {
1443 return super_class.raw(); 1418 return super_class.raw();
1444 } 1419 }
1445 field = super_class.LookupField(name); 1420 field = super_class.LookupField(name);
1446 if (!field.IsNull() && !field.is_static()) { 1421 if (!field.IsNull() && !field.is_static()) {
1447 return super_class.raw(); 1422 return super_class.raw();
1448 } 1423 }
1449 super_class = super_class.SuperClass(); 1424 super_class = super_class.SuperClass();
1450 } 1425 }
1451 return Class::null(); 1426 return Class::null();
1452 } 1427 }
1453 1428
1454
1455 // Check if an instance method of same name exists in any super class. 1429 // Check if an instance method of same name exists in any super class.
1456 static RawClass* FindSuperOwnerOfFunction(const Class& cls, 1430 static RawClass* FindSuperOwnerOfFunction(const Class& cls,
1457 const String& name) { 1431 const String& name) {
1458 Class& super_class = Class::Handle(); 1432 Class& super_class = Class::Handle();
1459 Function& function = Function::Handle(); 1433 Function& function = Function::Handle();
1460 super_class = cls.SuperClass(); 1434 super_class = cls.SuperClass();
1461 while (!super_class.IsNull()) { 1435 while (!super_class.IsNull()) {
1462 function = super_class.LookupFunction(name); 1436 function = super_class.LookupFunction(name);
1463 if (!function.IsNull() && !function.is_static() && 1437 if (!function.IsNull() && !function.is_static() &&
1464 !function.IsMethodExtractor()) { 1438 !function.IsMethodExtractor()) {
1465 return super_class.raw(); 1439 return super_class.raw();
1466 } 1440 }
1467 super_class = super_class.SuperClass(); 1441 super_class = super_class.SuperClass();
1468 } 1442 }
1469 return Class::null(); 1443 return Class::null();
1470 } 1444 }
1471 1445
1472
1473 // Resolve the upper bounds of the type parameters of class cls. 1446 // Resolve the upper bounds of the type parameters of class cls.
1474 void ClassFinalizer::ResolveUpperBounds(const Class& cls) { 1447 void ClassFinalizer::ResolveUpperBounds(const Class& cls) {
1475 const intptr_t num_type_params = cls.NumTypeParameters(); 1448 const intptr_t num_type_params = cls.NumTypeParameters();
1476 TypeParameter& type_param = TypeParameter::Handle(); 1449 TypeParameter& type_param = TypeParameter::Handle();
1477 AbstractType& bound = AbstractType::Handle(); 1450 AbstractType& bound = AbstractType::Handle();
1478 const TypeArguments& type_params = 1451 const TypeArguments& type_params =
1479 TypeArguments::Handle(cls.type_parameters()); 1452 TypeArguments::Handle(cls.type_parameters());
1480 ASSERT((type_params.IsNull() && (num_type_params == 0)) || 1453 ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
1481 (type_params.Length() == num_type_params)); 1454 (type_params.Length() == num_type_params));
1482 // In a first pass, resolve all bounds. This guarantees that finalization 1455 // In a first pass, resolve all bounds. This guarantees that finalization
1483 // of mutually referencing bounds will not encounter an unresolved bound. 1456 // of mutually referencing bounds will not encounter an unresolved bound.
1484 for (intptr_t i = 0; i < num_type_params; i++) { 1457 for (intptr_t i = 0; i < num_type_params; i++) {
1485 type_param ^= type_params.TypeAt(i); 1458 type_param ^= type_params.TypeAt(i);
1486 bound = type_param.bound(); 1459 bound = type_param.bound();
1487 ResolveType(cls, bound); 1460 ResolveType(cls, bound);
1488 } 1461 }
1489 } 1462 }
1490 1463
1491
1492 // Finalize the upper bounds of the type parameters of class cls. 1464 // Finalize the upper bounds of the type parameters of class cls.
1493 void ClassFinalizer::FinalizeUpperBounds(const Class& cls, 1465 void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
1494 FinalizationKind finalization) { 1466 FinalizationKind finalization) {
1495 const intptr_t num_type_params = cls.NumTypeParameters(); 1467 const intptr_t num_type_params = cls.NumTypeParameters();
1496 TypeParameter& type_param = TypeParameter::Handle(); 1468 TypeParameter& type_param = TypeParameter::Handle();
1497 AbstractType& bound = AbstractType::Handle(); 1469 AbstractType& bound = AbstractType::Handle();
1498 const TypeArguments& type_params = 1470 const TypeArguments& type_params =
1499 TypeArguments::Handle(cls.type_parameters()); 1471 TypeArguments::Handle(cls.type_parameters());
1500 ASSERT((type_params.IsNull() && (num_type_params == 0)) || 1472 ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
1501 (type_params.Length() == num_type_params)); 1473 (type_params.Length() == num_type_params));
1502 for (intptr_t i = 0; i < num_type_params; i++) { 1474 for (intptr_t i = 0; i < num_type_params; i++) {
1503 type_param ^= type_params.TypeAt(i); 1475 type_param ^= type_params.TypeAt(i);
1504 bound = type_param.bound(); 1476 bound = type_param.bound();
1505 // Bound may be finalized, but not canonical yet. 1477 // Bound may be finalized, but not canonical yet.
1506 if (bound.IsCanonical() || bound.IsBeingFinalized()) { 1478 if (bound.IsCanonical() || bound.IsBeingFinalized()) {
1507 // A bound involved in F-bounded quantification may form a cycle. 1479 // A bound involved in F-bounded quantification may form a cycle.
1508 continue; 1480 continue;
1509 } 1481 }
1510 bound = FinalizeType(cls, bound, finalization); 1482 bound = FinalizeType(cls, bound, finalization);
1511 type_param.set_bound(bound); 1483 type_param.set_bound(bound);
1512 } 1484 }
1513 } 1485 }
1514 1486
1515
1516 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { 1487 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
1517 // Note that getters and setters are explicitly listed as such in the list of 1488 // Note that getters and setters are explicitly listed as such in the list of
1518 // functions of a class, so we do not need to consider fields as implicitly 1489 // functions of a class, so we do not need to consider fields as implicitly
1519 // generating getters and setters. 1490 // generating getters and setters.
1520 // Most overriding conflicts are only static warnings, i.e. they are not 1491 // Most overriding conflicts are only static warnings, i.e. they are not
1521 // reported as compile-time errors by the vm. However, signature conflicts in 1492 // reported as compile-time errors by the vm. However, signature conflicts in
1522 // overrides can be reported if the flag --error_on_bad_override is specified. 1493 // overrides can be reported if the flag --error_on_bad_override is specified.
1523 // Static warning examples are: 1494 // Static warning examples are:
1524 // - a static getter 'v' conflicting with an inherited instance setter 'v='. 1495 // - a static getter 'v' conflicting with an inherited instance setter 'v='.
1525 // - a static setter 'v=' conflicting with an inherited instance member 'v'. 1496 // - a static setter 'v=' conflicting with an inherited instance member 'v'.
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 ReportError(cls, function.token_pos(), 1736 ReportError(cls, function.token_pos(),
1766 "method '%s' of class '%s' conflicts with " 1737 "method '%s' of class '%s' conflicts with "
1767 "getter '%s' of super class '%s'", 1738 "getter '%s' of super class '%s'",
1768 name.ToCString(), class_name.ToCString(), name.ToCString(), 1739 name.ToCString(), class_name.ToCString(), name.ToCString(),
1769 super_cls_name.ToCString()); 1740 super_cls_name.ToCString());
1770 } 1741 }
1771 } 1742 }
1772 } 1743 }
1773 } 1744 }
1774 1745
1775
1776 // Clone the type parameters of the super class and of the mixin class of this 1746 // Clone the type parameters of the super class and of the mixin class of this
1777 // mixin application class and use them as the type parameters of this mixin 1747 // mixin application class and use them as the type parameters of this mixin
1778 // application class. Set the type arguments of the super type, of the mixin 1748 // application class. Set the type arguments of the super type, of the mixin
1779 // type (as well as of the interface type, which is identical to the mixin type) 1749 // type (as well as of the interface type, which is identical to the mixin type)
1780 // to refer to the respective type parameters of the mixin application class. 1750 // to refer to the respective type parameters of the mixin application class.
1781 // In other words, decorate this mixin application class with type parameters 1751 // In other words, decorate this mixin application class with type parameters
1782 // that forward to the super type and mixin type (and interface type). 1752 // that forward to the super type and mixin type (and interface type).
1783 // Example: 1753 // Example:
1784 // class S<T extends BT> { } 1754 // class S<T extends BT> { }
1785 // class M<T extends BT> { } 1755 // class M<T extends BT> { }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 } 1927 }
1958 // If the mixin class is a mixin application alias class, we insert a new 1928 // If the mixin class is a mixin application alias class, we insert a new
1959 // synthesized mixin application class in the super chain of this mixin 1929 // synthesized mixin application class in the super chain of this mixin
1960 // application class. The new class will have the aliased mixin as actual 1930 // application class. The new class will have the aliased mixin as actual
1961 // mixin. 1931 // mixin.
1962 if (mixin_class.is_mixin_app_alias()) { 1932 if (mixin_class.is_mixin_app_alias()) {
1963 ApplyMixinAppAlias(mixin_app_class, instantiator); 1933 ApplyMixinAppAlias(mixin_app_class, instantiator);
1964 } 1934 }
1965 } 1935 }
1966 1936
1967
1968 /* Support for mixin alias. 1937 /* Support for mixin alias.
1969 Consider the following example: 1938 Consider the following example:
1970 1939
1971 class I<T> { } 1940 class I<T> { }
1972 class J<T> { } 1941 class J<T> { }
1973 class S<T extends num> { } 1942 class S<T extends num> { }
1974 class M<T extends Map> { } 1943 class M<T extends Map> { }
1975 class A<U, V extends List> = Object with M<Map<U, V>> implements I<V>; 1944 class A<U, V extends List> = Object with M<Map<U, V>> implements I<V>;
1976 class C<T, K extends T> = S<T> with A<T, List<K>> implements J<K>; 1945 class C<T, K extends T> = S<T> with A<T, List<K>> implements J<K>;
1977 1946
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
2227 String::Handle(inserted_class.Name()).ToCString(), 2196 String::Handle(inserted_class.Name()).ToCString(),
2228 TypeArguments::Handle(inserted_class.type_parameters()).ToCString(), 2197 TypeArguments::Handle(inserted_class.type_parameters()).ToCString(),
2229 String::Handle(zone, super_type.Name()).ToCString(), 2198 String::Handle(zone, super_type.Name()).ToCString(),
2230 num_super_type_params + num_aliased_mixin_type_params, 2199 num_super_type_params + num_aliased_mixin_type_params,
2231 super_type.ToCString(), 2200 super_type.ToCString(),
2232 String::Handle(mixin_app_class.Name()).ToCString(), 2201 String::Handle(mixin_app_class.Name()).ToCString(),
2233 TypeArguments::Handle(mixin_app_class.type_parameters()).ToCString()); 2202 TypeArguments::Handle(mixin_app_class.type_parameters()).ToCString());
2234 } 2203 }
2235 } 2204 }
2236 2205
2237
2238 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class, 2206 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class,
2239 PendingTypes* pending_types) { 2207 PendingTypes* pending_types) {
2240 if (mixin_app_class.is_mixin_type_applied()) { 2208 if (mixin_app_class.is_mixin_type_applied()) {
2241 return; 2209 return;
2242 } 2210 }
2243 Type& mixin_type = Type::Handle(mixin_app_class.mixin()); 2211 Type& mixin_type = Type::Handle(mixin_app_class.mixin());
2244 ASSERT(!mixin_type.IsNull()); 2212 ASSERT(!mixin_type.IsNull());
2245 ASSERT(mixin_type.HasResolvedTypeClass()); 2213 ASSERT(mixin_type.HasResolvedTypeClass());
2246 const Class& mixin_class = Class::Handle(mixin_type.type_class()); 2214 const Class& mixin_class = Class::Handle(mixin_type.type_class());
2247 2215
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 ASSERT(!mixin_type.IsBeingFinalized()); 2254 ASSERT(!mixin_type.IsBeingFinalized());
2287 mixin_type ^= 2255 mixin_type ^=
2288 FinalizeType(mixin_app_class, mixin_type, kFinalize, pending_types); 2256 FinalizeType(mixin_app_class, mixin_type, kFinalize, pending_types);
2289 // The mixin type cannot be malbounded, since it merely substitutes the 2257 // The mixin type cannot be malbounded, since it merely substitutes the
2290 // type parameters of the mixin class with those of the mixin application 2258 // type parameters of the mixin class with those of the mixin application
2291 // class, but it does not instantiate them. 2259 // class, but it does not instantiate them.
2292 ASSERT(!mixin_type.IsMalbounded()); 2260 ASSERT(!mixin_type.IsMalbounded());
2293 mixin_app_class.set_mixin(mixin_type); 2261 mixin_app_class.set_mixin(mixin_type);
2294 } 2262 }
2295 2263
2296
2297 void ClassFinalizer::CreateForwardingConstructors( 2264 void ClassFinalizer::CreateForwardingConstructors(
2298 const Class& mixin_app, 2265 const Class& mixin_app,
2299 const Class& mixin_cls, 2266 const Class& mixin_cls,
2300 const GrowableObjectArray& cloned_funcs) { 2267 const GrowableObjectArray& cloned_funcs) {
2301 Thread* T = Thread::Current(); 2268 Thread* T = Thread::Current();
2302 Zone* Z = T->zone(); 2269 Zone* Z = T->zone();
2303 const String& mixin_name = String::Handle(Z, mixin_app.Name()); 2270 const String& mixin_name = String::Handle(Z, mixin_app.Name());
2304 const Class& super_class = Class::Handle(Z, mixin_app.SuperClass()); 2271 const Class& super_class = Class::Handle(Z, mixin_app.SuperClass());
2305 const String& super_name = String::Handle(Z, super_class.Name()); 2272 const String& super_name = String::Handle(Z, super_class.Name());
2306 const Array& functions = Array::Handle(Z, super_class.functions()); 2273 const Array& functions = Array::Handle(Z, super_class.functions());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 // The parameter types of the cloned constructor are 'dynamic'. 2316 // The parameter types of the cloned constructor are 'dynamic'.
2350 clone.set_parameter_types(Array::Handle(Z, Array::New(num_parameters))); 2317 clone.set_parameter_types(Array::Handle(Z, Array::New(num_parameters)));
2351 for (intptr_t n = 0; n < num_parameters; n++) { 2318 for (intptr_t n = 0; n < num_parameters; n++) {
2352 clone.SetParameterTypeAt(n, Object::dynamic_type()); 2319 clone.SetParameterTypeAt(n, Object::dynamic_type());
2353 } 2320 }
2354 cloned_funcs.Add(clone); 2321 cloned_funcs.Add(clone);
2355 } 2322 }
2356 } 2323 }
2357 } 2324 }
2358 2325
2359
2360 void ClassFinalizer::ApplyMixinMembers(const Class& cls) { 2326 void ClassFinalizer::ApplyMixinMembers(const Class& cls) {
2361 Zone* zone = Thread::Current()->zone(); 2327 Zone* zone = Thread::Current()->zone();
2362 const Type& mixin_type = Type::Handle(zone, cls.mixin()); 2328 const Type& mixin_type = Type::Handle(zone, cls.mixin());
2363 ASSERT(!mixin_type.IsNull()); 2329 ASSERT(!mixin_type.IsNull());
2364 ASSERT(mixin_type.HasResolvedTypeClass()); 2330 ASSERT(mixin_type.HasResolvedTypeClass());
2365 const Class& mixin_cls = Class::Handle(zone, mixin_type.type_class()); 2331 const Class& mixin_cls = Class::Handle(zone, mixin_type.type_class());
2366 FinalizeClass(mixin_cls); 2332 FinalizeClass(mixin_cls);
2367 // If the mixin is a mixin application alias class, there are no members to 2333 // If the mixin is a mixin application alias class, there are no members to
2368 // apply here. A new synthesized class representing the aliased mixin 2334 // apply here. A new synthesized class representing the aliased mixin
2369 // application class was inserted in the super chain of this mixin application 2335 // application class was inserted in the super chain of this mixin application
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 } 2415 }
2450 } 2416 }
2451 cls.AddFields(cloned_fields); 2417 cls.AddFields(cloned_fields);
2452 2418
2453 if (FLAG_trace_class_finalization) { 2419 if (FLAG_trace_class_finalization) {
2454 THR_Print("Done applying mixin members of %s to %s\n", 2420 THR_Print("Done applying mixin members of %s to %s\n",
2455 mixin_cls.ToCString(), cls.ToCString()); 2421 mixin_cls.ToCString(), cls.ToCString());
2456 } 2422 }
2457 } 2423 }
2458 2424
2459
2460 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { 2425 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
2461 Thread* thread = Thread::Current(); 2426 Thread* thread = Thread::Current();
2462 HANDLESCOPE(thread); 2427 HANDLESCOPE(thread);
2463 if (cls.is_type_finalized()) { 2428 if (cls.is_type_finalized()) {
2464 return; 2429 return;
2465 } 2430 }
2466 if (FLAG_trace_class_finalization) { 2431 if (FLAG_trace_class_finalization) {
2467 THR_Print("Finalize types in %s\n", cls.ToCString()); 2432 THR_Print("Finalize types in %s\n", cls.ToCString());
2468 } 2433 }
2469 if (!IsSuperCycleFree(cls)) { 2434 if (!IsSuperCycleFree(cls)) {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2608 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but 2573 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but
2609 // it causes other things to fail by violating their assumptions. Reenable 2574 // it causes other things to fail by violating their assumptions. Reenable
2610 // this ASSERT if it's important, remove it if it's just a sanity check and 2575 // this ASSERT if it's important, remove it if it's just a sanity check and
2611 // not required for correctness. 2576 // not required for correctness.
2612 // 2577 //
2613 // ASSERT((Array::Handle(cls.functions()).Length() == 0) || 2578 // ASSERT((Array::Handle(cls.functions()).Length() == 0) ||
2614 // cls.is_refinalize_after_patch()); 2579 // cls.is_refinalize_after_patch());
2615 } 2580 }
2616 } 2581 }
2617 2582
2618
2619 void ClassFinalizer::FinalizeClass(const Class& cls) { 2583 void ClassFinalizer::FinalizeClass(const Class& cls) {
2620 Thread* thread = Thread::Current(); 2584 Thread* thread = Thread::Current();
2621 HANDLESCOPE(thread); 2585 HANDLESCOPE(thread);
2622 ASSERT(cls.is_type_finalized()); 2586 ASSERT(cls.is_type_finalized());
2623 if (cls.is_finalized()) { 2587 if (cls.is_finalized()) {
2624 return; 2588 return;
2625 } 2589 }
2626 if (FLAG_trace_class_finalization) { 2590 if (FLAG_trace_class_finalization) {
2627 THR_Print("Finalize %s\n", cls.ToCString()); 2591 THR_Print("Finalize %s\n", cls.ToCString());
2628 } 2592 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2685 GrowableArray<intptr_t> cids; 2649 GrowableArray<intptr_t> cids;
2686 CollectFinalizedSuperClasses(cls, &cids); 2650 CollectFinalizedSuperClasses(cls, &cids);
2687 CollectImmediateSuperInterfaces(cls, &cids); 2651 CollectImmediateSuperInterfaces(cls, &cids);
2688 RemoveCHAOptimizedCode(cls, cids); 2652 RemoveCHAOptimizedCode(cls, cids);
2689 } 2653 }
2690 if (cls.is_enum_class()) { 2654 if (cls.is_enum_class()) {
2691 AllocateEnumValues(cls); 2655 AllocateEnumValues(cls);
2692 } 2656 }
2693 } 2657 }
2694 2658
2695
2696 // Allocate instances for each enumeration value, and populate the 2659 // Allocate instances for each enumeration value, and populate the
2697 // static field 'values'. 2660 // static field 'values'.
2698 // By allocating the instances programmatically, we save an implicit final 2661 // By allocating the instances programmatically, we save an implicit final
2699 // getter function object for each enumeration value and for the 2662 // getter function object for each enumeration value and for the
2700 // values field. We also don't have to generate the code for these getters 2663 // values field. We also don't have to generate the code for these getters
2701 // from thin air (no source code is available). 2664 // from thin air (no source code is available).
2702 void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) { 2665 void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) {
2703 Thread* thread = Thread::Current(); 2666 Thread* thread = Thread::Current();
2704 Zone* zone = thread->zone(); 2667 Zone* zone = thread->zone();
2705 const Field& index_field = 2668 const Field& index_field =
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2766 field.RecordStore(enum_value); 2729 field.RecordStore(enum_value);
2767 intptr_t ord = Smi::Cast(ordinal_value).Value(); 2730 intptr_t ord = Smi::Cast(ordinal_value).Value();
2768 ASSERT(ord < values_list.Length()); 2731 ASSERT(ord < values_list.Length());
2769 values_list.SetAt(ord, enum_value); 2732 values_list.SetAt(ord, enum_value);
2770 } 2733 }
2771 values_list.MakeImmutable(); 2734 values_list.MakeImmutable();
2772 values_list ^= values_list.CheckAndCanonicalize(thread, &error_msg); 2735 values_list ^= values_list.CheckAndCanonicalize(thread, &error_msg);
2773 ASSERT(!values_list.IsNull()); 2736 ASSERT(!values_list.IsNull());
2774 } 2737 }
2775 2738
2776
2777 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { 2739 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
2778 Class& test1 = Class::Handle(cls.raw()); 2740 Class& test1 = Class::Handle(cls.raw());
2779 Class& test2 = Class::Handle(cls.SuperClass()); 2741 Class& test2 = Class::Handle(cls.SuperClass());
2780 // A finalized class has been checked for cycles. 2742 // A finalized class has been checked for cycles.
2781 // Using the hare and tortoise algorithm for locating cycles. 2743 // Using the hare and tortoise algorithm for locating cycles.
2782 while (!test1.is_type_finalized() && !test2.IsNull() && 2744 while (!test1.is_type_finalized() && !test2.IsNull() &&
2783 !test2.is_type_finalized()) { 2745 !test2.is_type_finalized()) {
2784 if (test1.raw() == test2.raw()) { 2746 if (test1.raw() == test2.raw()) {
2785 // Found a cycle. 2747 // Found a cycle.
2786 return false; 2748 return false;
2787 } 2749 }
2788 test1 = test1.SuperClass(); 2750 test1 = test1.SuperClass();
2789 test2 = test2.SuperClass(); 2751 test2 = test2.SuperClass();
2790 if (!test2.IsNull()) { 2752 if (!test2.IsNull()) {
2791 test2 = test2.SuperClass(); 2753 test2 = test2.SuperClass();
2792 } 2754 }
2793 } 2755 }
2794 // No cycles. 2756 // No cycles.
2795 return true; 2757 return true;
2796 } 2758 }
2797 2759
2798
2799 // Returns false if a function type alias illegally refers to itself. 2760 // Returns false if a function type alias illegally refers to itself.
2800 bool ClassFinalizer::IsTypedefCycleFree(const Class& cls, 2761 bool ClassFinalizer::IsTypedefCycleFree(const Class& cls,
2801 const AbstractType& type, 2762 const AbstractType& type,
2802 GrowableArray<intptr_t>* visited) { 2763 GrowableArray<intptr_t>* visited) {
2803 ASSERT(visited != NULL); 2764 ASSERT(visited != NULL);
2804 ResolveType(cls, type); 2765 ResolveType(cls, type);
2805 bool checking_typedef = false; 2766 bool checking_typedef = false;
2806 if (type.IsType() && !type.IsMalformed()) { 2767 if (type.IsType() && !type.IsMalformed()) {
2807 AbstractType& other_type = AbstractType::Handle(); 2768 AbstractType& other_type = AbstractType::Handle();
2808 if (type.IsFunctionType()) { 2769 if (type.IsFunctionType()) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2863 } 2824 }
2864 } 2825 }
2865 } 2826 }
2866 if (checking_typedef) { 2827 if (checking_typedef) {
2867 visited->RemoveLast(); 2828 visited->RemoveLast();
2868 } 2829 }
2869 } 2830 }
2870 return true; 2831 return true;
2871 } 2832 }
2872 2833
2873
2874 // Returns false if the mixin illegally refers to itself. 2834 // Returns false if the mixin illegally refers to itself.
2875 bool ClassFinalizer::IsMixinCycleFree(const Class& cls, 2835 bool ClassFinalizer::IsMixinCycleFree(const Class& cls,
2876 GrowableArray<intptr_t>* visited) { 2836 GrowableArray<intptr_t>* visited) {
2877 ASSERT(visited != NULL); 2837 ASSERT(visited != NULL);
2878 const intptr_t cls_index = cls.id(); 2838 const intptr_t cls_index = cls.id();
2879 for (intptr_t i = 0; i < visited->length(); i++) { 2839 for (intptr_t i = 0; i < visited->length(); i++) {
2880 if ((*visited)[i] == cls_index) { 2840 if ((*visited)[i] == cls_index) {
2881 // We have already visited mixin 'cls'. We found a cycle. 2841 // We have already visited mixin 'cls'. We found a cycle.
2882 return false; 2842 return false;
2883 } 2843 }
(...skipping 11 matching lines...) Expand all
2895 if (!IsMixinCycleFree(mixin_class, visited)) { 2855 if (!IsMixinCycleFree(mixin_class, visited)) {
2896 return false; 2856 return false;
2897 } 2857 }
2898 } 2858 }
2899 super_class = super_class.SuperClass(); 2859 super_class = super_class.SuperClass();
2900 } while (!super_class.IsNull()); 2860 } while (!super_class.IsNull());
2901 visited->RemoveLast(); 2861 visited->RemoveLast();
2902 return true; 2862 return true;
2903 } 2863 }
2904 2864
2905
2906 void ClassFinalizer::CollectTypeArguments( 2865 void ClassFinalizer::CollectTypeArguments(
2907 const Class& cls, 2866 const Class& cls,
2908 const Type& type, 2867 const Type& type,
2909 const GrowableObjectArray& collected_args) { 2868 const GrowableObjectArray& collected_args) {
2910 ASSERT(type.HasResolvedTypeClass()); 2869 ASSERT(type.HasResolvedTypeClass());
2911 Class& type_class = Class::Handle(type.type_class()); 2870 Class& type_class = Class::Handle(type.type_class());
2912 TypeArguments& type_args = TypeArguments::Handle(type.arguments()); 2871 TypeArguments& type_args = TypeArguments::Handle(type.arguments());
2913 const intptr_t num_type_parameters = type_class.NumTypeParameters(); 2872 const intptr_t num_type_parameters = type_class.NumTypeParameters();
2914 const intptr_t num_type_arguments = 2873 const intptr_t num_type_arguments =
2915 type_args.IsNull() ? 0 : type_args.Length(); 2874 type_args.IsNull() ? 0 : type_args.Length();
(...skipping 16 matching lines...) Expand all
2932 } 2891 }
2933 // Discard provided type arguments and treat type as raw. 2892 // Discard provided type arguments and treat type as raw.
2934 } 2893 }
2935 // Fill arguments with type dynamic. 2894 // Fill arguments with type dynamic.
2936 for (intptr_t i = 0; i < num_type_parameters; i++) { 2895 for (intptr_t i = 0; i < num_type_parameters; i++) {
2937 arg = Type::DynamicType(); 2896 arg = Type::DynamicType();
2938 collected_args.Add(arg); 2897 collected_args.Add(arg);
2939 } 2898 }
2940 } 2899 }
2941 2900
2942
2943 RawType* ClassFinalizer::ResolveMixinAppType( 2901 RawType* ClassFinalizer::ResolveMixinAppType(
2944 const Class& cls, 2902 const Class& cls,
2945 const MixinAppType& mixin_app_type) { 2903 const MixinAppType& mixin_app_type) {
2946 // Lookup or create mixin application classes in the library of cls 2904 // Lookup or create mixin application classes in the library of cls
2947 // and resolve super type and mixin types. 2905 // and resolve super type and mixin types.
2948 Thread* thread = Thread::Current(); 2906 Thread* thread = Thread::Current();
2949 Zone* zone = thread->zone(); 2907 Zone* zone = thread->zone();
2950 const Library& library = Library::Handle(zone, cls.library()); 2908 const Library& library = Library::Handle(zone, cls.library());
2951 ASSERT(!library.IsNull()); 2909 ASSERT(!library.IsNull());
2952 const Script& script = Script::Handle(zone, cls.script()); 2910 const Script& script = Script::Handle(zone, cls.script());
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 } 3057 }
3100 // The mixin application class at depth k is a subclass of mixin application 3058 // The mixin application class at depth k is a subclass of mixin application
3101 // class at depth k - 1. Build a new super type with the class at the highest 3059 // class at depth k - 1. Build a new super type with the class at the highest
3102 // depth (the last one processed by the loop above) as the type class and the 3060 // depth (the last one processed by the loop above) as the type class and the
3103 // collected type arguments from the super type and all mixin types. 3061 // collected type arguments from the super type and all mixin types.
3104 // This super type replaces the MixinAppType object in the class that extends 3062 // This super type replaces the MixinAppType object in the class that extends
3105 // the mixin application. 3063 // the mixin application.
3106 return Type::New(mixin_app_class, mixin_app_args, mixin_app_type.token_pos()); 3064 return Type::New(mixin_app_class, mixin_app_args, mixin_app_type.token_pos());
3107 } 3065 }
3108 3066
3109
3110 // Recursively walks the graph of explicitly declared super type and 3067 // Recursively walks the graph of explicitly declared super type and
3111 // interfaces, resolving unresolved super types and interfaces. 3068 // interfaces, resolving unresolved super types and interfaces.
3112 // Reports an error if there is an interface reference that cannot be 3069 // Reports an error if there is an interface reference that cannot be
3113 // resolved, or if there is a cycle in the graph. We detect cycles by 3070 // resolved, or if there is a cycle in the graph. We detect cycles by
3114 // remembering interfaces we've visited in each path through the 3071 // remembering interfaces we've visited in each path through the
3115 // graph. If we visit an interface a second time on a given path, 3072 // graph. If we visit an interface a second time on a given path,
3116 // we found a loop. 3073 // we found a loop.
3117 void ClassFinalizer::ResolveSuperTypeAndInterfaces( 3074 void ClassFinalizer::ResolveSuperTypeAndInterfaces(
3118 const Class& cls, 3075 const Class& cls,
3119 GrowableArray<intptr_t>* visited) { 3076 GrowableArray<intptr_t>* visited) {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 } 3243 }
3287 } 3244 }
3288 interface_class.set_is_implemented(); 3245 interface_class.set_is_implemented();
3289 // Now resolve the super interfaces. 3246 // Now resolve the super interfaces.
3290 ResolveSuperTypeAndInterfaces(interface_class, visited); 3247 ResolveSuperTypeAndInterfaces(interface_class, visited);
3291 } 3248 }
3292 visited->RemoveLast(); 3249 visited->RemoveLast();
3293 cls.set_is_cycle_free(); 3250 cls.set_is_cycle_free();
3294 } 3251 }
3295 3252
3296
3297 // A class is marked as constant if it has one constant constructor. 3253 // A class is marked as constant if it has one constant constructor.
3298 // A constant class can only have final instance fields. 3254 // A constant class can only have final instance fields.
3299 // Note: we must check for cycles before checking for const properties. 3255 // Note: we must check for cycles before checking for const properties.
3300 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { 3256 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) {
3301 ASSERT(cls.is_const()); 3257 ASSERT(cls.is_const());
3302 const Array& fields_array = Array::Handle(cls.fields()); 3258 const Array& fields_array = Array::Handle(cls.fields());
3303 intptr_t len = fields_array.Length(); 3259 intptr_t len = fields_array.Length();
3304 Field& field = Field::Handle(); 3260 Field& field = Field::Handle();
3305 for (intptr_t i = 0; i < len; i++) { 3261 for (intptr_t i = 0; i < len; i++) {
3306 field ^= fields_array.At(i); 3262 field ^= fields_array.At(i);
3307 if (!field.is_static() && !field.is_final()) { 3263 if (!field.is_static() && !field.is_final()) {
3308 const String& class_name = String::Handle(cls.Name()); 3264 const String& class_name = String::Handle(cls.Name());
3309 const String& field_name = String::Handle(field.name()); 3265 const String& field_name = String::Handle(field.name());
3310 ReportError(cls, field.token_pos(), 3266 ReportError(cls, field.token_pos(),
3311 "const class '%s' has non-final field '%s'", 3267 "const class '%s' has non-final field '%s'",
3312 class_name.ToCString(), field_name.ToCString()); 3268 class_name.ToCString(), field_name.ToCString());
3313 } 3269 }
3314 } 3270 }
3315 } 3271 }
3316 3272
3317
3318 void ClassFinalizer::PrintClassInformation(const Class& cls) { 3273 void ClassFinalizer::PrintClassInformation(const Class& cls) {
3319 Thread* thread = Thread::Current(); 3274 Thread* thread = Thread::Current();
3320 HANDLESCOPE(thread); 3275 HANDLESCOPE(thread);
3321 const String& class_name = String::Handle(cls.Name()); 3276 const String& class_name = String::Handle(cls.Name());
3322 THR_Print("class '%s'", class_name.ToCString()); 3277 THR_Print("class '%s'", class_name.ToCString());
3323 const Library& library = Library::Handle(cls.library()); 3278 const Library& library = Library::Handle(cls.library());
3324 if (!library.IsNull()) { 3279 if (!library.IsNull()) {
3325 THR_Print(" library '%s%s':\n", String::Handle(library.url()).ToCString(), 3280 THR_Print(" library '%s%s':\n", String::Handle(library.url()).ToCString(),
3326 String::Handle(library.private_key()).ToCString()); 3281 String::Handle(library.private_key()).ToCString());
3327 } else { 3282 } else {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3381 if (!type.IsFinalized()) { 3336 if (!type.IsFinalized()) {
3382 type.SetIsFinalized(); 3337 type.SetIsFinalized();
3383 // Do not canonicalize malformed types, since they contain an error field. 3338 // Do not canonicalize malformed types, since they contain an error field.
3384 } else { 3339 } else {
3385 // The only case where the malformed type was already finalized is when its 3340 // The only case where the malformed type was already finalized is when its
3386 // type arguments are not within bounds. In that case, we have a prev_error. 3341 // type arguments are not within bounds. In that case, we have a prev_error.
3387 ASSERT(!prev_error.IsNull()); 3342 ASSERT(!prev_error.IsNull());
3388 } 3343 }
3389 } 3344 }
3390 3345
3391
3392 RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error, 3346 RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error,
3393 const Script& script, 3347 const Script& script,
3394 TokenPosition type_pos, 3348 TokenPosition type_pos,
3395 const char* format, 3349 const char* format,
3396 ...) { 3350 ...) {
3397 va_list args; 3351 va_list args;
3398 va_start(args, format); 3352 va_start(args, format);
3399 const UnresolvedClass& unresolved_class = 3353 const UnresolvedClass& unresolved_class =
3400 UnresolvedClass::Handle(UnresolvedClass::New(LibraryPrefix::Handle(), 3354 UnresolvedClass::Handle(UnresolvedClass::New(LibraryPrefix::Handle(),
3401 Symbols::Empty(), type_pos)); 3355 Symbols::Empty(), type_pos));
3402 const Type& type = Type::Handle( 3356 const Type& type = Type::Handle(
3403 Type::New(unresolved_class, Object::null_type_arguments(), type_pos)); 3357 Type::New(unresolved_class, Object::null_type_arguments(), type_pos));
3404 MarkTypeMalformed(prev_error, script, type, format, args); 3358 MarkTypeMalformed(prev_error, script, type, format, args);
3405 va_end(args); 3359 va_end(args);
3406 ASSERT(type.IsMalformed()); 3360 ASSERT(type.IsMalformed());
3407 ASSERT(type.IsFinalized()); 3361 ASSERT(type.IsFinalized());
3408 return type.raw(); 3362 return type.raw();
3409 } 3363 }
3410 3364
3411
3412 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, 3365 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error,
3413 const Script& script, 3366 const Script& script,
3414 const Type& type, 3367 const Type& type,
3415 const char* format, 3368 const char* format,
3416 ...) { 3369 ...) {
3417 va_list args; 3370 va_list args;
3418 va_start(args, format); 3371 va_start(args, format);
3419 MarkTypeMalformed(prev_error, script, type, format, args); 3372 MarkTypeMalformed(prev_error, script, type, format, args);
3420 va_end(args); 3373 va_end(args);
3421 } 3374 }
3422 3375
3423
3424 void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error, 3376 void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
3425 const Script& script, 3377 const Script& script,
3426 const AbstractType& type, 3378 const AbstractType& type,
3427 const char* format, 3379 const char* format,
3428 ...) { 3380 ...) {
3429 va_list args; 3381 va_list args;
3430 va_start(args, format); 3382 va_start(args, format);
3431 LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV( 3383 LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
3432 prev_error, script, type.token_pos(), Report::AtLocation, 3384 prev_error, script, type.token_pos(), Report::AtLocation,
3433 Report::kMalboundedType, Heap::kOld, format, args)); 3385 Report::kMalboundedType, Heap::kOld, format, args));
3434 va_end(args); 3386 va_end(args);
3435 if (Isolate::Current()->error_on_bad_type()) { 3387 if (Isolate::Current()->error_on_bad_type()) {
3436 ReportError(error); 3388 ReportError(error);
3437 } 3389 }
3438 type.set_error(error); 3390 type.set_error(error);
3439 if (!type.IsFinalized()) { 3391 if (!type.IsFinalized()) {
3440 type.SetIsFinalized(); 3392 type.SetIsFinalized();
3441 // Do not canonicalize malbounded types. 3393 // Do not canonicalize malbounded types.
3442 } 3394 }
3443 } 3395 }
3444 3396
3445
3446 void ClassFinalizer::ReportError(const Error& error) { 3397 void ClassFinalizer::ReportError(const Error& error) {
3447 Report::LongJump(error); 3398 Report::LongJump(error);
3448 UNREACHABLE(); 3399 UNREACHABLE();
3449 } 3400 }
3450 3401
3451
3452 void ClassFinalizer::ReportErrors(const Error& prev_error, 3402 void ClassFinalizer::ReportErrors(const Error& prev_error,
3453 const Class& cls, 3403 const Class& cls,
3454 TokenPosition token_pos, 3404 TokenPosition token_pos,
3455 const char* format, 3405 const char* format,
3456 ...) { 3406 ...) {
3457 va_list args; 3407 va_list args;
3458 va_start(args, format); 3408 va_start(args, format);
3459 const Script& script = Script::Handle(cls.script()); 3409 const Script& script = Script::Handle(cls.script());
3460 Report::LongJumpV(prev_error, script, token_pos, format, args); 3410 Report::LongJumpV(prev_error, script, token_pos, format, args);
3461 va_end(args); 3411 va_end(args);
3462 UNREACHABLE(); 3412 UNREACHABLE();
3463 } 3413 }
3464 3414
3465
3466 void ClassFinalizer::ReportError(const Class& cls, 3415 void ClassFinalizer::ReportError(const Class& cls,
3467 TokenPosition token_pos, 3416 TokenPosition token_pos,
3468 const char* format, 3417 const char* format,
3469 ...) { 3418 ...) {
3470 va_list args; 3419 va_list args;
3471 va_start(args, format); 3420 va_start(args, format);
3472 const Script& script = Script::Handle(cls.script()); 3421 const Script& script = Script::Handle(cls.script());
3473 Report::MessageV(Report::kError, script, token_pos, Report::AtLocation, 3422 Report::MessageV(Report::kError, script, token_pos, Report::AtLocation,
3474 format, args); 3423 format, args);
3475 va_end(args); 3424 va_end(args);
3476 UNREACHABLE(); 3425 UNREACHABLE();
3477 } 3426 }
3478 3427
3479
3480 void ClassFinalizer::VerifyImplicitFieldOffsets() { 3428 void ClassFinalizer::VerifyImplicitFieldOffsets() {
3481 #ifdef DEBUG 3429 #ifdef DEBUG
3482 Thread* thread = Thread::Current(); 3430 Thread* thread = Thread::Current();
3483 Isolate* isolate = thread->isolate(); 3431 Isolate* isolate = thread->isolate();
3484 Zone* zone = thread->zone(); 3432 Zone* zone = thread->zone();
3485 const ClassTable& class_table = *(isolate->class_table()); 3433 const ClassTable& class_table = *(isolate->class_table());
3486 Class& cls = Class::Handle(zone); 3434 Class& cls = Class::Handle(zone);
3487 Array& fields_array = Array::Handle(zone); 3435 Array& fields_array = Array::Handle(zone);
3488 Field& field = Field::Handle(zone); 3436 Field& field = Field::Handle(zone);
3489 String& name = String::Handle(zone); 3437 String& name = String::Handle(zone);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3543 fields_array ^= cls.fields(); 3491 fields_array ^= cls.fields();
3544 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); 3492 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
3545 field ^= fields_array.At(0); 3493 field ^= fields_array.At(0);
3546 ASSERT(field.Offset() == ByteBuffer::data_offset()); 3494 ASSERT(field.Offset() == ByteBuffer::data_offset());
3547 name ^= field.name(); 3495 name ^= field.name();
3548 expected_name ^= String::New("_data"); 3496 expected_name ^= String::New("_data");
3549 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 3497 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
3550 #endif 3498 #endif
3551 } 3499 }
3552 3500
3553
3554 void ClassFinalizer::SortClasses() { 3501 void ClassFinalizer::SortClasses() {
3555 Thread* T = Thread::Current(); 3502 Thread* T = Thread::Current();
3556 Zone* Z = T->zone(); 3503 Zone* Z = T->zone();
3557 Isolate* I = T->isolate(); 3504 Isolate* I = T->isolate();
3558 ClassTable* table = I->class_table(); 3505 ClassTable* table = I->class_table();
3559 intptr_t num_cids = table->NumCids(); 3506 intptr_t num_cids = table->NumCids();
3560 intptr_t* old_to_new_cid = new intptr_t[num_cids]; 3507 intptr_t* old_to_new_cid = new intptr_t[num_cids];
3561 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) { 3508 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
3562 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids. 3509 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
3563 } 3510 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3617 } 3564 }
3618 } 3565 }
3619 } 3566 }
3620 ASSERT(next_new_cid == num_cids); 3567 ASSERT(next_new_cid == num_cids);
3621 3568
3622 RemapClassIds(old_to_new_cid); 3569 RemapClassIds(old_to_new_cid);
3623 delete[] old_to_new_cid; 3570 delete[] old_to_new_cid;
3624 RehashTypes(); // Types use cid's as part of their hashes. 3571 RehashTypes(); // Types use cid's as part of their hashes.
3625 } 3572 }
3626 3573
3627
3628 class CidRewriteVisitor : public ObjectVisitor { 3574 class CidRewriteVisitor : public ObjectVisitor {
3629 public: 3575 public:
3630 explicit CidRewriteVisitor(intptr_t* old_to_new_cids) 3576 explicit CidRewriteVisitor(intptr_t* old_to_new_cids)
3631 : old_to_new_cids_(old_to_new_cids) {} 3577 : old_to_new_cids_(old_to_new_cids) {}
3632 3578
3633 intptr_t Map(intptr_t cid) { 3579 intptr_t Map(intptr_t cid) {
3634 ASSERT(cid != -1); 3580 ASSERT(cid != -1);
3635 return old_to_new_cids_[cid]; 3581 return old_to_new_cids_[cid];
3636 } 3582 }
3637 3583
(...skipping 24 matching lines...) Expand all
3662 // which are write-protected. 3608 // which are write-protected.
3663 obj->SetClassId(new_cid); 3609 obj->SetClassId(new_cid);
3664 } 3610 }
3665 } 3611 }
3666 } 3612 }
3667 3613
3668 private: 3614 private:
3669 intptr_t* old_to_new_cids_; 3615 intptr_t* old_to_new_cids_;
3670 }; 3616 };
3671 3617
3672
3673 void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) { 3618 void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
3674 Isolate* I = Thread::Current()->isolate(); 3619 Isolate* I = Thread::Current()->isolate();
3675 3620
3676 // Code, ICData, allocation stubs have now-invalid cids. 3621 // Code, ICData, allocation stubs have now-invalid cids.
3677 ClearAllCode(); 3622 ClearAllCode();
3678 3623
3679 { 3624 {
3680 HeapIterationScope his; 3625 HeapIterationScope his;
3681 I->set_remapping_cids(true); 3626 I->set_remapping_cids(true);
3682 3627
3683 // Update the class table. Do it before rewriting cids in headers, as the 3628 // Update the class table. Do it before rewriting cids in headers, as the
3684 // heap walkers load an object's size *after* calling the visitor. 3629 // heap walkers load an object's size *after* calling the visitor.
3685 I->class_table()->Remap(old_to_new_cid); 3630 I->class_table()->Remap(old_to_new_cid);
3686 3631
3687 // Rewrite cids in headers and cids in Classes, Fields, Types and 3632 // Rewrite cids in headers and cids in Classes, Fields, Types and
3688 // TypeParameters. 3633 // TypeParameters.
3689 { 3634 {
3690 CidRewriteVisitor visitor(old_to_new_cid); 3635 CidRewriteVisitor visitor(old_to_new_cid);
3691 I->heap()->VisitObjects(&visitor); 3636 I->heap()->VisitObjects(&visitor);
3692 } 3637 }
3693 I->set_remapping_cids(false); 3638 I->set_remapping_cids(false);
3694 } 3639 }
3695 3640
3696 #if defined(DEBUG) 3641 #if defined(DEBUG)
3697 I->class_table()->Validate(); 3642 I->class_table()->Validate();
3698 I->heap()->Verify(); 3643 I->heap()->Verify();
3699 #endif 3644 #endif
3700 } 3645 }
3701 3646
3702
3703 class ClearTypeHashVisitor : public ObjectVisitor { 3647 class ClearTypeHashVisitor : public ObjectVisitor {
3704 public: 3648 public:
3705 explicit ClearTypeHashVisitor(Zone* zone) 3649 explicit ClearTypeHashVisitor(Zone* zone)
3706 : type_param_(TypeParameter::Handle(zone)), 3650 : type_param_(TypeParameter::Handle(zone)),
3707 type_(Type::Handle(zone)), 3651 type_(Type::Handle(zone)),
3708 type_args_(TypeArguments::Handle(zone)), 3652 type_args_(TypeArguments::Handle(zone)),
3709 bounded_type_(BoundedType::Handle(zone)) {} 3653 bounded_type_(BoundedType::Handle(zone)) {}
3710 3654
3711 void VisitObject(RawObject* obj) { 3655 void VisitObject(RawObject* obj) {
3712 if (obj->IsTypeParameter()) { 3656 if (obj->IsTypeParameter()) {
(...skipping 11 matching lines...) Expand all
3724 } 3668 }
3725 } 3669 }
3726 3670
3727 private: 3671 private:
3728 TypeParameter& type_param_; 3672 TypeParameter& type_param_;
3729 Type& type_; 3673 Type& type_;
3730 TypeArguments& type_args_; 3674 TypeArguments& type_args_;
3731 BoundedType& bounded_type_; 3675 BoundedType& bounded_type_;
3732 }; 3676 };
3733 3677
3734
3735 void ClassFinalizer::RehashTypes() { 3678 void ClassFinalizer::RehashTypes() {
3736 Thread* T = Thread::Current(); 3679 Thread* T = Thread::Current();
3737 Zone* Z = T->zone(); 3680 Zone* Z = T->zone();
3738 Isolate* I = T->isolate(); 3681 Isolate* I = T->isolate();
3739 3682
3740 // Clear all cached hash values. 3683 // Clear all cached hash values.
3741 { 3684 {
3742 HeapIterationScope his; 3685 HeapIterationScope his;
3743 ClearTypeHashVisitor visitor(Z); 3686 ClearTypeHashVisitor visitor(Z);
3744 I->heap()->VisitObjects(&visitor); 3687 I->heap()->VisitObjects(&visitor);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
3791 HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld); 3734 HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld);
3792 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw()); 3735 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw());
3793 for (intptr_t i = 0; i < typeargs.Length(); i++) { 3736 for (intptr_t i = 0; i < typeargs.Length(); i++) {
3794 typearg ^= typeargs.At(i); 3737 typearg ^= typeargs.At(i);
3795 bool present = typeargs_table.Insert(typearg); 3738 bool present = typeargs_table.Insert(typearg);
3796 ASSERT(!present || typearg.IsRecursive()); 3739 ASSERT(!present || typearg.IsRecursive());
3797 } 3740 }
3798 object_store->set_canonical_type_arguments(typeargs_table.Release()); 3741 object_store->set_canonical_type_arguments(typeargs_table.Release());
3799 } 3742 }
3800 3743
3801
3802 void ClassFinalizer::ClearAllCode() { 3744 void ClassFinalizer::ClearAllCode() {
3803 class ClearCodeFunctionVisitor : public FunctionVisitor { 3745 class ClearCodeFunctionVisitor : public FunctionVisitor {
3804 void Visit(const Function& function) { 3746 void Visit(const Function& function) {
3805 function.ClearCode(); 3747 function.ClearCode();
3806 function.ClearICDataArray(); 3748 function.ClearICDataArray();
3807 } 3749 }
3808 }; 3750 };
3809 ClearCodeFunctionVisitor function_visitor; 3751 ClearCodeFunctionVisitor function_visitor;
3810 ProgramVisitor::VisitFunctions(&function_visitor); 3752 ProgramVisitor::VisitFunctions(&function_visitor);
3811 3753
3812 class ClearCodeClassVisitor : public ClassVisitor { 3754 class ClearCodeClassVisitor : public ClassVisitor {
3813 void Visit(const Class& cls) { cls.DisableAllocationStub(); } 3755 void Visit(const Class& cls) { cls.DisableAllocationStub(); }
3814 }; 3756 };
3815 ClearCodeClassVisitor class_visitor; 3757 ClearCodeClassVisitor class_visitor;
3816 ProgramVisitor::VisitClasses(&class_visitor); 3758 ProgramVisitor::VisitClasses(&class_visitor);
3817 } 3759 }
3818 3760
3819 } // namespace dart 3761 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/cha_test.cc ('k') | runtime/vm/class_finalizer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698