| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.serialization_model_test; | 5 library dart2js.serialization_model_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 import 'package:async_helper/async_helper.dart'; | 9 import 'package:async_helper/async_helper.dart'; |
| 10 import 'package:expect/expect.dart'; | 10 import 'package:expect/expect.dart'; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 checkAllImpacts(compilerNormal, compilerDeserialized, verbose: verbose); | 100 checkAllImpacts(compilerNormal, compilerDeserialized, verbose: verbose); |
| 101 checkResolutionEnqueuers( | 101 checkResolutionEnqueuers( |
| 102 compilerNormal.backend.backendUsage, | 102 compilerNormal.backend.backendUsage, |
| 103 compilerDeserialized.backend.backendUsage, | 103 compilerDeserialized.backend.backendUsage, |
| 104 compilerNormal.enqueuer.resolution, | 104 compilerNormal.enqueuer.resolution, |
| 105 compilerDeserialized.enqueuer.resolution, | 105 compilerDeserialized.enqueuer.resolution, |
| 106 verbose: verbose); | 106 verbose: verbose); |
| 107 checkClosedWorlds( | 107 checkClosedWorlds( |
| 108 compilerNormal.resolutionWorldBuilder.closedWorldForTesting, | 108 compilerNormal.resolutionWorldBuilder.closedWorldForTesting, |
| 109 compilerDeserialized.resolutionWorldBuilder.closedWorldForTesting, | 109 compilerDeserialized.resolutionWorldBuilder.closedWorldForTesting, |
| 110 areElementsEquivalent, |
| 110 verbose: verbose); | 111 verbose: verbose); |
| 111 checkBackendInfo(compilerNormal, compilerDeserialized, verbose: verbose); | 112 checkBackendInfo(compilerNormal, compilerDeserialized, verbose: verbose); |
| 112 }); | 113 }); |
| 113 } | 114 } |
| 114 | 115 |
| 115 void checkResolutionEnqueuers( | 116 void checkResolutionEnqueuers( |
| 116 BackendUsage backendUsage1, | 117 BackendUsage backendUsage1, |
| 117 BackendUsage backendUsage2, | 118 BackendUsage backendUsage2, |
| 118 ResolutionEnqueuer enqueuer1, | 119 ResolutionEnqueuer enqueuer1, |
| 119 ResolutionEnqueuer enqueuer2, | 120 ResolutionEnqueuer enqueuer2, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 "JavaScriptBackend.hasFunctionApplySupport mismatch"); | 165 "JavaScriptBackend.hasFunctionApplySupport mismatch"); |
| 165 Expect.equals( | 166 Expect.equals( |
| 166 backendUsage1.isRuntimeTypeUsed, | 167 backendUsage1.isRuntimeTypeUsed, |
| 167 backendUsage2.isRuntimeTypeUsed, | 168 backendUsage2.isRuntimeTypeUsed, |
| 168 "JavaScriptBackend.hasRuntimeTypeSupport mismatch"); | 169 "JavaScriptBackend.hasRuntimeTypeSupport mismatch"); |
| 169 Expect.equals(backendUsage1.isIsolateInUse, backendUsage2.isIsolateInUse, | 170 Expect.equals(backendUsage1.isIsolateInUse, backendUsage2.isIsolateInUse, |
| 170 "JavaScriptBackend.hasIsolateSupport mismatch"); | 171 "JavaScriptBackend.hasIsolateSupport mismatch"); |
| 171 } | 172 } |
| 172 | 173 |
| 173 void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2, | 174 void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2, |
| 175 bool elementEquivalence(Entity a, Entity b), |
| 174 {bool verbose: false}) { | 176 {bool verbose: false}) { |
| 177 if (verbose) { |
| 178 print(closedWorld1.dump()); |
| 179 print(closedWorld2.dump()); |
| 180 } |
| 175 checkClassHierarchyNodes( | 181 checkClassHierarchyNodes( |
| 176 closedWorld1, | 182 closedWorld1, |
| 177 closedWorld2, | 183 closedWorld2, |
| 178 closedWorld1 | 184 closedWorld1 |
| 179 .getClassHierarchyNode(closedWorld1.commonElements.objectClass), | 185 .getClassHierarchyNode(closedWorld1.commonElements.objectClass), |
| 180 closedWorld2 | 186 closedWorld2 |
| 181 .getClassHierarchyNode(closedWorld2.commonElements.objectClass), | 187 .getClassHierarchyNode(closedWorld2.commonElements.objectClass), |
| 188 elementEquivalence, |
| 182 verbose: verbose); | 189 verbose: verbose); |
| 183 } | 190 } |
| 184 | 191 |
| 185 void checkBackendInfo(Compiler compilerNormal, Compiler compilerDeserialized, | 192 void checkBackendInfo(Compiler compilerNormal, Compiler compilerDeserialized, |
| 186 {bool verbose: false}) { | 193 {bool verbose: false}) { |
| 187 checkSets( | 194 checkSets( |
| 188 compilerNormal.enqueuer.resolution.processedEntities, | 195 compilerNormal.enqueuer.resolution.processedEntities, |
| 189 compilerDeserialized.enqueuer.resolution.processedEntities, | 196 compilerDeserialized.enqueuer.resolution.processedEntities, |
| 190 "Processed element mismatch", | 197 "Processed element mismatch", |
| 191 areElementsEquivalent, onSameElement: (a, b) { | 198 areElementsEquivalent, onSameElement: (a, b) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 JavaScriptBackend backend1 = compiler1.backend; | 304 JavaScriptBackend backend1 = compiler1.backend; |
| 298 JavaScriptBackend backend2 = compiler2.backend; | 305 JavaScriptBackend backend2 = compiler2.backend; |
| 299 Expect.equals( | 306 Expect.equals( |
| 300 backend1.inlineCache.getCurrentCacheDecisionForTesting(element1), | 307 backend1.inlineCache.getCurrentCacheDecisionForTesting(element1), |
| 301 backend2.inlineCache.getCurrentCacheDecisionForTesting(element2), | 308 backend2.inlineCache.getCurrentCacheDecisionForTesting(element2), |
| 302 "Inline cache decision mismatch for $element1 vs $element2"); | 309 "Inline cache decision mismatch for $element1 vs $element2"); |
| 303 | 310 |
| 304 checkElementOutputUnits(compiler1, compiler2, element1, element2); | 311 checkElementOutputUnits(compiler1, compiler2, element1, element2); |
| 305 } | 312 } |
| 306 | 313 |
| 307 void checkMixinUses(ClosedWorld closedWorld1, ClosedWorld closedWorld2, | 314 void checkMixinUses( |
| 308 ClassElement class1, ClassElement class2, | 315 ClosedWorld closedWorld1, |
| 316 ClosedWorld closedWorld2, |
| 317 ClassEntity class1, |
| 318 ClassEntity class2, |
| 319 bool elementEquivalence(Entity a, Entity b), |
| 309 {bool verbose: false}) { | 320 {bool verbose: false}) { |
| 310 checkSets(closedWorld1.mixinUsesOf(class1), closedWorld2.mixinUsesOf(class2), | 321 checkSets(closedWorld1.mixinUsesOf(class1), closedWorld2.mixinUsesOf(class2), |
| 311 "Mixin uses of $class1 vs $class2", areElementsEquivalent, | 322 "Mixin uses of $class1 vs $class2", elementEquivalence, |
| 312 verbose: verbose); | 323 verbose: verbose); |
| 313 } | 324 } |
| 314 | 325 |
| 315 void checkClassHierarchyNodes( | 326 void checkClassHierarchyNodes( |
| 316 ClosedWorld closedWorld1, | 327 ClosedWorld closedWorld1, |
| 317 ClosedWorld closedWorld2, | 328 ClosedWorld closedWorld2, |
| 318 ClassHierarchyNode node1, | 329 ClassHierarchyNode node1, |
| 319 ClassHierarchyNode node2, | 330 ClassHierarchyNode node2, |
| 331 bool elementEquivalence(Entity a, Entity b), |
| 320 {bool verbose: false}) { | 332 {bool verbose: false}) { |
| 321 if (verbose) { | 333 if (verbose) { |
| 322 print('Checking $node1 vs $node2'); | 334 print('Checking $node1 vs $node2'); |
| 323 } | 335 } |
| 324 ClassElement cls1 = node1.cls; | 336 ClassEntity cls1 = node1.cls; |
| 325 ClassElement cls2 = node2.cls; | 337 ClassEntity cls2 = node2.cls; |
| 326 Expect.isTrue(areElementsEquivalent(cls1, cls2), | 338 Expect.isTrue(elementEquivalence(cls1, cls2), |
| 327 "Element identity mismatch for ${cls1} vs ${cls2}."); | 339 "Element identity mismatch for ${cls1} vs ${cls2}."); |
| 328 Expect.equals( | 340 Expect.equals( |
| 329 node1.isDirectlyInstantiated, | 341 node1.isDirectlyInstantiated, |
| 330 node2.isDirectlyInstantiated, | 342 node2.isDirectlyInstantiated, |
| 331 "Value mismatch for 'isDirectlyInstantiated' " | 343 "Value mismatch for 'isDirectlyInstantiated' " |
| 332 "for ${cls1} vs ${cls2}."); | 344 "for ${cls1} vs ${cls2}."); |
| 333 Expect.equals( | 345 Expect.equals( |
| 334 node1.isIndirectlyInstantiated, | 346 node1.isIndirectlyInstantiated, |
| 335 node2.isIndirectlyInstantiated, | 347 node2.isIndirectlyInstantiated, |
| 336 "Value mismatch for 'isIndirectlyInstantiated' " | 348 "Value mismatch for 'isIndirectlyInstantiated' " |
| 337 "for ${node1.cls} vs ${node2.cls}."); | 349 "for ${node1.cls} vs ${node2.cls}."); |
| 338 // TODO(johnniwinther): Enforce a canonical and stable order on direct | 350 // TODO(johnniwinther): Enforce a canonical and stable order on direct |
| 339 // subclasses. | 351 // subclasses. |
| 340 for (ClassHierarchyNode child in node1.directSubclasses) { | 352 for (ClassHierarchyNode child in node1.directSubclasses) { |
| 341 bool found = false; | 353 bool found = false; |
| 342 for (ClassHierarchyNode other in node2.directSubclasses) { | 354 for (ClassHierarchyNode other in node2.directSubclasses) { |
| 343 ClassElement child1 = child.cls; | 355 ClassEntity child1 = child.cls; |
| 344 ClassElement child2 = other.cls; | 356 ClassEntity child2 = other.cls; |
| 345 if (areElementsEquivalent(child1, child2)) { | 357 if (elementEquivalence(child1, child2)) { |
| 346 checkClassHierarchyNodes(closedWorld1, closedWorld2, child, other, | 358 checkClassHierarchyNodes( |
| 359 closedWorld1, closedWorld2, child, other, elementEquivalence, |
| 347 verbose: verbose); | 360 verbose: verbose); |
| 348 found = true; | 361 found = true; |
| 349 break; | 362 break; |
| 350 } | 363 } |
| 351 } | 364 } |
| 352 if (!found) { | 365 if (!found) { |
| 353 if (child.isInstantiated) { | 366 if (child.isInstantiated) { |
| 354 print('Missing subclass ${child.cls} of ${node1.cls} ' | 367 print('Missing subclass ${child.cls} of ${node1.cls} ' |
| 355 'in ${node2.directSubclasses}'); | 368 'in ${node2.directSubclasses}'); |
| 356 print(closedWorld1.dump( | 369 print(closedWorld1.dump( |
| 357 verbose ? closedWorld1.commonElements.objectClass : node1.cls)); | 370 verbose ? closedWorld1.commonElements.objectClass : node1.cls)); |
| 358 print(closedWorld2.dump( | 371 print(closedWorld2.dump( |
| 359 verbose ? closedWorld2.commonElements.objectClass : node2.cls)); | 372 verbose ? closedWorld2.commonElements.objectClass : node2.cls)); |
| 360 } | 373 } |
| 361 Expect.isFalse( | 374 Expect.isFalse( |
| 362 child.isInstantiated, | 375 child.isInstantiated, |
| 363 'Missing subclass ${child.cls} of ${node1.cls} in ' | 376 'Missing subclass ${child.cls} of ${node1.cls} in ' |
| 364 '${node2.directSubclasses}'); | 377 '${node2.directSubclasses}'); |
| 365 } | 378 } |
| 366 } | 379 } |
| 367 checkMixinUses(closedWorld1, closedWorld2, node1.cls, node2.cls, | 380 checkMixinUses( |
| 381 closedWorld1, closedWorld2, node1.cls, node2.cls, elementEquivalence, |
| 368 verbose: verbose); | 382 verbose: verbose); |
| 369 } | 383 } |
| 370 | 384 |
| 371 bool areLocalsEquivalent(Local a, Local b) { | 385 bool areLocalsEquivalent(Local a, Local b) { |
| 372 if (a == b) return true; | 386 if (a == b) return true; |
| 373 if (a == null || b == null) return false; | 387 if (a == null || b == null) return false; |
| 374 | 388 |
| 375 if (a is Element) { | 389 if (a is Element) { |
| 376 return b is Element && areElementsEquivalent(a as Element, b as Element); | 390 return b is Element && areElementsEquivalent(a as Element, b as Element); |
| 377 } else { | 391 } else { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } | 472 } |
| 459 | 473 |
| 460 bool areInstancesEquivalent(Instance instance1, Instance instance2, | 474 bool areInstancesEquivalent(Instance instance1, Instance instance2, |
| 461 bool typeEquivalence(DartType a, DartType b)) { | 475 bool typeEquivalence(DartType a, DartType b)) { |
| 462 InterfaceType type1 = instance1.type; | 476 InterfaceType type1 = instance1.type; |
| 463 InterfaceType type2 = instance2.type; | 477 InterfaceType type2 = instance2.type; |
| 464 return typeEquivalence(type1, type2) && | 478 return typeEquivalence(type1, type2) && |
| 465 instance1.kind == instance2.kind && | 479 instance1.kind == instance2.kind && |
| 466 instance1.isRedirection == instance2.isRedirection; | 480 instance1.isRedirection == instance2.isRedirection; |
| 467 } | 481 } |
| OLD | NEW |