Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 library kernel.incremental_class_hierarchy; | 4 library kernel.incremental_class_hierarchy; |
| 5 | 5 |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 | 8 |
| 9 import 'package:kernel/ast.dart'; | 9 import 'package:kernel/ast.dart'; |
| 10 import 'package:kernel/class_hierarchy.dart'; | 10 import 'package:kernel/class_hierarchy.dart'; |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 | 208 |
| 209 @override | 209 @override |
| 210 Member getDispatchTarget(Class node, Name name, {bool setter: false}) { | 210 Member getDispatchTarget(Class node, Name name, {bool setter: false}) { |
| 211 _ClassInfo info = _getInfo(node); | 211 _ClassInfo info = _getInfo(node); |
| 212 List<Member> targets = | 212 List<Member> targets = |
| 213 setter ? info.implementedSetters : info.implementedGettersAndCalls; | 213 setter ? info.implementedSetters : info.implementedGettersAndCalls; |
| 214 return _findMemberByName(targets, name); | 214 return _findMemberByName(targets, name); |
| 215 } | 215 } |
| 216 | 216 |
| 217 @override | 217 @override |
| 218 Member getInterfaceMember(Class class_, Name name, {bool setter: false}) { | 218 Member getInterfaceMember(Class node, Name name, {bool setter: false}) { |
| 219 // TODO(scheglov): implement getInterfaceMember | 219 _ClassInfo info = _getInfo(node); |
| 220 throw new UnimplementedError(); | 220 List<Member> members = |
| 221 setter ? info.interfaceSetters : info.interfaceGettersAndCalls; | |
| 222 return _findMemberByName(members, name); | |
| 221 } | 223 } |
| 222 | 224 |
| 223 @override | 225 @override |
| 224 List<Class> getRankedSuperclasses(Class node) { | 226 List<Class> getRankedSuperclasses(Class node) { |
| 225 var info = _getInfo(node); | 227 var info = _getInfo(node); |
| 226 return _getRankedSuperclassList(info).map((info) => info.node).toList(); | 228 return _getRankedSuperclassList(info).map((info) => info.node).toList(); |
| 227 } | 229 } |
| 228 | 230 |
| 229 @override | 231 @override |
| 230 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { | 232 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { |
| 231 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); | 233 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); |
| 232 if (castedType == null) return null; | 234 if (castedType == null) return null; |
| 233 return Substitution | 235 return Substitution |
| 234 .fromInterfaceType(type) | 236 .fromInterfaceType(type) |
| 235 .substituteType(castedType.asInterfaceType); | 237 .substituteType(castedType.asInterfaceType); |
| 236 } | 238 } |
| 237 | 239 |
| 238 @override | 240 @override |
| 239 bool hasProperSubtypes(Class class_) { | 241 bool hasProperSubtypes(Class class_) { |
| 240 // TODO(scheglov): implement hasProperSubtypes | 242 // TODO(scheglov): implement hasProperSubtypes |
| 241 throw new UnimplementedError(); | 243 throw new UnimplementedError(); |
| 242 } | 244 } |
| 243 | 245 |
| 244 /// Fill the given [info] with declared methods and setters. | 246 /// Fill the given [info] with declared instance methods and setters. |
| 245 void _buildDeclaredMembers(_ClassInfo info) { | 247 void _buildDeclaredMembers(_ClassInfo info) { |
| 246 Class node = info.node; | 248 Class node = info.node; |
| 247 if (node.mixedInType != null) { | 249 if (node.mixedInType != null) { |
| 248 _ClassInfo mixedInfo = _getInfo(node.mixedInType.classNode); | 250 _ClassInfo mixedInfo = _getInfo(node.mixedInType.classNode); |
| 249 info.declaredGettersAndCalls = mixedInfo.declaredGettersAndCalls; | 251 info.declaredGettersAndCalls = mixedInfo.declaredGettersAndCalls; |
| 250 info.declaredSetters = mixedInfo.declaredSetters; | 252 info.declaredSetters = mixedInfo.declaredSetters; |
| 251 } else { | 253 } else { |
| 252 var members = info.declaredGettersAndCalls = <Member>[]; | 254 var members = info.declaredGettersAndCalls = <Member>[]; |
| 253 var setters = info.declaredSetters = <Member>[]; | 255 var setters = info.declaredSetters = <Member>[]; |
| 254 for (Procedure procedure in node.procedures) { | 256 for (Procedure procedure in node.procedures) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 inheritedSetters = superInfo.implementedSetters; | 288 inheritedSetters = superInfo.implementedSetters; |
| 287 } | 289 } |
| 288 info.implementedGettersAndCalls = _inheritMembers( | 290 info.implementedGettersAndCalls = _inheritMembers( |
| 289 info.declaredGettersAndCalls, inheritedMembers, | 291 info.declaredGettersAndCalls, inheritedMembers, |
| 290 skipAbstractMembers: true); | 292 skipAbstractMembers: true); |
| 291 info.implementedSetters = _inheritMembers( | 293 info.implementedSetters = _inheritMembers( |
| 292 info.declaredSetters, inheritedSetters, | 294 info.declaredSetters, inheritedSetters, |
| 293 skipAbstractMembers: true); | 295 skipAbstractMembers: true); |
| 294 } | 296 } |
| 295 | 297 |
| 298 /// Build interface methods or setters for the class described by [info]. | |
| 299 void _buildInterfaceMembers(_ClassInfo info) { | |
| 300 List<Member> declaredGetters = info.declaredGettersAndCalls; | |
| 301 List<Member> declaredSetters = info.declaredSetters; | |
| 302 List<Member> allInheritedGetters = <Member>[]; | |
| 303 List<Member> allInheritedSetters = <Member>[]; | |
| 304 | |
| 305 void inheritFrom(Supertype type) { | |
| 306 if (type == null) return; | |
| 307 var info = _getInfo(type.classNode); | |
| 308 // TODO(scheglov): Can we optimize this with yield? | |
| 309 | |
| 310 var inheritedGetters = _getUnshadowedInheritedMembers( | |
| 311 declaredGetters, info.interfaceGettersAndCalls); | |
| 312 allInheritedGetters = _merge(allInheritedGetters, inheritedGetters); | |
| 313 | |
| 314 var inheritedSetters = _getUnshadowedInheritedMembers( | |
| 315 declaredSetters, info.interfaceSetters); | |
| 316 allInheritedSetters = _merge(allInheritedSetters, inheritedSetters); | |
| 317 } | |
| 318 | |
| 319 Class node = info.node; | |
| 320 inheritFrom(node.supertype); | |
| 321 inheritFrom(node.mixedInType); | |
| 322 node.implementedTypes.forEach(inheritFrom); | |
| 323 | |
| 324 info.interfaceGettersAndCalls = | |
| 325 _inheritMembers(declaredGetters, allInheritedGetters); | |
| 326 info.interfaceSetters = | |
| 327 _inheritMembers(declaredSetters, allInheritedSetters); | |
| 328 } | |
| 329 | |
| 296 /// Return the [_ClassInfo] for the [node]. | 330 /// Return the [_ClassInfo] for the [node]. |
| 297 _ClassInfo _getInfo(Class node) { | 331 _ClassInfo _getInfo(Class node) { |
| 298 var info = _info[node]; | 332 var info = _info[node]; |
| 299 if (info == null) { | 333 if (info == null) { |
| 300 info = new _ClassInfo(_nextId++, node); | 334 info = new _ClassInfo(_nextId++, node); |
| 301 _info[node] = info; | 335 _info[node] = info; |
| 302 | 336 |
| 303 void addSupertypeIdentifiers(_ClassInfo superInfo) { | 337 void addSupertypeIdentifiers(_ClassInfo superInfo) { |
| 304 info.supertypeIdSet.add(superInfo.id); | 338 info.supertypeIdSet.add(superInfo.id); |
| 305 info.supertypeIdSet.addAll(superInfo.supertypeIdSet); | 339 info.supertypeIdSet.addAll(superInfo.supertypeIdSet); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 321 for (var implementedType in node.implementedTypes) { | 355 for (var implementedType in node.implementedTypes) { |
| 322 var implementedInfo = _getInfo(implementedType.classNode); | 356 var implementedInfo = _getInfo(implementedType.classNode); |
| 323 superDepth = max(superDepth, implementedInfo.depth); | 357 superDepth = max(superDepth, implementedInfo.depth); |
| 324 addSupertypeIdentifiers(implementedInfo); | 358 addSupertypeIdentifiers(implementedInfo); |
| 325 _recordSuperTypes(info, implementedType, implementedInfo); | 359 _recordSuperTypes(info, implementedType, implementedInfo); |
| 326 } | 360 } |
| 327 info.depth = superDepth + 1; | 361 info.depth = superDepth + 1; |
| 328 | 362 |
| 329 _buildDeclaredMembers(info); | 363 _buildDeclaredMembers(info); |
| 330 _buildImplementedMembers(info); | 364 _buildImplementedMembers(info); |
| 365 _buildInterfaceMembers(info); | |
| 331 } | 366 } |
| 332 return info; | 367 return info; |
| 333 } | 368 } |
| 334 | 369 |
| 335 List<_ClassInfo> _getRankedSuperclassList(_ClassInfo info) { | 370 List<_ClassInfo> _getRankedSuperclassList(_ClassInfo info) { |
| 336 if (info.rankedSuperclassList != null) { | 371 if (info.rankedSuperclassList != null) { |
| 337 return info.rankedSuperclassList; | 372 return info.rankedSuperclassList; |
| 338 } | 373 } |
| 339 | 374 |
| 340 var heap = new _LubHeap()..add(info); | 375 var heap = new _LubHeap()..add(info); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 391 var substitution = Substitution.fromPairs( | 426 var substitution = Substitution.fromPairs( |
| 392 superclass.typeParameters, supertype.typeArguments); | 427 superclass.typeParameters, supertype.typeArguments); |
| 393 subInfo.genericSuperTypes ??= <Class, Supertype>{}; | 428 subInfo.genericSuperTypes ??= <Class, Supertype>{}; |
| 394 superInfo.genericSuperTypes?.forEach((Class key, Supertype type) { | 429 superInfo.genericSuperTypes?.forEach((Class key, Supertype type) { |
| 395 subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type); | 430 subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type); |
| 396 }); | 431 }); |
| 397 subInfo.genericSuperTypes[superclass] = supertype; | 432 subInfo.genericSuperTypes[superclass] = supertype; |
| 398 } | 433 } |
| 399 } | 434 } |
| 400 | 435 |
| 436 /// Returns the subset of members in [inherited] for which a member with the | |
| 437 /// same name does not occur in [declared]. | |
| 438 /// | |
| 439 /// The input lists must be sorted, and the returned list is sorted. | |
| 440 static List<Member> _getUnshadowedInheritedMembers( | |
| 441 List<Member> declared, List<Member> inherited) { | |
| 442 List<Member> result = <Member>[]..length = inherited.length; | |
|
Paul Berry
2017/06/03 13:27:34
Creating the list and then setting its length as t
scheglov
2017/06/04 00:47:47
Done.
| |
| 443 int storeIndex = 0; | |
| 444 int i = 0, j = 0; | |
| 445 while (i < declared.length && j < inherited.length) { | |
| 446 Member declaredMember = declared[i]; | |
| 447 Member inheritedMember = inherited[j]; | |
| 448 int comparison = _compareMembers(declaredMember, inheritedMember); | |
| 449 if (comparison < 0) { | |
| 450 ++i; | |
| 451 } else if (comparison > 0) { | |
| 452 result[storeIndex++] = inheritedMember; | |
| 453 ++j; | |
| 454 } else { | |
| 455 // Move past the shadowed member, but retain the declared member, as | |
| 456 // it may shadow multiple members. | |
| 457 ++j; | |
| 458 } | |
| 459 } | |
| 460 // If the list of declared members is exhausted, copy over the remains of | |
| 461 // the inherited members. | |
| 462 while (j < inherited.length) { | |
| 463 result[storeIndex++] = inherited[j++]; | |
| 464 } | |
| 465 result.length = storeIndex; | |
| 466 return result; | |
| 467 } | |
| 468 | |
| 401 /// Computes the list of implemented members, based on the declared instance | 469 /// Computes the list of implemented members, based on the declared instance |
| 402 /// members and inherited instance members. | 470 /// members and inherited instance members. |
| 403 /// | 471 /// |
| 404 /// Both lists must be sorted by name beforehand. | 472 /// Both lists must be sorted by name beforehand. |
| 405 static List<Member> _inheritMembers( | 473 static List<Member> _inheritMembers( |
| 406 List<Member> declared, List<Member> inherited, | 474 List<Member> declared, List<Member> inherited, |
| 407 {bool skipAbstractMembers: false}) { | 475 {bool skipAbstractMembers: false}) { |
| 408 List<Member> result = <Member>[]..length = | 476 List<Member> result = <Member>[]..length = |
| 409 declared.length + inherited.length; | 477 declared.length + inherited.length; |
| 410 // Since both lists are sorted, we can fuse them like in merge sort. | 478 // Since both lists are sorted, we can fuse them like in merge sort. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 441 result[storeIndex++] = declaredMember; | 509 result[storeIndex++] = declaredMember; |
| 442 } | 510 } |
| 443 while (j < inherited.length) { | 511 while (j < inherited.length) { |
| 444 Member inheritedMember = inherited[j++]; | 512 Member inheritedMember = inherited[j++]; |
| 445 if (skipAbstractMembers && inheritedMember.isAbstract) continue; | 513 if (skipAbstractMembers && inheritedMember.isAbstract) continue; |
| 446 result[storeIndex++] = inheritedMember; | 514 result[storeIndex++] = inheritedMember; |
| 447 } | 515 } |
| 448 result.length = storeIndex; | 516 result.length = storeIndex; |
| 449 return result; | 517 return result; |
| 450 } | 518 } |
| 519 | |
| 520 /// Merges two sorted lists. | |
| 521 /// | |
| 522 /// If a given member occurs in both lists, the merge will attempt to exclude | |
| 523 /// the duplicate member, but is not strictly guaranteed to do so. | |
| 524 static List<Member> _merge(List<Member> first, List<Member> second) { | |
| 525 if (first.isEmpty) return second; | |
| 526 if (second.isEmpty) return first; | |
| 527 List<Member> result = <Member>[]..length = first.length + second.length; | |
| 528 int storeIndex = 0; | |
| 529 int i = 0, j = 0; | |
| 530 while (i < first.length && j < second.length) { | |
| 531 Member firstMember = first[i]; | |
| 532 Member secondMember = second[j]; | |
| 533 int compare = _compareMembers(firstMember, secondMember); | |
| 534 if (compare <= 0) { | |
| 535 result[storeIndex++] = firstMember; | |
| 536 ++i; | |
| 537 // If the same member occurs in both lists, skip the duplicate. | |
| 538 if (identical(firstMember, secondMember)) { | |
| 539 ++j; | |
| 540 } | |
| 541 } else { | |
| 542 result[storeIndex++] = secondMember; | |
| 543 ++j; | |
| 544 } | |
| 545 } | |
| 546 while (i < first.length) { | |
| 547 result[storeIndex++] = first[i++]; | |
| 548 } | |
| 549 while (j < second.length) { | |
| 550 result[storeIndex++] = second[j++]; | |
| 551 } | |
| 552 result.length = storeIndex; | |
| 553 return result; | |
| 554 } | |
| 451 } | 555 } |
| 452 | 556 |
| 453 /// Information about a [Class]. | 557 /// Information about a [Class]. |
| 454 class _ClassInfo { | 558 class _ClassInfo { |
| 455 /// The unique identifier of the [_ClassInfo]. | 559 /// The unique identifier of the [_ClassInfo]. |
| 456 final int id; | 560 final int id; |
| 457 | 561 |
| 458 /// The [Class] node described by this [_ClassInfo]. | 562 /// The [Class] node described by this [_ClassInfo]. |
| 459 final Class node; | 563 final Class node; |
| 460 | 564 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 List<Member> declaredSetters; | 612 List<Member> declaredSetters; |
| 509 | 613 |
| 510 /// Instance fields, getters, methods, and operators implemented by this class | 614 /// Instance fields, getters, methods, and operators implemented by this class |
| 511 /// (declared or inherited). | 615 /// (declared or inherited). |
| 512 List<Member> implementedGettersAndCalls; | 616 List<Member> implementedGettersAndCalls; |
| 513 | 617 |
| 514 /// Non-final instance fields and setters implemented by this class | 618 /// Non-final instance fields and setters implemented by this class |
| 515 /// (declared or inherited). | 619 /// (declared or inherited). |
| 516 List<Member> implementedSetters; | 620 List<Member> implementedSetters; |
| 517 | 621 |
| 622 /// Instance fields, getters, methods, and operators declared in this class, | |
| 623 /// or its supertype, or interfaces, sorted according to [_compareMembers], | |
| 624 /// or `null` if it has not been computed yet. | |
| 625 List<Member> interfaceGettersAndCalls; | |
| 626 | |
| 627 /// Non-final instance fields and setters declared in this class, or its | |
| 628 /// supertype, or interfaces, sorted according to [_compareMembers], or | |
| 629 /// `null` if it has not been computed yet. | |
| 630 List<Member> interfaceSetters; | |
| 631 | |
| 518 _ClassInfo(this.id, this.node); | 632 _ClassInfo(this.id, this.node); |
| 519 | 633 |
| 520 /// Return `true` if the [superInfo] corresponds to a supertype of this class. | 634 /// Return `true` if the [superInfo] corresponds to a supertype of this class. |
| 521 bool isSubtypeOf(_ClassInfo superInfo) { | 635 bool isSubtypeOf(_ClassInfo superInfo) { |
| 522 return supertypeIdSet.contains(superInfo.id); | 636 return supertypeIdSet.contains(superInfo.id); |
| 523 } | 637 } |
| 524 | 638 |
| 525 @override | 639 @override |
| 526 String toString() => node.toString(); | 640 String toString() => node.toString(); |
| 527 } | 641 } |
| 528 | 642 |
| 529 /// Heap for use in computing least upper bounds. | 643 /// Heap for use in computing least upper bounds. |
| 530 /// | 644 /// |
| 531 /// The heap is sorted such that classes that are deepest in the hierarchy | 645 /// The heap is sorted such that classes that are deepest in the hierarchy |
| 532 /// are removed first; in the case of ties, classes with lower unique | 646 /// are removed first; in the case of ties, classes with lower unique |
| 533 /// identifiers removed first. | 647 /// identifiers removed first. |
| 534 class _LubHeap extends Heap<_ClassInfo> { | 648 class _LubHeap extends Heap<_ClassInfo> { |
| 535 @override | 649 @override |
| 536 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); | 650 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); |
| 537 | 651 |
| 538 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { | 652 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { |
| 539 if (a.depth > b.depth) return true; | 653 if (a.depth > b.depth) return true; |
| 540 if (a.depth < b.depth) return false; | 654 if (a.depth < b.depth) return false; |
| 541 return a.id < b.id; | 655 return a.id < b.id; |
| 542 } | 656 } |
| 543 } | 657 } |
| OLD | NEW |