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

Side by Side Diff: pkg/compiler/lib/src/serialization/equivalence.dart

Issue 1873573004: Serialize TreeElements (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Check only the last test to avoid timeout. Created 4 years, 8 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
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 /// Functions for asserting equivalence across serialization. 5 /// Functions for asserting equivalence across serialization.
6 6
7 library dart2js.serialization.equivalence; 7 library dart2js.serialization.equivalence;
8 8
9 import '../common/resolution.dart'; 9 import '../common/resolution.dart';
10 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
11 import '../dart_types.dart'; 11 import '../dart_types.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../elements/visitor.dart'; 13 import '../elements/visitor.dart';
14 import '../resolution/send_structure.dart';
15 import '../resolution/tree_elements.dart';
16 import '../tokens/token.dart';
17 import '../tree/nodes.dart';
14 import '../universe/selector.dart'; 18 import '../universe/selector.dart';
15 import '../universe/use.dart'; 19 import '../universe/use.dart';
20 import 'resolved_ast_serialization.dart';
16 21
17 /// Equality based equivalence function. 22 /// Equality based equivalence function.
18 bool equality(a, b) => a == b; 23 bool equality(a, b) => a == b;
19 24
20 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent 25 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent
21 /// according to [elementEquivalence]. 26 /// according to [elementEquivalence].
22 bool areListsEquivalent(List a, List b, 27 bool areListsEquivalent(List a, List b,
23 [bool elementEquivalence(a, b) = equality]) { 28 [bool elementEquivalence(a, b) = equality]) {
24 if (a.length != b.length) return false; 29 if (a.length != b.length) return false;
25 for (int i = 0; i < a.length && i < b.length; i++) { 30 for (int i = 0; i < a.length && i < b.length; i++) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 } 88 }
84 89
85 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. 90 /// Returns `true` if the lists of constants, [a] and [b], are equivalent.
86 bool areConstantListsEquivalent( 91 bool areConstantListsEquivalent(
87 List<ConstantExpression> a, List<ConstantExpression> b) { 92 List<ConstantExpression> a, List<ConstantExpression> b) {
88 return areListsEquivalent(a, b, areConstantsEquivalent); 93 return areListsEquivalent(a, b, areConstantsEquivalent);
89 } 94 }
90 95
91 /// Returns `true` if the selectors [a] and [b] are equivalent. 96 /// Returns `true` if the selectors [a] and [b] are equivalent.
92 bool areSelectorsEquivalent(Selector a, Selector b) { 97 bool areSelectorsEquivalent(Selector a, Selector b) {
98 if (identical(a, b)) return true;
99 if (a == null || b == null) return false;
93 return a.kind == b.kind && 100 return a.kind == b.kind &&
94 a.callStructure == b.callStructure && 101 a.callStructure == b.callStructure &&
95 areNamesEquivalent(a.memberName, b.memberName); 102 areNamesEquivalent(a.memberName, b.memberName);
96 } 103 }
97 104
98 /// Returns `true` if the names [a] and [b] are equivalent. 105 /// Returns `true` if the names [a] and [b] are equivalent.
99 bool areNamesEquivalent(Name a, Name b) { 106 bool areNamesEquivalent(Name a, Name b) {
100 return a.text == b.text && 107 return a.text == b.text &&
101 a.isSetter == b.isSetter && 108 a.isSetter == b.isSetter &&
102 areElementsEquivalent(a.library, b.library); 109 areElementsEquivalent(a.library, b.library);
(...skipping 21 matching lines...) Expand all
124 a.isEmpty == b.isEmpty; 131 a.isEmpty == b.isEmpty;
125 } 132 }
126 133
127 /// Returns `true` if the map literal uses [a] and [b] are equivalent. 134 /// Returns `true` if the map literal uses [a] and [b] are equivalent.
128 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { 135 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) {
129 return areTypesEquivalent(a.type, b.type) && 136 return areTypesEquivalent(a.type, b.type) &&
130 a.isConstant == b.isConstant && 137 a.isConstant == b.isConstant &&
131 a.isEmpty == b.isEmpty; 138 a.isEmpty == b.isEmpty;
132 } 139 }
133 140
141 /// Returns `true` if the send structures [a] and [b] are equivalent.
142 bool areSendStructuresEquivalent(SendStructure a, SendStructure b) {
143 if (identical(a, b)) return true;
144 if (a == null || b == null) return false;
145 if (a.kind != b.kind) return false;
146 // TODO(johnniwinther): Compute a deep equivalence.
147 return true;
148 }
149
150 /// Returns `true` if the new structures [a] and [b] are equivalent.
151 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) {
152 if (identical(a, b)) return true;
153 if (a == null || b == null) return false;
154 if (a.kind != b.kind) return false;
155 // TODO(johnniwinther): Compute a deep equivalence.
156 return true;
157 }
158
134 /// Strategy for testing equivalence. 159 /// Strategy for testing equivalence.
135 /// 160 ///
136 /// Use this strategy to determine equivalence without failing on inequivalence. 161 /// Use this strategy to determine equivalence without failing on inequivalence.
137 class TestStrategy { 162 class TestStrategy {
138 const TestStrategy(); 163 const TestStrategy();
139 164
140 bool test(var object1, var object2, String property, var value1, var value2) { 165 bool test(var object1, var object2, String property, var value1, var value2,
141 return value1 == value2; 166 [bool equivalence(a, b) = equality]) {
167 return equivalence(value1, value2);
142 } 168 }
143 169
144 bool testLists( 170 bool testLists(
145 Object object1, Object object2, String property, List list1, List list2, 171 Object object1, Object object2, String property, List list1, List list2,
146 [bool elementEquivalence(a, b) = equality]) { 172 [bool elementEquivalence(a, b) = equality]) {
147 return areListsEquivalent(list1, list2, elementEquivalence); 173 return areListsEquivalent(list1, list2, elementEquivalence);
148 } 174 }
149 175
150 bool testSets( 176 bool testSets(
151 var object1, var object2, String property, Iterable set1, Iterable set2, 177 var object1, var object2, String property, Iterable set1, Iterable set2,
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 502
477 @override 503 @override
478 bool visitPositional( 504 bool visitPositional(
479 PositionalArgumentReference exp1, PositionalArgumentReference exp2) { 505 PositionalArgumentReference exp1, PositionalArgumentReference exp2) {
480 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index); 506 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index);
481 } 507 }
482 508
483 @override 509 @override
484 bool visitSymbol( 510 bool visitSymbol(
485 SymbolConstantExpression exp1, SymbolConstantExpression exp2) { 511 SymbolConstantExpression exp1, SymbolConstantExpression exp2) {
486 // TODO: implement visitSymbol 512 // TODO(johnniwinther): Handle private names. Currently not even supported
487 return true; 513 // in resolution.
514 return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name);
488 } 515 }
489 516
490 @override 517 @override
491 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) { 518 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) {
492 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type); 519 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type);
493 } 520 }
494 521
495 @override 522 @override
496 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) { 523 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) {
497 return strategy.test( 524 return strategy.test(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 @override 592 @override
566 bool visitStringLength(StringLengthConstantExpression exp1, 593 bool visitStringLength(StringLengthConstantExpression exp1,
567 StringLengthConstantExpression exp2) { 594 StringLengthConstantExpression exp2) {
568 return strategy.testConstants( 595 return strategy.testConstants(
569 exp1, exp2, 'expression', exp1.expression, exp2.expression); 596 exp1, exp2, 'expression', exp1.expression, exp2.expression);
570 } 597 }
571 598
572 @override 599 @override
573 bool visitDeferred( 600 bool visitDeferred(
574 DeferredConstantExpression exp1, DeferredConstantExpression exp2) { 601 DeferredConstantExpression exp1, DeferredConstantExpression exp2) {
575 // TODO: implement visitDeferred 602 // TODO(johnniwinther): Implement this.
576 return true; 603 return true;
577 } 604 }
578 } 605 }
579 606
580 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. 607 /// Tests the equivalence of [impact1] and [impact2] using [strategy].
581 bool testResolutionImpactEquivalence( 608 bool testResolutionImpactEquivalence(
582 ResolutionImpact impact1, ResolutionImpact impact2, 609 ResolutionImpact impact1, ResolutionImpact impact2,
583 [TestStrategy strategy = const TestStrategy()]) { 610 [TestStrategy strategy = const TestStrategy()]) {
584 return strategy.testSets(impact1, impact2, 'constSymbolNames', 611 return strategy.testSets(impact1, impact2, 'constSymbolNames',
585 impact1.constSymbolNames, impact2.constSymbolNames) && 612 impact1.constSymbolNames, impact2.constSymbolNames) &&
(...skipping 10 matching lines...) Expand all
596 impact1, impact2, 'features', impact1.features, impact2.features) && 623 impact1, impact2, 'features', impact1.features, impact2.features) &&
597 strategy.testSets(impact1, impact2, 'listLiterals', impact1.listLiterals, 624 strategy.testSets(impact1, impact2, 'listLiterals', impact1.listLiterals,
598 impact2.listLiterals, areListLiteralUsesEquivalent) && 625 impact2.listLiterals, areListLiteralUsesEquivalent) &&
599 strategy.testSets(impact1, impact2, 'mapLiterals', impact1.mapLiterals, 626 strategy.testSets(impact1, impact2, 'mapLiterals', impact1.mapLiterals,
600 impact2.mapLiterals, areMapLiteralUsesEquivalent) && 627 impact2.mapLiterals, areMapLiteralUsesEquivalent) &&
601 strategy.testSets(impact1, impact2, 'staticUses', impact1.staticUses, 628 strategy.testSets(impact1, impact2, 'staticUses', impact1.staticUses,
602 impact2.staticUses, areStaticUsesEquivalent) && 629 impact2.staticUses, areStaticUsesEquivalent) &&
603 strategy.testSets(impact1, impact2, 'typeUses', impact1.typeUses, 630 strategy.testSets(impact1, impact2, 'typeUses', impact1.typeUses,
604 impact2.typeUses, areTypeUsesEquivalent); 631 impact2.typeUses, areTypeUsesEquivalent);
605 } 632 }
633
634 /// Tests the equivalence of [resolvedAst1] and [resolvedAst2] using [strategy].
635 bool testResolvedAstEquivalence(
636 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2,
637 [TestStrategy strategy = const TestStrategy()]) {
638 return strategy.testElements(resolvedAst1, resolvedAst2, 'element',
639 resolvedAst1.element, resolvedAst2.element) &&
640 // Compute AST equivalence by structural comparison.
641 strategy.test(
642 resolvedAst1,
643 resolvedAst2,
644 'node',
645 resolvedAst1.node.toDebugString(),
646 resolvedAst2.node.toDebugString()) &&
647 testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy);
648 }
649
650 /// Tests the equivalence of the data stored in the [TreeElements] of
651 /// [resolvedAst1] and [resolvedAst2] using [strategy].
652 bool testTreeElementsEquivalence(
653 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2,
654 [TestStrategy strategy = const TestStrategy()]) {
655 AstIndexComputer indices1 = new AstIndexComputer();
656 resolvedAst1.node.accept(indices1);
657 AstIndexComputer indices2 = new AstIndexComputer();
658 resolvedAst2.node.accept(indices2);
659
660 TreeElements elements1 = resolvedAst1.elements;
661 TreeElements elements2 = resolvedAst2.elements;
662
663 TreeElementsEquivalenceVisitor visitor = new TreeElementsEquivalenceVisitor(
664 indices1, indices2, elements1, elements2, strategy);
665 resolvedAst1.node.accept(visitor);
666 return visitor.success;
667 }
668
669 /// Visitor that checks the equivalence of [TreeElements] data.
670 class TreeElementsEquivalenceVisitor extends Visitor {
671 final TestStrategy strategy;
672 final AstIndexComputer indices1;
673 final AstIndexComputer indices2;
674 final TreeElements elements1;
675 final TreeElements elements2;
676 bool success = true;
677
678 TreeElementsEquivalenceVisitor(
679 this.indices1, this.indices2, this.elements1, this.elements2,
680 [this.strategy = const TestStrategy()]);
681
682 visitNode(Node node1) {
683 if (!success) return;
684 int index = indices1.nodeIndices[node1];
685 Node node2 = indices2.nodeList[index];
686 success = strategy.testElements(
687 node1, node2, '[$index]', elements1[node1], elements2[node2]) &&
688 strategy.testTypes(node1, node2, 'getType($index)',
689 elements1.getType(node1), elements2.getType(node2)) &&
690 strategy.test(
691 node1,
692 node2,
693 'getSelector($index)',
694 elements1.getSelector(node1),
695 elements2.getSelector(node2),
696 areSelectorsEquivalent) &&
697 strategy.testConstants(node1, node2, 'getConstant($index)',
698 elements1.getConstant(node1), elements2.getConstant(node2)) &&
699 strategy.testTypes(node1, node2, 'typesCache[$index]',
700 elements1.typesCache[node1], elements2.typesCache[node2]);
701
702 node1.visitChildren(this);
703 }
704
705 @override
706 visitSend(Send node1) {
707 visitExpression(node1);
708 if (!success) return;
709 int index = indices1.nodeIndices[node1];
710 Send node2 = indices2.nodeList[index];
711 success = strategy.test(node1, node2, 'isTypeLiteral($index)',
712 elements1.isTypeLiteral(node1), elements2.isTypeLiteral(node2)) &&
713 strategy.testTypes(
714 node1,
715 node2,
716 'getTypeLiteralType($index)',
717 elements1.getTypeLiteralType(node1),
718 elements2.getTypeLiteralType(node2)) &&
719 strategy.test(
720 node1,
721 node2,
722 'getSendStructure($index)',
723 elements1.getSendStructure(node1),
724 elements2.getSendStructure(node2),
725 areSendStructuresEquivalent);
726 }
727
728 @override
729 visitNewExpression(NewExpression node1) {
730 visitExpression(node1);
731 if (!success) return;
732 int index = indices1.nodeIndices[node1];
733 NewExpression node2 = indices2.nodeList[index];
734 success = strategy.test(
735 node1,
736 node2,
737 'getNewStructure($index)',
738 elements1.getNewStructure(node1),
739 elements2.getNewStructure(node2),
740 areNewStructuresEquivalent);
741 }
742
743 @override
744 visitSendSet(SendSet node1) {
745 visitSend(node1);
746 if (!success) return;
747 int index = indices1.nodeIndices[node1];
748 SendSet node2 = indices2.nodeList[index];
749 success = strategy.test(
750 node1,
751 node2,
752 'getGetterSelectorInComplexSendSet($index)',
753 elements1.getGetterSelectorInComplexSendSet(node1),
754 elements2.getGetterSelectorInComplexSendSet(node2),
755 areSelectorsEquivalent) &&
756 strategy.test(
757 node1,
758 node2,
759 'getOperatorSelectorInComplexSendSet($index)',
760 elements1.getOperatorSelectorInComplexSendSet(node1),
761 elements2.getOperatorSelectorInComplexSendSet(node2),
762 areSelectorsEquivalent);
763 }
764
765 @override
766 visitFunctionExpression(FunctionExpression node1) {
767 visitNode(node1);
768 if (!success) return;
769 int index = indices1.nodeIndices[node1];
770 FunctionExpression node2 = indices2.nodeList[index];
771 if (elements1[node1] is! FunctionElement) {
772 // [getFunctionDefinition] is currently stored in [] which doesn't always
773 // contain a [FunctionElement].
774 return;
775 }
776 success = strategy.testElements(
777 node1,
778 node2,
779 'getFunctionDefinition($index)',
780 elements1.getFunctionDefinition(node1),
781 elements2.getFunctionDefinition(node2));
782 }
783
784 @override
785 visitForIn(ForIn node1) {
786 visitLoop(node1);
787 if (!success) return;
788 int index = indices1.nodeIndices[node1];
789 ForIn node2 = indices2.nodeList[index];
790 success = strategy.testElements(node1, node2, 'getForInVariable($index)',
791 elements1.getForInVariable(node1), elements2.getForInVariable(node2));
792 }
793
794 @override
795 visitRedirectingFactoryBody(RedirectingFactoryBody node1) {
796 visitStatement(node1);
797 if (!success) return;
798 int index = indices1.nodeIndices[node1];
799 RedirectingFactoryBody node2 = indices2.nodeList[index];
800 success = strategy.testElements(
801 node1,
802 node2,
803 'getRedirectingTargetConstructor($index)',
804 elements1.getRedirectingTargetConstructor(node1),
805 elements2.getRedirectingTargetConstructor(node2));
806 }
807 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698