| 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 OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 HInstruction get zapInstruction { | 994 HInstruction get zapInstruction { |
| 995 if (zapInstructionCache == null) { | 995 if (zapInstructionCache == null) { |
| 996 // A constant with no type does not pollute types at phi nodes. | 996 // A constant with no type does not pollute types at phi nodes. |
| 997 ConstantValue constant = | 997 ConstantValue constant = |
| 998 new DummyConstantValue(const TypeMask.nonNullEmpty()); | 998 new DummyConstantValue(const TypeMask.nonNullEmpty()); |
| 999 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); | 999 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); |
| 1000 } | 1000 } |
| 1001 return zapInstructionCache; | 1001 return zapInstructionCache; |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 /// Returns true of [foreign] will throw an noSuchMethod error if | |
| 1005 /// receiver is `null` before having any other side-effects. | |
| 1006 bool templateThrowsNSMonNull(HForeignCode foreign, HInstruction receiver) { | |
| 1007 // We look for a template of the form | |
| 1008 // | |
| 1009 // #.something -or- #.something() | |
| 1010 // | |
| 1011 // where # is substituted by receiver. | |
| 1012 js.Template template = foreign.codeTemplate; | |
| 1013 js.Node node = template.ast; | |
| 1014 // #.something = ... | |
| 1015 if (node is js.Assignment) { | |
| 1016 js.Assignment assignment = node; | |
| 1017 node = assignment.leftHandSide; | |
| 1018 } | |
| 1019 | |
| 1020 // #.something | |
| 1021 if (node is js.PropertyAccess) { | |
| 1022 js.PropertyAccess access = node; | |
| 1023 if (access.receiver is js.InterpolatedExpression) { | |
| 1024 js.InterpolatedExpression hole = access.receiver; | |
| 1025 return hole.isPositional && foreign.inputs.first == receiver; | |
| 1026 } | |
| 1027 } | |
| 1028 return false; | |
| 1029 } | |
| 1030 | |
| 1031 /// Returns whether the next throwing instruction that may have side | 1004 /// Returns whether the next throwing instruction that may have side |
| 1032 /// effects after [instruction], throws [NoSuchMethodError] on the | 1005 /// effects after [instruction], throws [NoSuchMethodError] on the |
| 1033 /// same receiver of [instruction]. | 1006 /// same receiver of [instruction]. |
| 1034 bool hasFollowingThrowingNSM(HInstruction instruction) { | 1007 bool hasFollowingThrowingNSM(HInstruction instruction) { |
| 1035 HInstruction receiver = instruction.getDartReceiver(compiler); | 1008 HInstruction receiver = instruction.getDartReceiver(compiler); |
| 1036 HInstruction current = instruction.next; | 1009 HInstruction current = instruction.next; |
| 1037 do { | 1010 do { |
| 1038 if ((current.getDartReceiver(compiler) == receiver) | 1011 if ((current.getDartReceiver(compiler) == receiver) |
| 1039 && current.canThrow()) { | 1012 && current.canThrow()) { |
| 1040 return true; | 1013 return true; |
| 1041 } | 1014 } |
| 1042 if (current is HForeignCode && templateThrowsNSM(current, receiver)) { | |
| 1043 return true; | |
| 1044 } | |
| 1045 if (current.canThrow() || current.sideEffects.hasSideEffects()) { | 1015 if (current.canThrow() || current.sideEffects.hasSideEffects()) { |
| 1046 return false; | 1016 return false; |
| 1047 } | 1017 } |
| 1048 HInstruction next = current.next; | 1018 HInstruction next = current.next; |
| 1049 if (next == null) { | 1019 if (next == null) { |
| 1050 // We do not merge blocks in our SSA graph, so if this block just jumps | 1020 // We do not merge blocks in our SSA graph, so if this block just jumps |
| 1051 // to a single successor, visit the successor, avoiding back-edges. | 1021 // to a single successor, visit the successor, avoiding back-edges. |
| 1052 HBasicBlock successor; | 1022 HBasicBlock successor; |
| 1053 if (current is HGoto) { | 1023 if (current is HGoto) { |
| 1054 successor = current.block.successors.single; | 1024 successor = current.block.successors.single; |
| (...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 | 2205 |
| 2236 keyedValues.forEach((receiver, values) { | 2206 keyedValues.forEach((receiver, values) { |
| 2237 result.keyedValues[receiver] = | 2207 result.keyedValues[receiver] = |
| 2238 new Map<HInstruction, HInstruction>.from(values); | 2208 new Map<HInstruction, HInstruction>.from(values); |
| 2239 }); | 2209 }); |
| 2240 | 2210 |
| 2241 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2211 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2242 return result; | 2212 return result; |
| 2243 } | 2213 } |
| 2244 } | 2214 } |
| OLD | NEW |