| 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); |
| 11 R visitBitNot(HBitNot node); | 11 R visitBitNot(HBitNot node); |
| 12 R visitBitOr(HBitOr node); | 12 R visitBitOr(HBitOr node); |
| 13 R visitBitXor(HBitXor node); | 13 R visitBitXor(HBitXor node); |
| 14 R visitBoolify(HBoolify node); | 14 R visitBoolify(HBoolify node); |
| 15 R visitBoundsCheck(HBoundsCheck node); | 15 R visitBoundsCheck(HBoundsCheck node); |
| 16 R visitBreak(HBreak node); | 16 R visitBreak(HBreak node); |
| 17 R visitConstant(HConstant node); | 17 R visitConstant(HConstant node); |
| 18 R visitContinue(HContinue node); | 18 R visitContinue(HContinue node); |
| 19 R visitDivide(HDivide node); | 19 R visitDivide(HDivide node); |
| 20 R visitEquals(HEquals node); | |
| 21 R visitExit(HExit node); | 20 R visitExit(HExit node); |
| 22 R visitExitTry(HExitTry node); | 21 R visitExitTry(HExitTry node); |
| 23 R visitFieldGet(HFieldGet node); | 22 R visitFieldGet(HFieldGet node); |
| 24 R visitFieldSet(HFieldSet node); | 23 R visitFieldSet(HFieldSet node); |
| 25 R visitForeign(HForeign node); | 24 R visitForeign(HForeign node); |
| 26 R visitForeignNew(HForeignNew node); | 25 R visitForeignNew(HForeignNew node); |
| 27 R visitGoto(HGoto node); | 26 R visitGoto(HGoto node); |
| 28 R visitGreater(HGreater node); | 27 R visitGreater(HGreater node); |
| 29 R visitGreaterEqual(HGreaterEqual node); | 28 R visitGreaterEqual(HGreaterEqual node); |
| 30 R visitIdentity(HIdentity node); | 29 R visitIdentity(HIdentity node); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node); | 255 visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node); |
| 257 visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node); | 256 visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node); |
| 258 visitInvoke(HInvoke node) => visitInstruction(node); | 257 visitInvoke(HInvoke node) => visitInstruction(node); |
| 259 visitInvokeBinary(HInvokeBinary node) => visitInstruction(node); | 258 visitInvokeBinary(HInvokeBinary node) => visitInstruction(node); |
| 260 visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node); | 259 visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node); |
| 261 visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node); | 260 visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node); |
| 262 visitInvokeUnary(HInvokeUnary node) => visitInstruction(node); | 261 visitInvokeUnary(HInvokeUnary node) => visitInstruction(node); |
| 263 visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node); | 262 visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node); |
| 264 visitControlFlow(HControlFlow node) => visitInstruction(node); | 263 visitControlFlow(HControlFlow node) => visitInstruction(node); |
| 265 visitFieldAccess(HFieldAccess node) => visitInstruction(node); | 264 visitFieldAccess(HFieldAccess node) => visitInstruction(node); |
| 266 visitRelational(HRelational node) => visitInvokeStatic(node); | 265 visitRelational(HRelational node) => visitInvokeBinary(node); |
| 267 | 266 |
| 268 visitAdd(HAdd node) => visitBinaryArithmetic(node); | 267 visitAdd(HAdd node) => visitBinaryArithmetic(node); |
| 269 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); | 268 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); |
| 270 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); | 269 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); |
| 271 visitBitNot(HBitNot node) => visitInvokeUnary(node); | 270 visitBitNot(HBitNot node) => visitInvokeUnary(node); |
| 272 visitBitOr(HBitOr node) => visitBinaryBitOp(node); | 271 visitBitOr(HBitOr node) => visitBinaryBitOp(node); |
| 273 visitBitXor(HBitXor node) => visitBinaryBitOp(node); | 272 visitBitXor(HBitXor node) => visitBinaryBitOp(node); |
| 274 visitBoolify(HBoolify node) => visitInstruction(node); | 273 visitBoolify(HBoolify node) => visitInstruction(node); |
| 275 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); | 274 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); |
| 276 visitBreak(HBreak node) => visitJump(node); | 275 visitBreak(HBreak node) => visitJump(node); |
| 277 visitContinue(HContinue node) => visitJump(node); | 276 visitContinue(HContinue node) => visitJump(node); |
| 278 visitCheck(HCheck node) => visitInstruction(node); | 277 visitCheck(HCheck node) => visitInstruction(node); |
| 279 visitConstant(HConstant node) => visitInstruction(node); | 278 visitConstant(HConstant node) => visitInstruction(node); |
| 280 visitDivide(HDivide node) => visitBinaryArithmetic(node); | 279 visitDivide(HDivide node) => visitBinaryArithmetic(node); |
| 281 visitEquals(HEquals node) => visitRelational(node); | |
| 282 visitExit(HExit node) => visitControlFlow(node); | 280 visitExit(HExit node) => visitControlFlow(node); |
| 283 visitExitTry(HExitTry node) => visitControlFlow(node); | 281 visitExitTry(HExitTry node) => visitControlFlow(node); |
| 284 visitFieldGet(HFieldGet node) => visitFieldAccess(node); | 282 visitFieldGet(HFieldGet node) => visitFieldAccess(node); |
| 285 visitFieldSet(HFieldSet node) => visitFieldAccess(node); | 283 visitFieldSet(HFieldSet node) => visitFieldAccess(node); |
| 286 visitForeign(HForeign node) => visitInstruction(node); | 284 visitForeign(HForeign node) => visitInstruction(node); |
| 287 visitForeignNew(HForeignNew node) => visitForeign(node); | 285 visitForeignNew(HForeignNew node) => visitForeign(node); |
| 288 visitGoto(HGoto node) => visitControlFlow(node); | 286 visitGoto(HGoto node) => visitControlFlow(node); |
| 289 visitGreater(HGreater node) => visitRelational(node); | 287 visitGreater(HGreater node) => visitRelational(node); |
| 290 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); | 288 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); |
| 291 visitIdentity(HIdentity node) => visitRelational(node); | 289 visitIdentity(HIdentity node) => visitRelational(node); |
| (...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1542 HForeignNew(this.element, List<HInstruction> inputs) | 1540 HForeignNew(this.element, List<HInstruction> inputs) |
| 1543 : super(const LiteralDartString("new"), | 1541 : super(const LiteralDartString("new"), |
| 1544 const LiteralDartString("Object"), inputs); | 1542 const LiteralDartString("Object"), inputs); |
| 1545 accept(HVisitor visitor) => visitor.visitForeignNew(this); | 1543 accept(HVisitor visitor) => visitor.visitForeignNew(this); |
| 1546 } | 1544 } |
| 1547 | 1545 |
| 1548 abstract class HInvokeBinary extends HInstruction { | 1546 abstract class HInvokeBinary extends HInstruction { |
| 1549 HInvokeBinary(HInstruction left, HInstruction right) | 1547 HInvokeBinary(HInstruction left, HInstruction right) |
| 1550 : super(<HInstruction>[left, right]); | 1548 : super(<HInstruction>[left, right]); |
| 1551 | 1549 |
| 1550 void prepareGvn(HTypeMap types) { |
| 1551 clearAllSideEffects(); |
| 1552 setUseGvn(); |
| 1553 } |
| 1554 |
| 1552 HInstruction get left => inputs[0]; | 1555 HInstruction get left => inputs[0]; |
| 1553 HInstruction get right => inputs[1]; | 1556 HInstruction get right => inputs[1]; |
| 1554 | 1557 |
| 1555 BinaryOperation operation(ConstantSystem constantSystem); | 1558 BinaryOperation operation(ConstantSystem constantSystem); |
| 1556 } | 1559 } |
| 1557 | 1560 |
| 1558 abstract class HBinaryArithmetic extends HInvokeBinary { | 1561 abstract class HBinaryArithmetic extends HInvokeBinary { |
| 1559 HBinaryArithmetic(HInstruction left, HInstruction right) : super(left, right); | 1562 HBinaryArithmetic(HInstruction left, HInstruction right) : super(left, right); |
| 1560 | 1563 |
| 1561 void prepareGvn(HTypeMap types) { | |
| 1562 clearAllSideEffects(); | |
| 1563 setUseGvn(); | |
| 1564 } | |
| 1565 | |
| 1566 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | 1564 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1567 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER; | 1565 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER; |
| 1568 if (left.isDouble(types)) return HType.DOUBLE; | 1566 if (left.isDouble(types)) return HType.DOUBLE; |
| 1569 return HType.NUMBER; | 1567 return HType.NUMBER; |
| 1570 } | 1568 } |
| 1571 | 1569 |
| 1572 BinaryOperation operation(ConstantSystem constantSystem); | 1570 BinaryOperation operation(ConstantSystem constantSystem); |
| 1573 } | 1571 } |
| 1574 | 1572 |
| 1575 class HAdd extends HBinaryArithmetic { | 1573 class HAdd extends HBinaryArithmetic { |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1991 assert(isLogicalOperator()); | 1989 assert(isLogicalOperator()); |
| 1992 if (logicalOperatorType == IS_AND) return "&&"; | 1990 if (logicalOperatorType == IS_AND) return "&&"; |
| 1993 assert(logicalOperatorType == IS_OR); | 1991 assert(logicalOperatorType == IS_OR); |
| 1994 return "||"; | 1992 return "||"; |
| 1995 } | 1993 } |
| 1996 | 1994 |
| 1997 toString() => 'phi'; | 1995 toString() => 'phi'; |
| 1998 accept(HVisitor visitor) => visitor.visitPhi(this); | 1996 accept(HVisitor visitor) => visitor.visitPhi(this); |
| 1999 } | 1997 } |
| 2000 | 1998 |
| 2001 abstract class HRelational extends HInvokeStatic { | 1999 abstract class HRelational extends HInvokeBinary { |
| 2002 bool usesBoolifiedInterceptor = false; | 2000 bool usesBoolifiedInterceptor = false; |
| 2003 HRelational(HStatic target, HInstruction left, HInstruction right) | 2001 HRelational(HInstruction left, HInstruction right) : super(left, right); |
| 2004 : super(<HInstruction>[target, left, right]); | 2002 HType get guaranteedType => HType.BOOLEAN; |
| 2005 | |
| 2006 void prepareGvn(HTypeMap types) { | |
| 2007 clearAllSideEffects(); | |
| 2008 // Relational expressions can take part in global value numbering | |
| 2009 // and do not have any side-effects if we know all the inputs are | |
| 2010 // numbers. This can be improved for at least equality. | |
| 2011 if (isBuiltin(types)) { | |
| 2012 setUseGvn(); | |
| 2013 } else { | |
| 2014 setAllSideEffects(); | |
| 2015 } | |
| 2016 } | |
| 2017 | |
| 2018 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | |
| 2019 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; | |
| 2020 return HType.UNKNOWN; | |
| 2021 } | |
| 2022 | |
| 2023 HType get guaranteedType { | |
| 2024 if (usesBoolifiedInterceptor) return HType.BOOLEAN; | |
| 2025 return HType.UNKNOWN; | |
| 2026 } | |
| 2027 | |
| 2028 HType computeDesiredTypeForNonTargetInput(HInstruction input, | |
| 2029 HTypeMap types, | |
| 2030 Compiler compiler) { | |
| 2031 HType propagatedType = types[this]; | |
| 2032 // For all relational operations except HEquals, we expect to get numbers | |
| 2033 // only. With numbers the outgoing type is a boolean. If something else | |
| 2034 // is desired, then numbers are incorrect, though. | |
| 2035 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { | |
| 2036 if (left.isTypeUnknown(types) || left.isNumber(types)) { | |
| 2037 return HType.NUMBER; | |
| 2038 } | |
| 2039 } | |
| 2040 return HType.UNKNOWN; | |
| 2041 } | |
| 2042 | |
| 2043 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.BOOLEAN; | |
| 2044 | |
| 2045 bool isBuiltin(HTypeMap types) | |
| 2046 => left.isNumber(types) && right.isNumber(types); | |
| 2047 | |
| 2048 HInstruction get left => inputs[1]; | |
| 2049 HInstruction get right => inputs[2]; | |
| 2050 | |
| 2051 BinaryOperation operation(ConstantSystem constantSystem); | |
| 2052 } | |
| 2053 | |
| 2054 class HEquals extends HRelational { | |
| 2055 HEquals(HStatic target, HInstruction left, HInstruction right) | |
| 2056 : super(target, left, right); | |
| 2057 accept(HVisitor visitor) => visitor.visitEquals(this); | |
| 2058 | |
| 2059 bool isBuiltin(HTypeMap types) { | |
| 2060 // All primitive types have 'identical' semantics. | |
| 2061 // Note that this includes all constants except the user-constructed | |
| 2062 // objects. | |
| 2063 return types[left].isPrimitiveOrNull() || right.isConstantNull(); | |
| 2064 } | |
| 2065 | |
| 2066 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | |
| 2067 if (isBuiltin(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; | |
| 2068 return HType.UNKNOWN; | |
| 2069 } | |
| 2070 | |
| 2071 HType computeDesiredTypeForNonTargetInput(HInstruction input, | |
| 2072 HTypeMap types, | |
| 2073 Compiler compiler) { | |
| 2074 HType propagatedType = types[this]; | |
| 2075 if (input == left && types[right].isUseful()) { | |
| 2076 // All our useful types have 'identical' semantics. But we don't want to | |
| 2077 // speculatively test for all possible types. Therefore we try to match | |
| 2078 // the two types. That is, if we see x == 3, then we speculatively test | |
| 2079 // if x is a number and bailout if it isn't. | |
| 2080 // If right is a number we don't need more than a number (no need to match | |
| 2081 // the exact type of right). | |
| 2082 if (right.isNumber(types)) return HType.NUMBER; | |
| 2083 return types[right]; | |
| 2084 } | |
| 2085 // String equality testing is much more common than array equality testing. | |
| 2086 if (input == left && left.isIndexablePrimitive(types)) { | |
| 2087 return HType.READABLE_ARRAY; | |
| 2088 } | |
| 2089 // String equality testing is much more common than array equality testing. | |
| 2090 if (input == right && right.isIndexablePrimitive(types)) { | |
| 2091 return HType.STRING; | |
| 2092 } | |
| 2093 return HType.UNKNOWN; | |
| 2094 } | |
| 2095 | |
| 2096 BinaryOperation operation(ConstantSystem constantSystem) | |
| 2097 => constantSystem.equal; | |
| 2098 int typeCode() => HInstruction.EQUALS_TYPECODE; | |
| 2099 bool typeEquals(other) => other is HEquals; | |
| 2100 bool dataEquals(HInstruction other) => true; | |
| 2101 } | 2003 } |
| 2102 | 2004 |
| 2103 class HIdentity extends HRelational { | 2005 class HIdentity extends HRelational { |
| 2104 HIdentity(HStatic target, HInstruction left, HInstruction right) | 2006 HIdentity(HInstruction left, HInstruction right) : super(left, right); |
| 2105 : super(target, left, right); | |
| 2106 accept(HVisitor visitor) => visitor.visitIdentity(this); | 2007 accept(HVisitor visitor) => visitor.visitIdentity(this); |
| 2107 | 2008 |
| 2108 bool isBuiltin(HTypeMap types) => true; | |
| 2109 | |
| 2110 HType get guaranteedType => HType.BOOLEAN; | |
| 2111 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) | |
| 2112 => HType.BOOLEAN; | |
| 2113 // Note that the identity operator really does not care for its input types. | |
| 2114 HType computeDesiredTypeForInput(HInstruction input, | |
| 2115 HTypeMap types, | |
| 2116 Compiler compiler) { | |
| 2117 return HType.UNKNOWN; | |
| 2118 } | |
| 2119 | |
| 2120 BinaryOperation operation(ConstantSystem constantSystem) | 2009 BinaryOperation operation(ConstantSystem constantSystem) |
| 2121 => constantSystem.identity; | 2010 => constantSystem.identity; |
| 2122 int typeCode() => HInstruction.IDENTITY_TYPECODE; | 2011 int typeCode() => HInstruction.IDENTITY_TYPECODE; |
| 2123 bool typeEquals(other) => other is HIdentity; | 2012 bool typeEquals(other) => other is HIdentity; |
| 2124 bool dataEquals(HInstruction other) => true; | 2013 bool dataEquals(HInstruction other) => true; |
| 2125 } | 2014 } |
| 2126 | 2015 |
| 2127 class HGreater extends HRelational { | 2016 class HGreater extends HRelational { |
| 2128 HGreater(HStatic target, HInstruction left, HInstruction right) | 2017 HGreater(HInstruction left, HInstruction right) : super(left, right); |
| 2129 : super(target, left, right); | |
| 2130 accept(HVisitor visitor) => visitor.visitGreater(this); | 2018 accept(HVisitor visitor) => visitor.visitGreater(this); |
| 2131 | 2019 |
| 2132 BinaryOperation operation(ConstantSystem constantSystem) | 2020 BinaryOperation operation(ConstantSystem constantSystem) |
| 2133 => constantSystem.greater; | 2021 => constantSystem.greater; |
| 2134 int typeCode() => HInstruction.GREATER_TYPECODE; | 2022 int typeCode() => HInstruction.GREATER_TYPECODE; |
| 2135 bool typeEquals(other) => other is HGreater; | 2023 bool typeEquals(other) => other is HGreater; |
| 2136 bool dataEquals(HInstruction other) => true; | 2024 bool dataEquals(HInstruction other) => true; |
| 2137 } | 2025 } |
| 2138 | 2026 |
| 2139 class HGreaterEqual extends HRelational { | 2027 class HGreaterEqual extends HRelational { |
| 2140 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) | 2028 HGreaterEqual(HInstruction left, HInstruction right) : super(left, right); |
| 2141 : super(target, left, right); | |
| 2142 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); | 2029 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); |
| 2143 | 2030 |
| 2144 BinaryOperation operation(ConstantSystem constantSystem) | 2031 BinaryOperation operation(ConstantSystem constantSystem) |
| 2145 => constantSystem.greaterEqual; | 2032 => constantSystem.greaterEqual; |
| 2146 int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE; | 2033 int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE; |
| 2147 bool typeEquals(other) => other is HGreaterEqual; | 2034 bool typeEquals(other) => other is HGreaterEqual; |
| 2148 bool dataEquals(HInstruction other) => true; | 2035 bool dataEquals(HInstruction other) => true; |
| 2149 } | 2036 } |
| 2150 | 2037 |
| 2151 class HLess extends HRelational { | 2038 class HLess extends HRelational { |
| 2152 HLess(HStatic target, HInstruction left, HInstruction right) | 2039 HLess(HInstruction left, HInstruction right) : super(left, right); |
| 2153 : super(target, left, right); | |
| 2154 accept(HVisitor visitor) => visitor.visitLess(this); | 2040 accept(HVisitor visitor) => visitor.visitLess(this); |
| 2155 | 2041 |
| 2156 BinaryOperation operation(ConstantSystem constantSystem) | 2042 BinaryOperation operation(ConstantSystem constantSystem) |
| 2157 => constantSystem.less; | 2043 => constantSystem.less; |
| 2158 int typeCode() => HInstruction.LESS_TYPECODE; | 2044 int typeCode() => HInstruction.LESS_TYPECODE; |
| 2159 bool typeEquals(other) => other is HLess; | 2045 bool typeEquals(other) => other is HLess; |
| 2160 bool dataEquals(HInstruction other) => true; | 2046 bool dataEquals(HInstruction other) => true; |
| 2161 } | 2047 } |
| 2162 | 2048 |
| 2163 class HLessEqual extends HRelational { | 2049 class HLessEqual extends HRelational { |
| 2164 HLessEqual(HStatic target, HInstruction left, HInstruction right) | 2050 HLessEqual(HInstruction left, HInstruction right) : super(left, right); |
| 2165 : super(target, left, right); | |
| 2166 accept(HVisitor visitor) => visitor.visitLessEqual(this); | 2051 accept(HVisitor visitor) => visitor.visitLessEqual(this); |
| 2167 | 2052 |
| 2168 BinaryOperation operation(ConstantSystem constantSystem) | 2053 BinaryOperation operation(ConstantSystem constantSystem) |
| 2169 => constantSystem.lessEqual; | 2054 => constantSystem.lessEqual; |
| 2170 int typeCode() => HInstruction.LESS_EQUAL_TYPECODE; | 2055 int typeCode() => HInstruction.LESS_EQUAL_TYPECODE; |
| 2171 bool typeEquals(other) => other is HLessEqual; | 2056 bool typeEquals(other) => other is HLessEqual; |
| 2172 bool dataEquals(HInstruction other) => true; | 2057 bool dataEquals(HInstruction other) => true; |
| 2173 } | 2058 } |
| 2174 | 2059 |
| 2175 class HReturn extends HControlFlow { | 2060 class HReturn extends HControlFlow { |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2752 HBasicBlock get start => expression.start; | 2637 HBasicBlock get start => expression.start; |
| 2753 HBasicBlock get end { | 2638 HBasicBlock get end { |
| 2754 // We don't create a switch block if there are no cases. | 2639 // We don't create a switch block if there are no cases. |
| 2755 assert(!statements.isEmpty); | 2640 assert(!statements.isEmpty); |
| 2756 return statements.last.end; | 2641 return statements.last.end; |
| 2757 } | 2642 } |
| 2758 | 2643 |
| 2759 bool accept(HStatementInformationVisitor visitor) => | 2644 bool accept(HStatementInformationVisitor visitor) => |
| 2760 visitor.visitSwitchInfo(this); | 2645 visitor.visitSwitchInfo(this); |
| 2761 } | 2646 } |
| OLD | NEW |