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

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

Issue 11613007: Include super type in interface list for cycle detection (issue 4318). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years 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/parser.h » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 // Collect superclasses that were already finalized before this run of 131 // Collect superclasses that were already finalized before this run of
132 // finalization. 132 // finalization.
133 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); 133 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids);
134 Class& cls = Class::Handle(); 134 Class& cls = Class::Handle();
135 // First resolve all superclasses. 135 // First resolve all superclasses.
136 for (intptr_t i = 0; i < class_array.Length(); i++) { 136 for (intptr_t i = 0; i < class_array.Length(); i++) {
137 cls ^= class_array.At(i); 137 cls ^= class_array.At(i);
138 if (FLAG_trace_class_finalization) { 138 if (FLAG_trace_class_finalization) {
139 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); 139 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString());
140 } 140 }
141 ResolveSuperType(cls);
142 GrowableArray<intptr_t> visited_interfaces; 141 GrowableArray<intptr_t> visited_interfaces;
143 ResolveInterfaces(cls, &visited_interfaces); 142 ResolveInterfaces(cls, &visited_interfaces); // Including super type.
144 } 143 }
145 // Finalize all classes. 144 // Finalize all classes.
146 for (intptr_t i = 0; i < class_array.Length(); i++) { 145 for (intptr_t i = 0; i < class_array.Length(); i++) {
147 cls ^= class_array.At(i); 146 cls ^= class_array.At(i);
148 FinalizeClass(cls); 147 FinalizeClass(cls);
149 } 148 }
150 if (FLAG_print_classes) { 149 if (FLAG_print_classes) {
151 for (intptr_t i = 0; i < class_array.Length(); i++) { 150 for (intptr_t i = 0; i < class_array.Length(); i++) {
152 cls ^= class_array.At(i); 151 cls ^= class_array.At(i);
153 PrintClassInformation(cls); 152 PrintClassInformation(cls);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 } else { 301 } else {
303 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); 302 LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
304 lib_prefix = unresolved_class.library_prefix(); 303 lib_prefix = unresolved_class.library_prefix();
305 ASSERT(!lib_prefix.IsNull()); 304 ASSERT(!lib_prefix.IsNull());
306 resolved_class = lib_prefix.LookupLocalClass(class_name); 305 resolved_class = lib_prefix.LookupLocalClass(class_name);
307 } 306 }
308 return resolved_class.raw(); 307 return resolved_class.raw();
309 } 308 }
310 309
311 310
312 // Resolve unresolved supertype (String -> Class).
313 void ClassFinalizer::ResolveSuperType(const Class& cls) {
314 if (cls.is_finalized()) {
315 return;
316 }
317 Type& super_type = Type::Handle(cls.super_type());
318 if (super_type.IsNull()) {
319 return;
320 }
321 // Resolve failures lead to a longjmp.
322 ResolveType(cls, super_type, kCanonicalizeWellFormed);
323 const Class& super_class = Class::Handle(super_type.type_class());
324 // If cls belongs to core lib or to core lib's implementation, restrictions
325 // about allowed interfaces are lifted.
326 if (cls.library() != Library::CoreLibrary()) {
327 // Prevent extending core implementation classes.
328 bool is_error = false;
329 switch (super_class.id()) {
330 case kNumberCid:
331 case kIntegerCid:
332 case kSmiCid:
333 case kMintCid:
334 case kBigintCid:
335 case kDoubleCid:
336 case kOneByteStringCid:
337 case kTwoByteStringCid:
338 case kExternalOneByteStringCid:
339 case kExternalTwoByteStringCid:
340 case kBoolCid:
341 case kArrayCid:
342 case kImmutableArrayCid:
343 case kGrowableObjectArrayCid:
344 case kInt8ArrayCid:
345 case kExternalInt8ArrayCid:
346 case kUint8ArrayCid:
347 case kUint8ClampedArrayCid:
348 case kExternalUint8ArrayCid:
349 case kExternalUint8ClampedArrayCid:
350 case kInt16ArrayCid:
351 case kExternalInt16ArrayCid:
352 case kUint16ArrayCid:
353 case kExternalUint16ArrayCid:
354 case kInt32ArrayCid:
355 case kExternalInt32ArrayCid:
356 case kUint32ArrayCid:
357 case kExternalUint32ArrayCid:
358 case kInt64ArrayCid:
359 case kExternalInt64ArrayCid:
360 case kUint64ArrayCid:
361 case kExternalUint64ArrayCid:
362 case kFloat32ArrayCid:
363 case kExternalFloat32ArrayCid:
364 case kFloat64ArrayCid:
365 case kExternalFloat64ArrayCid:
366 case kDartFunctionCid:
367 case kWeakPropertyCid:
368 is_error = true;
369 break;
370 default: {
371 // Special case: classes for which we don't have a known class id.
372 // TODO(regis): Why isn't comparing to kIntegerCid enough?
373 if (Type::Handle(Type::Double()).type_class() == super_class.raw() ||
374 Type::Handle(Type::IntType()).type_class() == super_class.raw() ||
375 Type::Handle(
376 Type::StringType()).type_class() == super_class.raw()) {
377 is_error = true;
378 }
379 break;
380 }
381 }
382 if (is_error) {
383 const Script& script = Script::Handle(cls.script());
384 ReportError(script, cls.token_pos(),
385 "'%s' is not allowed to extend '%s'",
386 String::Handle(cls.Name()).ToCString(),
387 String::Handle(super_class.Name()).ToCString());
388 }
389 }
390 return;
391 }
392
393
394 void ClassFinalizer::ResolveRedirectingFactoryTarget( 311 void ClassFinalizer::ResolveRedirectingFactoryTarget(
395 const Class& cls, 312 const Class& cls,
396 const Function& factory, 313 const Function& factory,
397 const GrowableObjectArray& visited_factories) { 314 const GrowableObjectArray& visited_factories) {
398 ASSERT(factory.IsRedirectingFactory()); 315 ASSERT(factory.IsRedirectingFactory());
399 316
400 // Check for redirection cycle. 317 // Check for redirection cycle.
401 for (int i = 0; i < visited_factories.Length(); i++) { 318 for (int i = 0; i < visited_factories.Length(); i++) {
402 if (visited_factories.At(i) == factory.raw()) { 319 if (visited_factories.At(i) == factory.raw()) {
403 // A redirection cycle is reported as a compile-time error. 320 // A redirection cycle is reported as a compile-time error.
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 return false; 1236 return false;
1320 } 1237 }
1321 } 1238 }
1322 } 1239 }
1323 } 1240 }
1324 visited->RemoveLast(); 1241 visited->RemoveLast();
1325 return true; 1242 return true;
1326 } 1243 }
1327 1244
1328 1245
1329 // Walks the graph of explicitly declared interfaces of classes and 1246 // Recursively walks the graph of explicitly declared super type and
1330 // interfaces recursively. Resolves unresolved interfaces. 1247 // interfaces, resolving unresolved super types and interfaces.
1331 // Returns false if there is an interface reference that cannot be 1248 // Reports an error if there is an interface reference that cannot be
1332 // resolved, or if there is a cycle in the graph. We detect cycles by 1249 // resolved, or if there is a cycle in the graph. We detect cycles by
1333 // remembering interfaces we've visited in each path through the 1250 // remembering interfaces we've visited in each path through the
1334 // graph. If we visit an interface a second time on a given path, 1251 // graph. If we visit an interface a second time on a given path,
1335 // we found a loop. 1252 // we found a loop.
1336 void ClassFinalizer::ResolveInterfaces(const Class& cls, 1253 void ClassFinalizer::ResolveInterfaces(const Class& cls,
srdjan 2012/12/18 00:06:11 rename ResolveSuperTypesAndInterfaces
regis 2012/12/18 00:12:03 Renamed to ResolveSuperTypeAndInterfaces
1337 GrowableArray<intptr_t>* visited) { 1254 GrowableArray<intptr_t>* visited) {
1338 ASSERT(visited != NULL); 1255 ASSERT(visited != NULL);
1339 const intptr_t cls_index = cls.id(); 1256 const intptr_t cls_index = cls.id();
1340 for (int i = 0; i < visited->length(); i++) { 1257 for (int i = 0; i < visited->length(); i++) {
1341 if ((*visited)[i] == cls_index) { 1258 if ((*visited)[i] == cls_index) {
1342 // We have already visited interface class 'cls'. We found a cycle. 1259 // We have already visited class 'cls'. We found a cycle.
1343 const String& interface_name = String::Handle(cls.Name()); 1260 const String& class_name = String::Handle(cls.Name());
1344 const Script& script = Script::Handle(cls.script()); 1261 const Script& script = Script::Handle(cls.script());
1345 ReportError(script, cls.token_pos(), 1262 ReportError(script, cls.token_pos(),
1346 "cyclic reference found for interface '%s'", 1263 "cyclic reference found for class '%s'",
1347 interface_name.ToCString()); 1264 class_name.ToCString());
1348 } 1265 }
1349 } 1266 }
1350 1267
1351 // If the class/interface has no explicit interfaces, we are done. 1268 // If the class/interface has no explicit super class/interfaces, we are done.
1269 Type& super_type = Type::Handle(cls.super_type());
1352 Array& super_interfaces = Array::Handle(cls.interfaces()); 1270 Array& super_interfaces = Array::Handle(cls.interfaces());
1353 if (super_interfaces.Length() == 0) { 1271 if ((super_type.IsNull() || super_type.IsObjectType()) &&
1272 (super_interfaces.Length() == 0)) {
1354 return; 1273 return;
1355 } 1274 }
1356 1275
1357 // If cls belongs to core lib or to core lib's implementation, restrictions 1276 // If cls belongs to core lib or to core lib's implementation, restrictions
1358 // about allowed interfaces are lifted. 1277 // about allowed interfaces are lifted.
1359 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); 1278 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary();
1360 1279
1361 // Resolve and check the interfaces of cls. 1280 // Resolve and check the super type and interfaces of cls.
1362 visited->Add(cls_index); 1281 visited->Add(cls_index);
1363 AbstractType& interface = AbstractType::Handle(); 1282 AbstractType& interface = AbstractType::Handle();
1364 Class& interface_class = Class::Handle(); 1283 Class& interface_class = Class::Handle();
1284
1285 // Resolve super type. Failures lead to a longjmp.
1286 ResolveType(cls, super_type, kCanonicalizeWellFormed);
1287
1288 // If cls belongs to core lib or to core lib's implementation, restrictions
1289 interface_class = super_type.type_class();
1290 // If cls belongs to core lib or to core lib's implementation, restrictions
1291 // about allowed interfaces are lifted.
1292 if (!cls_belongs_to_core_lib) {
1293 // Prevent extending core implementation classes.
1294 bool is_error = false;
1295 switch (interface_class.id()) {
1296 case kNumberCid:
1297 case kIntegerCid: // Class Integer, not int.
1298 case kSmiCid:
1299 case kMintCid:
1300 case kBigintCid:
1301 case kDoubleCid: // Class Double, not double.
1302 case kOneByteStringCid:
1303 case kTwoByteStringCid:
1304 case kExternalOneByteStringCid:
1305 case kExternalTwoByteStringCid:
1306 case kBoolCid:
1307 case kArrayCid:
1308 case kImmutableArrayCid:
1309 case kGrowableObjectArrayCid:
1310 case kInt8ArrayCid:
1311 case kExternalInt8ArrayCid:
1312 case kUint8ArrayCid:
1313 case kUint8ClampedArrayCid:
1314 case kExternalUint8ArrayCid:
1315 case kExternalUint8ClampedArrayCid:
1316 case kInt16ArrayCid:
1317 case kExternalInt16ArrayCid:
1318 case kUint16ArrayCid:
1319 case kExternalUint16ArrayCid:
1320 case kInt32ArrayCid:
1321 case kExternalInt32ArrayCid:
1322 case kUint32ArrayCid:
1323 case kExternalUint32ArrayCid:
1324 case kInt64ArrayCid:
1325 case kExternalInt64ArrayCid:
1326 case kUint64ArrayCid:
1327 case kExternalUint64ArrayCid:
1328 case kFloat32ArrayCid:
1329 case kExternalFloat32ArrayCid:
1330 case kFloat64ArrayCid:
1331 case kExternalFloat64ArrayCid:
1332 case kDartFunctionCid:
1333 case kWeakPropertyCid:
1334 is_error = true;
1335 break;
1336 default: {
1337 // Special case: classes for which we don't have a known class id.
1338 if (super_type.IsDoubleType() ||
1339 super_type.IsIntType() ||
1340 super_type.IsStringType()) {
1341 is_error = true;
1342 }
1343 break;
1344 }
1345 }
1346 if (is_error) {
1347 const Script& script = Script::Handle(cls.script());
1348 ReportError(script, cls.token_pos(),
1349 "'%s' is not allowed to extend '%s'",
1350 String::Handle(cls.Name()).ToCString(),
1351 String::Handle(interface_class.Name()).ToCString());
1352 }
1353 }
1354 // Now resolve the super interfaces of the super type.
1355 ResolveInterfaces(interface_class, visited);
1356
1357 // Resolve interfaces. Failures lead to a longjmp.
1365 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { 1358 for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
1366 interface ^= super_interfaces.At(i); 1359 interface ^= super_interfaces.At(i);
1367 ResolveType(cls, interface, kCanonicalizeWellFormed); 1360 ResolveType(cls, interface, kCanonicalizeWellFormed);
1368 if (interface.IsTypeParameter()) { 1361 if (interface.IsTypeParameter()) {
1369 const Script& script = Script::Handle(cls.script()); 1362 const Script& script = Script::Handle(cls.script());
1370 ReportError(script, cls.token_pos(), 1363 ReportError(script, cls.token_pos(),
1371 "type parameter '%s' cannot be used as interface", 1364 "type parameter '%s' cannot be used as interface",
1372 String::Handle(interface.Name()).ToCString()); 1365 String::Handle(interface.Name()).ToCString());
1373 } 1366 }
1374 interface_class = interface.type_class(); 1367 interface_class = interface.type_class();
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 void ClassFinalizer::ReportError(const char* format, ...) { 1575 void ClassFinalizer::ReportError(const char* format, ...) {
1583 va_list args; 1576 va_list args;
1584 va_start(args, format); 1577 va_start(args, format);
1585 const Error& error = Error::Handle( 1578 const Error& error = Error::Handle(
1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1579 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1587 va_end(args); 1580 va_end(args);
1588 ReportError(error); 1581 ReportError(error);
1589 } 1582 }
1590 1583
1591 } // namespace dart 1584 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698