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

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

Issue 19030004: Stop resolving classes prematurely in the vm (issue 11023). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/mirrors_api_impl.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/heap.h" 8 #include "vm/heap.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 OS::Exit(255); 248 OS::Exit(255);
249 } 249 }
250 if (FLAG_trace_class_finalization) { 250 if (FLAG_trace_class_finalization) {
251 OS::Print("VerifyBootstrapClasses END.\n"); 251 OS::Print("VerifyBootstrapClasses END.\n");
252 } 252 }
253 Isolate::Current()->heap()->Verify(); 253 Isolate::Current()->heap()->Verify();
254 } 254 }
255 255
256 256
257 // Resolve unresolved_class in the library of cls, or return null. 257 // Resolve unresolved_class in the library of cls, or return null.
258 RawClass* ClassFinalizer::ResolveClass( 258 RawClass* ClassFinalizer::ResolveClass(const Class& cls,
259 const Class& cls, const UnresolvedClass& unresolved_class) { 259 const UnresolvedClass& unresolved_class,
260 Error* ambiguity_error) {
260 const String& class_name = String::Handle(unresolved_class.ident()); 261 const String& class_name = String::Handle(unresolved_class.ident());
261 Library& lib = Library::Handle(); 262 Library& lib = Library::Handle();
262 Class& resolved_class = Class::Handle(); 263 Class& resolved_class = Class::Handle();
263 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { 264 if (unresolved_class.library_prefix() == LibraryPrefix::null()) {
264 lib = cls.library(); 265 lib = cls.library();
265 ASSERT(!lib.IsNull()); 266 ASSERT(!lib.IsNull());
266 resolved_class = lib.LookupClass(class_name); 267 // TODO(regis): Call lib.LookupClass(class_name, ambiguity_error) instead
268 // once it takes the ambiguity_error parameter.
269
270 // First check if name is found in the local scope of the library.
271 Object& obj = Object::Handle(lib.LookupLocalObject(class_name));
272 if (!obj.IsNull() && obj.IsClass()) {
273 return Class::Cast(obj).raw();
274 }
275 // Now check if class_name is found in any imported libs.
276 String& first_lib_url = String::Handle();
277 Namespace& import = Namespace::Handle();
278 Library& import_lib = Library::Handle();
279 for (intptr_t i = 0; i < lib.num_imports(); i++) {
280 import ^= lib.ImportAt(i);
281 obj = import.Lookup(class_name);
282 if (!obj.IsNull()) {
283 import_lib = import.library();
284 if (!first_lib_url.IsNull()) {
285 // Found duplicate definition.
286 const Script& script = Script::Handle(cls.script());
287 if (first_lib_url.raw() == lib.url()) {
288 *ambiguity_error = Parser::FormatErrorMsg(
289 script, unresolved_class.token_pos(), "Error",
290 "ambiguous reference to '%s', "
291 "as library '%s' is imported multiple times",
292 class_name.ToCString(),
293 first_lib_url.ToCString());
294 } else {
295 *ambiguity_error = Parser::FormatErrorMsg(
296 script, unresolved_class.token_pos(), "Error",
297 "ambiguous reference: "
298 "'%s' is defined in library '%s' and also in '%s'",
299 class_name.ToCString(),
300 first_lib_url.ToCString(),
301 String::Handle(lib.url()).ToCString());
302 }
303 return Class::null();
304 }
305 first_lib_url = lib.url();
306 if (obj.IsClass()) {
307 resolved_class = Class::Cast(obj).raw();
308 }
309 }
310 }
267 } else { 311 } else {
268 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); 312 LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
269 lib_prefix = unresolved_class.library_prefix(); 313 lib_prefix = unresolved_class.library_prefix();
270 ASSERT(!lib_prefix.IsNull()); 314 ASSERT(!lib_prefix.IsNull());
271 resolved_class = lib_prefix.LookupLocalClass(class_name); 315 resolved_class = lib_prefix.LookupLocalClass(class_name);
272 } 316 }
273 return resolved_class.raw(); 317 return resolved_class.raw();
274 } 318 }
275 319
276 320
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 OS::Print("Resolving redirecting factory: %s\n", 354 OS::Print("Resolving redirecting factory: %s\n",
311 String::Handle(factory.name()).ToCString()); 355 String::Handle(factory.name()).ToCString());
312 } 356 }
313 ResolveType(cls, type, kCanonicalize); 357 ResolveType(cls, type, kCanonicalize);
314 type ^= FinalizeType(cls, type, kCanonicalize); 358 type ^= FinalizeType(cls, type, kCanonicalize);
315 factory.SetRedirectionType(type); 359 factory.SetRedirectionType(type);
316 if (type.IsMalformed()) { 360 if (type.IsMalformed()) {
317 ASSERT(factory.RedirectionTarget() == Function::null()); 361 ASSERT(factory.RedirectionTarget() == Function::null());
318 return; 362 return;
319 } 363 }
364 ASSERT(!type.IsTypeParameter()); // Resolved in parser.
365 if (type.IsDynamicType()) {
366 // Replace the type with a malformed type and compile a throw when called.
367 type = NewFinalizedMalformedType(
368 Error::Handle(), // No previous error.
369 cls,
370 factory.token_pos(),
371 kResolveTypeParameters, // No compile-time error.
372 "factory may not redirect to 'dynamic'");
373 factory.SetRedirectionType(type);
374 ASSERT(factory.RedirectionTarget() == Function::null());
375 return;
376 }
320 const Class& target_class = Class::Handle(type.type_class()); 377 const Class& target_class = Class::Handle(type.type_class());
321 String& target_class_name = String::Handle(target_class.Name()); 378 String& target_class_name = String::Handle(target_class.Name());
322 String& target_name = String::Handle( 379 String& target_name = String::Handle(
323 String::Concat(target_class_name, Symbols::Dot())); 380 String::Concat(target_class_name, Symbols::Dot()));
324 const String& identifier = String::Handle(factory.RedirectionIdentifier()); 381 const String& identifier = String::Handle(factory.RedirectionIdentifier());
325 if (!identifier.IsNull()) { 382 if (!identifier.IsNull()) {
326 target_name = String::Concat(target_name, identifier); 383 target_name = String::Concat(target_name, identifier);
327 } 384 }
328 385
329 // Verify that the target constructor of the redirection exists. 386 // Verify that the target constructor of the redirection exists.
330 target = target_class.LookupConstructor(target_name); 387 target = target_class.LookupConstructor(target_name);
331 if (target.IsNull()) { 388 if (target.IsNull()) {
332 target = target_class.LookupFactory(target_name); 389 target = target_class.LookupFactory(target_name);
333 } 390 }
334 if (target.IsNull()) { 391 if (target.IsNull()) {
335 const String& user_visible_target_name = 392 const String& user_visible_target_name =
336 identifier.IsNull() ? target_class_name : target_name; 393 identifier.IsNull() ? target_class_name : target_name;
337 // Replace the type with a malformed type and compile a throw when called. 394 // Replace the type with a malformed type and compile a throw when called.
338 type = NewFinalizedMalformedType( 395 type = NewFinalizedMalformedType(
339 Error::Handle(), // No previous error. 396 Error::Handle(), // No previous error.
340 cls, 397 cls,
341 factory.token_pos(), 398 factory.token_pos(),
342 kTryResolve, // No compile-time error. 399 kResolveTypeParameters, // No compile-time error.
343 "class '%s' has no constructor or factory named '%s'", 400 "class '%s' has no constructor or factory named '%s'",
344 target_class_name.ToCString(), 401 target_class_name.ToCString(),
345 user_visible_target_name.ToCString()); 402 user_visible_target_name.ToCString());
346 factory.SetRedirectionType(type); 403 factory.SetRedirectionType(type);
347 ASSERT(factory.RedirectionTarget() == Function::null()); 404 ASSERT(factory.RedirectionTarget() == Function::null());
348 return; 405 return;
349 } 406 }
350 407
351 // Verify that the target is compatible with the redirecting factory. 408 // Verify that the target is compatible with the redirecting factory.
352 if (!target.HasCompatibleParametersWith(factory)) { 409 if (!target.HasCompatibleParametersWith(factory)) {
353 type = NewFinalizedMalformedType( 410 type = NewFinalizedMalformedType(
354 Error::Handle(), // No previous error. 411 Error::Handle(), // No previous error.
355 cls, 412 cls,
356 factory.token_pos(), 413 factory.token_pos(),
357 kTryResolve, // No compile-time error. 414 kResolveTypeParameters, // No compile-time error.
358 "constructor '%s' has incompatible parameters with " 415 "constructor '%s' has incompatible parameters with "
359 "redirecting factory '%s'", 416 "redirecting factory '%s'",
360 String::Handle(target.name()).ToCString(), 417 String::Handle(target.name()).ToCString(),
361 String::Handle(factory.name()).ToCString()); 418 String::Handle(factory.name()).ToCString());
362 factory.SetRedirectionType(type); 419 factory.SetRedirectionType(type);
363 ASSERT(factory.RedirectionTarget() == Function::null()); 420 ASSERT(factory.RedirectionTarget() == Function::null());
364 return; 421 return;
365 } 422 }
366 423
367 // Verify that the target is const if the the redirecting factory is const. 424 // Verify that the target is const if the the redirecting factory is const.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 if (!type.HasResolvedTypeClass()) { 487 if (!type.HasResolvedTypeClass()) {
431 // Type parameters are always resolved in the parser in the correct 488 // Type parameters are always resolved in the parser in the correct
432 // non-static scope or factory scope. That resolution scope is unknown here. 489 // non-static scope or factory scope. That resolution scope is unknown here.
433 // Being able to resolve a type parameter from class cls here would indicate 490 // Being able to resolve a type parameter from class cls here would indicate
434 // that the type parameter appeared in a static scope. Leaving the type as 491 // that the type parameter appeared in a static scope. Leaving the type as
435 // unresolved is the correct thing to do. 492 // unresolved is the correct thing to do.
436 493
437 // Lookup the type class. 494 // Lookup the type class.
438 const UnresolvedClass& unresolved_class = 495 const UnresolvedClass& unresolved_class =
439 UnresolvedClass::Handle(type.unresolved_class()); 496 UnresolvedClass::Handle(type.unresolved_class());
497 Error& ambiguous_error = Error::Handle();
440 const Class& type_class = 498 const Class& type_class =
441 Class::Handle(ResolveClass(cls, unresolved_class)); 499 Class::Handle(ResolveClass(cls, unresolved_class, &ambiguous_error));
442 500
443 // Replace unresolved class with resolved type class. 501 // Replace unresolved class with resolved type class.
444 const Type& parameterized_type = Type::Cast(type); 502 const Type& parameterized_type = Type::Cast(type);
445 if (!type_class.IsNull()) { 503 if (!type_class.IsNull()) {
446 parameterized_type.set_type_class(type_class); 504 parameterized_type.set_type_class(type_class);
447 } else { 505 } else {
448 // The type class could not be resolved. The type is malformed. 506 // The type class could not be resolved. The type is malformed.
449 FinalizeMalformedType(Error::Handle(), // No previous error. 507 FinalizeMalformedType(ambiguous_error, // May be null.
450 cls, parameterized_type, finalization, 508 cls, parameterized_type, finalization,
451 "cannot resolve class name '%s' from '%s'", 509 "cannot resolve class name '%s' from '%s'",
452 String::Handle(unresolved_class.Name()).ToCString(), 510 String::Handle(unresolved_class.Name()).ToCString(),
453 String::Handle(cls.Name()).ToCString()); 511 String::Handle(cls.Name()).ToCString());
454 return; 512 return;
455 } 513 }
456 } 514 }
457 515
458 // Resolve type arguments, if any. 516 // Resolve type arguments, if any.
459 const AbstractTypeArguments& arguments = 517 const AbstractTypeArguments& arguments =
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 // function type to refer to itself via its parameter types and result type. 921 // function type to refer to itself via its parameter types and result type.
864 if (type_class.IsSignatureClass()) { 922 if (type_class.IsSignatureClass()) {
865 // The class may be created while parsing a function body, after all 923 // The class may be created while parsing a function body, after all
866 // pending classes have already been finalized. 924 // pending classes have already been finalized.
867 FinalizeTypesInClass(type_class); 925 FinalizeTypesInClass(type_class);
868 } 926 }
869 927
870 // If a bound error occurred, return a BoundedType with a malformed bound. 928 // If a bound error occurred, return a BoundedType with a malformed bound.
871 // The malformed bound will be ignored in production mode. 929 // The malformed bound will be ignored in production mode.
872 if (!bound_error.IsNull()) { 930 if (!bound_error.IsNull()) {
873 FinalizationKind bound_finalization = kTryResolve; // No compile error. 931 // No compile-time error during finalization.
932 FinalizationKind bound_finalization = kResolveTypeParameters;
874 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { 933 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
875 bound_finalization = finalization; 934 bound_finalization = finalization;
876 } 935 }
877 const String& parameterized_type_name = String::Handle( 936 const String& parameterized_type_name = String::Handle(
878 parameterized_type.UserVisibleName()); 937 parameterized_type.UserVisibleName());
879 const Type& malformed_bound = Type::Handle( 938 const Type& malformed_bound = Type::Handle(
880 NewFinalizedMalformedType(bound_error, 939 NewFinalizedMalformedType(bound_error,
881 cls, 940 cls,
882 parameterized_type.token_pos(), 941 parameterized_type.token_pos(),
883 bound_finalization, 942 bound_finalization,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 const Script& script = Script::Handle(cls.script()); 1114 const Script& script = Script::Handle(cls.script());
1056 ReportError(script, field.token_pos(), 1115 ReportError(script, field.token_pos(),
1057 "field '%s' of class '%s' conflicts with method '%s' " 1116 "field '%s' of class '%s' conflicts with method '%s' "
1058 "of super class '%s'", 1117 "of super class '%s'",
1059 name.ToCString(), 1118 name.ToCString(),
1060 class_name.ToCString(), 1119 class_name.ToCString(),
1061 name.ToCString(), 1120 name.ToCString(),
1062 super_class_name.ToCString()); 1121 super_class_name.ToCString());
1063 } 1122 }
1064 } 1123 }
1124 if ((FLAG_enable_type_checks || FLAG_error_on_malformed_type) &&
1125 field.is_static() && field.is_const() &&
1126 (field.value() != Object::null()) &&
1127 (field.value() != Object::sentinel().raw())) {
1128 // The parser does not preset the value if the type is a type parameter or
1129 // is parameterized unless the value is null.
1130 Error& malformed_error = Error::Handle();
1131 if (type.IsMalformed()) {
1132 malformed_error = type.malformed_error();
1133 } else {
1134 ASSERT(type.IsInstantiated());
1135 }
1136 const Instance& const_value = Instance::Handle(field.value());
1137 if (!malformed_error.IsNull() ||
1138 (!type.IsDynamicType() &&
1139 !const_value.IsInstanceOf(type,
1140 AbstractTypeArguments::Handle(),
1141 &malformed_error))) {
1142 // If the failure is due to a malformed type error, display it instead.
1143 if (!malformed_error.IsNull()) {
1144 ReportError(malformed_error);
1145 } else {
1146 const AbstractType& const_value_type = AbstractType::Handle(
1147 const_value.GetType());
1148 const String& const_value_type_name = String::Handle(
1149 const_value_type.UserVisibleName());
1150 const String& type_name = String::Handle(type.UserVisibleName());
1151 const Script& script = Script::Handle(cls.script());
1152 ReportError(script, field.token_pos(),
1153 "error initializing const field '%s': type '%s' is not a "
1154 "subtype of type '%s'",
1155 name.ToCString(),
1156 const_value_type_name.ToCString(),
1157 type_name.ToCString());
1158 }
1159 }
1160 }
1065 } 1161 }
1066 // Collect interfaces, super interfaces, and super classes of this class. 1162 // Collect interfaces, super interfaces, and super classes of this class.
1067 const GrowableObjectArray& interfaces = 1163 const GrowableObjectArray& interfaces =
1068 GrowableObjectArray::Handle(GrowableObjectArray::New()); 1164 GrowableObjectArray::Handle(GrowableObjectArray::New());
1069 CollectInterfaces(cls, interfaces); 1165 CollectInterfaces(cls, interfaces);
1070 // Include superclasses in list of interfaces and super interfaces. 1166 // Include superclasses in list of interfaces and super interfaces.
1071 super_class = cls.SuperClass(); 1167 super_class = cls.SuperClass();
1072 while (!super_class.IsNull()) { 1168 while (!super_class.IsNull()) {
1073 interfaces.Add(super_class); 1169 interfaces.Add(super_class);
1074 CollectInterfaces(super_class, interfaces); 1170 CollectInterfaces(super_class, interfaces);
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 // are lifted. 1798 // are lifted.
1703 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); 1799 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary();
1704 1800
1705 // Resolve and check the super type and interfaces of cls. 1801 // Resolve and check the super type and interfaces of cls.
1706 visited->Add(cls_index); 1802 visited->Add(cls_index);
1707 AbstractType& interface = AbstractType::Handle(); 1803 AbstractType& interface = AbstractType::Handle();
1708 Class& interface_class = Class::Handle(); 1804 Class& interface_class = Class::Handle();
1709 1805
1710 // Resolve super type. Failures lead to a longjmp. 1806 // Resolve super type. Failures lead to a longjmp.
1711 ResolveType(cls, super_type, kCanonicalizeWellFormed); 1807 ResolveType(cls, super_type, kCanonicalizeWellFormed);
1808 if (super_type.IsDynamicType()) {
1809 const Script& script = Script::Handle(cls.script());
1810 ReportError(script, cls.token_pos(),
1811 "class '%s' may not extend 'dynamic'",
1812 String::Handle(cls.Name()).ToCString());
1813 }
1712 1814
1713 interface_class = super_type.type_class(); 1815 interface_class = super_type.type_class();
1714 // If cls belongs to core lib or to core lib's implementation, restrictions 1816 // If cls belongs to core lib or to core lib's implementation, restrictions
1715 // about allowed interfaces are lifted. 1817 // about allowed interfaces are lifted.
1716 if (!cls_belongs_to_core_lib) { 1818 if (!cls_belongs_to_core_lib) {
1717 // Prevent extending core implementation classes. 1819 // Prevent extending core implementation classes.
1718 bool is_error = false; 1820 bool is_error = false;
1719 switch (interface_class.id()) { 1821 switch (interface_class.id()) {
1720 case kNumberCid: 1822 case kNumberCid:
1721 case kIntegerCid: // Class Integer, not int. 1823 case kIntegerCid: // Class Integer, not int.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 String::Handle(interface_class.Name()).ToCString()); 1862 String::Handle(interface_class.Name()).ToCString());
1761 } 1863 }
1762 } 1864 }
1763 // Now resolve the super interfaces of the super type. 1865 // Now resolve the super interfaces of the super type.
1764 ResolveSuperTypeAndInterfaces(interface_class, visited); 1866 ResolveSuperTypeAndInterfaces(interface_class, visited);
1765 1867
1766 // Resolve interfaces. Failures lead to a longjmp. 1868 // Resolve interfaces. Failures lead to a longjmp.
1767 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { 1869 for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
1768 interface ^= super_interfaces.At(i); 1870 interface ^= super_interfaces.At(i);
1769 ResolveType(cls, interface, kCanonicalizeWellFormed); 1871 ResolveType(cls, interface, kCanonicalizeWellFormed);
1770 if (interface.IsTypeParameter()) { 1872 ASSERT(!interface.IsTypeParameter()); // Should be detected by parser.
1873 if (interface.IsDynamicType()) {
1771 const Script& script = Script::Handle(cls.script()); 1874 const Script& script = Script::Handle(cls.script());
1772 ReportError(script, cls.token_pos(), 1875 ReportError(script, cls.token_pos(),
1773 "type parameter '%s' cannot be used as interface", 1876 "'dynamic' may not be used as interface");
1774 String::Handle(interface.Name()).ToCString());
1775 } 1877 }
1776 interface_class = interface.type_class(); 1878 interface_class = interface.type_class();
1777 if (interface_class.IsSignatureClass()) { 1879 if (interface_class.IsSignatureClass()) {
1778 const Script& script = Script::Handle(cls.script()); 1880 const Script& script = Script::Handle(cls.script());
1779 ReportError(script, cls.token_pos(), 1881 ReportError(script, cls.token_pos(),
1780 "'%s' is used where an interface or class name is expected", 1882 "'%s' is used where an interface or class name is expected",
1781 String::Handle(interface_class.Name()).ToCString()); 1883 String::Handle(interface_class.Name()).ToCString());
1782 } 1884 }
1783 // Verify that unless cls belongs to core lib, it cannot extend or implement 1885 // Verify that unless cls belongs to core lib, it cannot extend or implement
1784 // any of bool, num, int, double, String, Function, dynamic. 1886 // any of bool, num, int, double, String, Function, dynamic.
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
2035 expected_name ^= String::New("_offset"); 2137 expected_name ^= String::New("_offset");
2036 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 2138 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
2037 field ^= fields_array.At(2); 2139 field ^= fields_array.At(2);
2038 ASSERT(field.Offset() == TypedDataView::length_offset()); 2140 ASSERT(field.Offset() == TypedDataView::length_offset());
2039 name ^= field.name(); 2141 name ^= field.name();
2040 ASSERT(name.Equals("length")); 2142 ASSERT(name.Equals("length"));
2041 #endif 2143 #endif
2042 } 2144 }
2043 2145
2044 } // namespace dart 2146 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/mirrors_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698