| OLD | NEW |
| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class HVisitor<R> { | 7 abstract class HVisitor<R> { |
| 8 R visitAdd(HAdd node); | 8 R visitAdd(HAdd node); |
| 9 R visitBailoutTarget(HBailoutTarget node); | 9 R visitBailoutTarget(HBailoutTarget node); |
| 10 R visitBitAnd(HBitAnd node); | 10 R visitBitAnd(HBitAnd node); |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 from.usedBy.clear(); | 610 from.usedBy.clear(); |
| 611 } | 611 } |
| 612 | 612 |
| 613 /** | 613 /** |
| 614 * Rewrites all uses of the [from] instruction to using either the | 614 * Rewrites all uses of the [from] instruction to using either the |
| 615 * [to] instruction, or a [HCheck] instruction that has better type | 615 * [to] instruction, or a [HCheck] instruction that has better type |
| 616 * information on [to], and that dominates the user. | 616 * information on [to], and that dominates the user. |
| 617 */ | 617 */ |
| 618 void rewriteWithBetterUser(HInstruction from, HInstruction to) { | 618 void rewriteWithBetterUser(HInstruction from, HInstruction to) { |
| 619 Link<HCheck> better = const Link<HCheck>(); | 619 Link<HCheck> better = const Link<HCheck>(); |
| 620 for (HInstruction user in to.usedBy) { | 620 for (var user in to.usedBy) { |
| 621 if (user is HCheck && identical((user as HCheck).checkedInput, to)) { | 621 if (user != from && user is HCheck && user.checkedInput == to) { |
| 622 better = better.prepend(user); | 622 better = better.prepend(user); |
| 623 } | 623 } |
| 624 } | 624 } |
| 625 | 625 |
| 626 if (better.isEmpty) return rewrite(from, to); | 626 if (better.isEmpty) return rewrite(from, to); |
| 627 | 627 |
| 628 L1: for (HInstruction user in from.usedBy) { | 628 L1: for (HInstruction user in from.usedBy) { |
| 629 for (HCheck check in better) { | 629 for (HCheck check in better) { |
| 630 if (check.dominates(user)) { | 630 if (check.dominates(user)) { |
| 631 user.rewriteInput(from, check); | 631 user.rewriteInput(from, check); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 | 923 |
| 924 StringBuffer buffer = new StringBuffer(); | 924 StringBuffer buffer = new StringBuffer(); |
| 925 buffer.write('('); | 925 buffer.write('('); |
| 926 addAsCommaSeparated(buffer, inputs); | 926 addAsCommaSeparated(buffer, inputs); |
| 927 buffer.write(') - used at ['); | 927 buffer.write(') - used at ['); |
| 928 addAsCommaSeparated(buffer, usedBy); | 928 addAsCommaSeparated(buffer, usedBy); |
| 929 buffer.write(']'); | 929 buffer.write(']'); |
| 930 return buffer.toString(); | 930 return buffer.toString(); |
| 931 } | 931 } |
| 932 | 932 |
| 933 nonCheck(instruction) { |
| 934 while (instruction is HCheck) instruction = instruction.checkedInput; |
| 935 return instruction; |
| 936 } |
| 937 |
| 933 bool gvnEquals(HInstruction other) { | 938 bool gvnEquals(HInstruction other) { |
| 934 assert(useGvn() && other.useGvn()); | 939 assert(useGvn() && other.useGvn()); |
| 935 // Check that the type and the flags match. | 940 // Check that the type and the flags match. |
| 936 bool hasSameType = typeEquals(other); | 941 bool hasSameType = typeEquals(other); |
| 937 assert(hasSameType == (typeCode() == other.typeCode())); | 942 assert(hasSameType == (typeCode() == other.typeCode())); |
| 938 if (!hasSameType) return false; | 943 if (!hasSameType) return false; |
| 939 if (flags != other.flags) return false; | 944 if (flags != other.flags) return false; |
| 940 // Check that the inputs match. | 945 // Check that the inputs match. |
| 941 final int inputsLength = inputs.length; | 946 final int inputsLength = inputs.length; |
| 942 final List<HInstruction> otherInputs = other.inputs; | 947 final List<HInstruction> otherInputs = other.inputs; |
| 943 if (inputsLength != otherInputs.length) return false; | 948 if (inputsLength != otherInputs.length) return false; |
| 944 for (int i = 0; i < inputsLength; i++) { | 949 for (int i = 0; i < inputsLength; i++) { |
| 945 if (!identical(inputs[i], otherInputs[i])) return false; | 950 if (nonCheck(inputs[i]) != nonCheck(otherInputs[i])) { |
| 951 return false; |
| 952 } |
| 946 } | 953 } |
| 947 // Check that the data in the instruction matches. | 954 // Check that the data in the instruction matches. |
| 948 return dataEquals(other); | 955 return dataEquals(other); |
| 949 } | 956 } |
| 950 | 957 |
| 951 int gvnHashCode() { | 958 int gvnHashCode() { |
| 952 int result = typeCode(); | 959 int result = typeCode(); |
| 953 int length = inputs.length; | 960 int length = inputs.length; |
| 954 for (int i = 0; i < length; i++) { | 961 for (int i = 0; i < length; i++) { |
| 955 result = (result * 19) + (inputs[i].id) + (result >> 7); | 962 result = (result * 19) + (nonCheck(inputs[i]).id) + (result >> 7); |
| 956 } | 963 } |
| 957 return result; | 964 return result; |
| 958 } | 965 } |
| 959 | 966 |
| 960 // These methods should be overwritten by instructions that | 967 // These methods should be overwritten by instructions that |
| 961 // participate in global value numbering. | 968 // participate in global value numbering. |
| 962 int typeCode() => HInstruction.UNDEFINED_TYPECODE; | 969 int typeCode() => HInstruction.UNDEFINED_TYPECODE; |
| 963 bool typeEquals(HInstruction other) => false; | 970 bool typeEquals(HInstruction other) => false; |
| 964 bool dataEquals(HInstruction other) => false; | 971 bool dataEquals(HInstruction other) => false; |
| 965 | 972 |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 if (isSideEffectFree) { | 1398 if (isSideEffectFree) { |
| 1392 setUseGvn(); | 1399 setUseGvn(); |
| 1393 setDependsOnInstancePropertyStore(); | 1400 setDependsOnInstancePropertyStore(); |
| 1394 } else { | 1401 } else { |
| 1395 setDependsOnSomething(); | 1402 setDependsOnSomething(); |
| 1396 setAllSideEffects(); | 1403 setAllSideEffects(); |
| 1397 } | 1404 } |
| 1398 } | 1405 } |
| 1399 toString() => 'invoke dynamic getter: $selector'; | 1406 toString() => 'invoke dynamic getter: $selector'; |
| 1400 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); | 1407 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
| 1408 |
| 1409 int typeCode() => HInstruction.FIELD_GET_TYPECODE; |
| 1410 bool typeEquals(other) => other is HFieldGet || other is HInvokeDynamicGetter; |
| 1411 bool dataEquals(other) { |
| 1412 return other is HFieldGet |
| 1413 ? other.element.name == selector.name |
| 1414 : super.dataEquals(other); |
| 1415 } |
| 1401 } | 1416 } |
| 1402 | 1417 |
| 1403 class HInvokeDynamicSetter extends HInvokeDynamicField { | 1418 class HInvokeDynamicSetter extends HInvokeDynamicField { |
| 1404 HInvokeDynamicSetter(selector, element, inputs, isSideEffectFree) | 1419 HInvokeDynamicSetter(selector, element, inputs, isSideEffectFree) |
| 1405 : super(selector, element, inputs, isSideEffectFree) { | 1420 : super(selector, element, inputs, isSideEffectFree) { |
| 1406 clearAllSideEffects(); | 1421 clearAllSideEffects(); |
| 1407 if (isSideEffectFree) { | 1422 if (isSideEffectFree) { |
| 1408 setChangesInstanceProperty(); | 1423 setChangesInstanceProperty(); |
| 1409 } else { | 1424 } else { |
| 1410 setAllSideEffects(); | 1425 setAllSideEffects(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 bool interceptor = | 1493 bool interceptor = |
| 1479 backend.isInterceptorClass(sourceElement.getEnclosingClass()); | 1494 backend.isInterceptorClass(sourceElement.getEnclosingClass()); |
| 1480 return interceptor && sourceElement is ThisElement; | 1495 return interceptor && sourceElement is ThisElement; |
| 1481 } | 1496 } |
| 1482 | 1497 |
| 1483 bool canThrow() => receiver.canBeNull(); | 1498 bool canThrow() => receiver.canBeNull(); |
| 1484 | 1499 |
| 1485 accept(HVisitor visitor) => visitor.visitFieldGet(this); | 1500 accept(HVisitor visitor) => visitor.visitFieldGet(this); |
| 1486 | 1501 |
| 1487 int typeCode() => HInstruction.FIELD_GET_TYPECODE; | 1502 int typeCode() => HInstruction.FIELD_GET_TYPECODE; |
| 1488 bool typeEquals(other) => other is HFieldGet; | 1503 bool typeEquals(other) => other is HFieldGet || other is HInvokeDynamicGetter; |
| 1489 bool dataEquals(HFieldGet other) => element == other.element; | 1504 bool dataEquals(other) { |
| 1505 return other is HInvokeDynamicGetter |
| 1506 ? element.name == other.selector.name |
| 1507 : element == other.element; |
| 1508 } |
| 1490 String toString() => "FieldGet $element"; | 1509 String toString() => "FieldGet $element"; |
| 1491 } | 1510 } |
| 1492 | 1511 |
| 1493 class HFieldSet extends HFieldAccess { | 1512 class HFieldSet extends HFieldAccess { |
| 1494 HFieldSet(Element element, | 1513 HFieldSet(Element element, |
| 1495 HInstruction receiver, | 1514 HInstruction receiver, |
| 1496 HInstruction value) | 1515 HInstruction value) |
| 1497 : super(element, <HInstruction>[receiver, value]) { | 1516 : super(element, <HInstruction>[receiver, value]) { |
| 1498 clearAllSideEffects(); | 1517 clearAllSideEffects(); |
| 1499 setChangesInstanceProperty(); | 1518 setChangesInstanceProperty(); |
| (...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2662 HBasicBlock get start => expression.start; | 2681 HBasicBlock get start => expression.start; |
| 2663 HBasicBlock get end { | 2682 HBasicBlock get end { |
| 2664 // We don't create a switch block if there are no cases. | 2683 // We don't create a switch block if there are no cases. |
| 2665 assert(!statements.isEmpty); | 2684 assert(!statements.isEmpty); |
| 2666 return statements.last.end; | 2685 return statements.last.end; |
| 2667 } | 2686 } |
| 2668 | 2687 |
| 2669 bool accept(HStatementInformationVisitor visitor) => | 2688 bool accept(HStatementInformationVisitor visitor) => |
| 2670 visitor.visitSwitchInfo(this); | 2689 visitor.visitSwitchInfo(this); |
| 2671 } | 2690 } |
| OLD | NEW |