| 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 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 4559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4570 | 4570 |
| 4571 visitLiteralMapEntry(LiteralMapEntry node) { | 4571 visitLiteralMapEntry(LiteralMapEntry node) { |
| 4572 visit(node.value); | 4572 visit(node.value); |
| 4573 visit(node.key); | 4573 visit(node.key); |
| 4574 } | 4574 } |
| 4575 | 4575 |
| 4576 visitNamedArgument(NamedArgument node) { | 4576 visitNamedArgument(NamedArgument node) { |
| 4577 visit(node.expression); | 4577 visit(node.expression); |
| 4578 } | 4578 } |
| 4579 | 4579 |
| 4580 Map<CaseMatch,Constant> buildSwitchCaseConstants(SwitchStatement node) { | 4580 Map<CaseMatch, Constant> buildSwitchCaseConstants(SwitchStatement node) { |
| 4581 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>(); | 4581 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>(); |
| 4582 // First check whether all case expressions are compile-time constants, | |
| 4583 // and all have the same type that doesn't override operator==. | |
| 4584 // TODO(lrn): Move the constant resolution to the resolver, so | |
| 4585 // we can report an error before reaching the backend. | |
| 4586 DartType firstConstantType = null; | |
| 4587 bool failure = false; | |
| 4588 for (SwitchCase switchCase in node.cases) { | 4582 for (SwitchCase switchCase in node.cases) { |
| 4589 for (Node labelOrCase in switchCase.labelsAndCases) { | 4583 for (Node labelOrCase in switchCase.labelsAndCases) { |
| 4590 if (labelOrCase is CaseMatch) { | 4584 if (labelOrCase is CaseMatch) { |
| 4591 CaseMatch match = labelOrCase; | 4585 CaseMatch match = labelOrCase; |
| 4592 Constant constant = getConstantForNode(match.expression); | 4586 Constant constant = getConstantForNode(match.expression); |
| 4593 if (firstConstantType == null) { | |
| 4594 firstConstantType = constant.computeType(compiler); | |
| 4595 if (nonPrimitiveTypeOverridesEquals(constant)) { | |
| 4596 compiler.reportFatalError( | |
| 4597 match.expression, | |
| 4598 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS); | |
| 4599 failure = true; | |
| 4600 } | |
| 4601 } | |
| 4602 constants[labelOrCase] = constant; | 4587 constants[labelOrCase] = constant; |
| 4603 } | 4588 } |
| 4604 } | 4589 } |
| 4605 } | 4590 } |
| 4606 return constants; | 4591 return constants; |
| 4607 } | 4592 } |
| 4608 | 4593 |
| 4609 visitSwitchStatement(SwitchStatement node) { | 4594 visitSwitchStatement(SwitchStatement node) { |
| 4610 Map<CaseMatch,Constant> constants = buildSwitchCaseConstants(node); | 4595 Map<CaseMatch,Constant> constants = buildSwitchCaseConstants(node); |
| 4611 | 4596 |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4948 new HSwitchBlockInformation(expressionInfo, | 4933 new HSwitchBlockInformation(expressionInfo, |
| 4949 matchExpressions, | 4934 matchExpressions, |
| 4950 statements, | 4935 statements, |
| 4951 jumpHandler.target, | 4936 jumpHandler.target, |
| 4952 jumpHandler.labels()), | 4937 jumpHandler.labels()), |
| 4953 joinBlock); | 4938 joinBlock); |
| 4954 | 4939 |
| 4955 jumpHandler.close(); | 4940 jumpHandler.close(); |
| 4956 } | 4941 } |
| 4957 | 4942 |
| 4958 bool nonPrimitiveTypeOverridesEquals(Constant constant) { | |
| 4959 // Function values override equals. Even static ones, since | |
| 4960 // they inherit from [Function]. | |
| 4961 if (constant.isFunction()) return true; | |
| 4962 | |
| 4963 // [Map] and [List] do not override equals. | |
| 4964 // If constant is primitive, just return false. We know | |
| 4965 // about the equals methods of num/String classes. | |
| 4966 if (!constant.isConstructedObject()) return false; | |
| 4967 | |
| 4968 ConstructedConstant constructedConstant = constant; | |
| 4969 DartType type = constructedConstant.type; | |
| 4970 assert(type != null); | |
| 4971 Element element = type.element; | |
| 4972 // If the type is not a class, we'll just assume it overrides | |
| 4973 // operator==. Typedefs do, since [Function] does. | |
| 4974 if (!element.isClass()) return true; | |
| 4975 ClassElement classElement = element; | |
| 4976 return typeOverridesObjectEquals(classElement); | |
| 4977 } | |
| 4978 | |
| 4979 bool typeOverridesObjectEquals(ClassElement classElement) { | |
| 4980 Element operatorEq = | |
| 4981 lookupOperator(classElement, const SourceString('==')); | |
| 4982 if (operatorEq == null) return false; | |
| 4983 // If the operator== declaration is in Object, it's not overridden. | |
| 4984 return (operatorEq.getEnclosingClass() != compiler.objectClass); | |
| 4985 } | |
| 4986 | |
| 4987 Element lookupOperator(ClassElement classElement, SourceString operatorName) { | 4943 Element lookupOperator(ClassElement classElement, SourceString operatorName) { |
| 4988 SourceString dartMethodName = | 4944 SourceString dartMethodName = |
| 4989 Elements.constructOperatorName(operatorName, false); | 4945 Elements.constructOperatorName(operatorName, false); |
| 4990 return classElement.lookupMember(dartMethodName); | 4946 return classElement.lookupMember(dartMethodName); |
| 4991 } | 4947 } |
| 4992 | 4948 |
| 4993 visitSwitchCase(SwitchCase node) { | 4949 visitSwitchCase(SwitchCase node) { |
| 4994 compiler.internalError('SsaBuilder.visitSwitchCase'); | 4950 compiler.internalError('SsaBuilder.visitSwitchCase'); |
| 4995 } | 4951 } |
| 4996 | 4952 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5619 new HSubGraphBlockInformation(elseBranch.graph)); | 5575 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5620 | 5576 |
| 5621 HBasicBlock conditionStartBlock = conditionBranch.block; | 5577 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5622 conditionStartBlock.setBlockFlow(info, joinBlock); | 5578 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5623 SubGraph conditionGraph = conditionBranch.graph; | 5579 SubGraph conditionGraph = conditionBranch.graph; |
| 5624 HIf branch = conditionGraph.end.last; | 5580 HIf branch = conditionGraph.end.last; |
| 5625 assert(branch is HIf); | 5581 assert(branch is HIf); |
| 5626 branch.blockInformation = conditionStartBlock.blockFlow; | 5582 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5627 } | 5583 } |
| 5628 } | 5584 } |
| OLD | NEW |